6

I have a set of resources called Tasks and Posts and there are in a has_and_belongs_to_many (HABTM) relationship with each other.

There is also a join table connecting their values.

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

So my question is how do I check to see if the id of a specific task exists within the array created from @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
    ">]

So my question is whats the ruby way for writing does "@task = Task.find(2)" exist within @post.tasks and if so return true or false?

ChrisWesAllen
  • 4,935
  • 18
  • 58
  • 83

4 Answers4

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

Is much lighter compared to what Gabelsman has suggested.

Chirantan
  • 15,304
  • 8
  • 49
  • 75
10
@post.tasks.map(&:id).include?(task_id)

Where task_id is the id of the task you want to check. To explain this a little bit, you're taking the list of tasks, mapping them to an array of their ids, and then checking to see if the id in question is in that array. If you're not familiar with map you should check it out, it's awesome.

ruby-docs

GabeIsman
  • 821
  • 7
  • 9
  • Just want to point out that this is not necessarily the best answer. The right way to do this will depend on what data you have already loaded, and what future questions you intend to ask of it. Database queries are expensive! Minimize them. – GabeIsman Apr 14 '15 at 22:32
3

Assuming you named your has_and_belongs_to_many to :posts then doing something like this in Rails is very optimized:

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

I noticed that the two answer provided here result in n select statements. But doing it with task_ids caches the first query and the rest does not require a SELECT statement from the DB.

Amir Raminfar
  • 33,777
  • 7
  • 93
  • 123
2

You can use exists? method for that:

@post.tasks.exists?(id: task_id)
Alexander Karmes
  • 2,438
  • 1
  • 28
  • 34