【问题标题】:Rails - check if record exists in has_many associationRails - 检查 has_many 关联中是否存在记录
【发布时间】:2016-04-08 02:36:28
【问题描述】:

我不确定我的问题措辞是否正确。

我有三个模型:UserItemUserItem

user has_many :user_items
user has_many :items, through :user_items

item has_many :user_items
item has_many :users -> {uniq}, through :user_items
item belongs_to :user

user_item belongs_to :user
user_item belongs_to :item

我需要一种方法来查看用户是否有要在我的项目视图中创建 if 语句的项目但这里有一个问题,user_items 有 enum status: [ :pending, approved]。所以我需要看看current_user 是否有某个:pending 项。

例如,当用户访问 item1 的查看页面时,我将 item_controller 的显示操作声明为 @item = Item.find_by_id(params[:id])。但是我可以用这个@item 做什么来查看用户是否有这个项目?

【问题讨论】:

    标签: ruby-on-rails activerecord associations has-many


    【解决方案1】:

    试试:

    current_user.items.exists?(params[:id])
    

    或者

    current_user.items.exists?(@item.id)
    

    【讨论】:

      【解决方案2】:

      在这里扩展@lei-liu 的答案。可以通过:current_user.items.exists?(params[:id])

      查找该记录是否存在于众多记录中

      同时,exists? 允许过滤除id 之外的列,也允许更复杂的条件,如下所示:

      current_user.items.exists?('id > 3')
      current_user.items.exists?(name: 'some_name')
      

      【讨论】:

        【解决方案3】:

        但是我可以用这个@item 做什么来查看用户是否有这个项目?

        我认为您在这里缺少的是模型方法。例如,如果您在 Item 模型中添加了一个名为 belongs_to_user_in_pending_state 的方法,您就可以在任何需要的地方调用@item.belongs_to_user_in_pending_state(current_user)

        def belongs_to_user_in_pending_state(user)
          if self.user_items.pending.select {|s| s.user == user}.count > 0 
            return true
          else
            return false
          end
        end
        

        【讨论】:

        • 这不是为了复制和粘贴而编写的,它是作为示例编写的,以向 OP 展示如何编写和使用模型方法......以及如何使用他的未决枚举器。鉴于 uniq 限制,select 调用有点浪费,但其他人已经展示了如何检查是否存在。在不提供任何有价值的东西的情况下仇恨的方式@AndreyDeineko。
        • 1) 你不需要self。 2) select 会在评估块之前将整个待处理的 user_items 集合加载到内存中,因此,如果有大量记录在集合中,它可能会压倒内存。 3) 在这种情况下,您不需要return。 4)你可以离开user_items.pending.select {|s| s.user == user}.count > 0,因为它已经返回布尔值。 5) 很抱歉我的第一条评论的形式 - 那是早上 - 道歉
        • @AndreyDeineko 你提到了一种“传统”的方式来实现这一点。那会是什么?
        • @user4584963 非常规我的意思是这里错误地使用了return 关键字。
        • @AndreyDeineko - 1+2 - 我认为这是减少内存需求的好方法 - 我们应该只获取该项目的 user_items,并且只有那些待处理的......我不知道自己没必要!! 3)当我多年前学习comp sci时,回归习惯来自C - 在十多年前退出编程。 4) 正在考虑为他设置更复杂的功能 - 同意这种情况! 5)一切都好...感谢您回来澄清!始终热衷于学习更好的方法!
        【解决方案4】:

        1) 为 User_item 类添加范围

        scope :pending, -> {where status: 'pending'}
        

        2) 在 Item 类的实例方法中使用该范围:

        def is_pending_with_someone?
          self.user_items.pending.count > 0
        end
        

        然后就可以使用了

        if @item.is_pending_with_someone? 
          ...
        

        【讨论】:

        • 我相信枚举会自动添加范围
        • 我认为您不需要计数查询。如果您只是使用.exists? 检查是否存在,则会给您一个SELECT ... LIMIT 1,一旦找到匹配项就会停止。
        猜你喜欢
        • 2012-05-30
        • 1970-01-01
        • 2011-12-04
        • 1970-01-01
        • 2011-02-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-12-10
        相关资源
        最近更新 更多