Rails - 检查 has_many 关联中的记录是否存在

29

我不确定我的问题是否表达正确。

我有三个模型: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语句。但是这里有一个问题,用户项目具有枚举状态:[: pending,approved]。因此,我需要查看current_user是否拥有特定的:pending项目。

例如,当用户访问item1的视图页面时,我希望在item_controller的show操作中声明@item = Item.find_by_id(params[:id])。但是,我如何使用此@item来查看用户是否拥有此项目呢?

4个回答

46

尝试:

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

7

延续@lei-liu的回答。可以通过以下方式判断记录是否存在: current_user.items.exists?(params[:id])

同时,exists?允许筛选除了id以外的列,并且还允许更复杂的条件,例如下面的操作:

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

0
但是我该如何使用这个@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

这不是为了复制粘贴而写的,而是为了展示如何编写和使用模型方法以及如何使用待处理的枚举器。考虑到uniq的限制,select调用有些浪费,但其他人已经展示了如何检查某个东西是否存在。@AndreyDeineko没有提供任何有价值的东西,只是在恶意攻击。 - tkz79
1
  1. 你不需要使用 self
  2. select会在评估块之前将整个待处理的 user_items 集合加载到内存中,因此,如果集合中有大量记录,可能会超出内存限制。
  3. 在这种情况下,你不需要使用 return
  4. 你可以直接使用 user_items.pending.select {|s| s.user == user}.count > 0,它已经返回了布尔值。
  5. 对于我第一条评论的形式感到抱歉 - 当时正好是早上 - 再次道歉。
- Andrey Deineko
@AndreyDeineko,您提到了一种“传统”的解决方案。那是什么? - user4584963
@user4584963,通过“非常规”我指的是这里错误使用了return关键字。 - Andrey Deineko
@AndreyDeineko - 1+2 - 我认为这是减少内存需求的好方法 - 我们应该只获取该项的用户物品,仅获取那些处于待处理状态的物品...我不知道self是不必要的!! 3) 返回习惯来自于我多年前学习计算机科学时的C语言 - 在停止编程十多年之前。 4) 想要为他设置更复杂的功能 - 对于这种情况达成一致!5) 一切都好...感谢您回来澄清!总是热衷于学习更好的方法! - tkz79

-1

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? 
  ...

1
我相信枚举类型会自动添加作用域。 - user4584963
我认为你不需要一个计数查询。如果你只是想检查是否存在,使用.exists?会给你一个SELECT ... LIMIT 1,一旦找到匹配项就会停止。 - drewish

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接