2011-10-18 34 views
4

我有一组称为任务和帖子的资源,并且存在has_and_belongs_to_many(HABTM)关系。Ruby/Rails - 检查子对象是否存在于HABTM关系记录中

还有一个连接表连接它们的值。

create_table 'posts_tasks', :id => false do |t| 
    t.column :post_id, :integer 
    t.column :task_id, :integer 
end 

所以我的问题是如何检查特定任务的ID是否存在于从@ post.tasks创建的数组中?

irb(main):011:0> @post = Post.find(1) 
=> #<Post id: 2, comment: "blah blah", created_at: "2011-10-18 03:40:30", updated_at: 
irb(main):012:0> @post.tasks 
=> [#<Task id: 1, description: "Test 1", created_at: "2011-10-18 03: 
    22:05", updated_at: "2011-10-18 03:22:05">, #<Task id: 3, description: "Test 3", 
    created_at: "2011-10-18 03:22:21", updated_at: "2011-10-18 03:22:21 
    ">] 

所以我的问题是什么写作的红宝石的方式做“@task = Task.find(2)”内部存在@ post.tasks如果这样返回true或false?

回答

8
​​

其中task_id是您要检查的任务的ID。为了解释这一点,你需要获取任务列表,将它们映射到它们的ID的数组,然后检查所查询的ID是否在该数组中。如果你不熟悉map你应该检查出来,这很棒。

ruby-docs

+0

只是想指出,这不一定是最好的答案。做到这一点的正确方法取决于你已经加载的数据以及你打算询问的未来问题。数据库查询很贵!尽量减少它们。 – GabeIsman

11
@post.tasks.where(:id => task_id).present? 

相比有什么Gabelsman曾建议要轻得多。

+1

这使得'n'查询你是否正在检查'n'任务。但仍然比接受的答案更好。 –

+1

它不是必须的。你可以传递一个'task_ids'数组。 – Chirantan

3

假设你命名你的has_and_belongs_to_many:posts然后做这样的事情在Rails中非常优化:

@post.task_ids.include?(task.id)

我注意到,这里提供的两个答案导致n select语句。但是用task_ids缓存第一个查询,其余的不需要DB中的SELECT语句。

1

可以使用exists?方法为:

@post.tasks.exists?(id: task_id)