#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
ним, вы должны проверить это, это потрясающе.
Комментарии:
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)