Ruby / Rails — проверяет, существует ли дочерний идентификатор в записи отношения HABTM

#ruby-on-rails #ruby #has-and-belongs-to-many

#ruby-on-rails #ruby #имеет-и-принадлежит-многим

Вопрос:

У меня есть набор ресурсов, называемых Tasks и Posts, и они находятся в отношениях has_and_belongs_to_many (HABTM) друг с другом.

Существует также таблица соединений, соединяющая их значения.

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

Итак, мой вопрос в том, как мне проверить, существует ли идентификатор конкретной задачи в массиве, созданном из @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
    ">]
  

Итак, мой вопрос в том, каков способ ruby для записи, существует ли «@task = Task.find (2)» в @post.tasks, и если да, возвращает true или false?

Ответ №1:

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

Намного легче по сравнению с тем, что предложил Габельсман.

Комментарии:

1. Это создает n запросы, если вы проверяете n задачи. Но все же лучше, чем принятый ответ.

2. Это не обязательно. Вы можете передать массив task_ids .

Ответ №2:

 @post.tasks.map(amp;:id).include?(task_id)
  

Где task_id идентификатор задачи, которую вы хотите проверить. Чтобы немного объяснить это, вы берете список задач, сопоставляете их с массивом их идентификаторов, а затем проверяете, есть ли соответствующий идентификатор в этом массиве. Если вы не знакомы с map ним, вы должны проверить это, это потрясающе.

ruby-docs

Комментарии:

1. Просто хочу отметить, что это не обязательно лучший ответ. Правильный способ сделать это будет зависеть от того, какие данные вы уже загрузили, и какие будущие вопросы вы собираетесь задать. Запросы к базе данных стоят дорого! Сверните их.

Ответ №3:

Предполагая, что вы назвали свой has_and_belongs_to_many to :posts , то выполнение чего-то подобного в Rails очень оптимизировано:

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

Я заметил, что два ответа, приведенные здесь, приводят к n операторам выбора. Но выполнение этого с task_ids кэшированием первого запроса, а остальные не требуют SELECT запроса из базы данных.

Ответ №4:

Вы можете использовать exists?метод для этого:

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