#ruby-on-rails #ruby
#ruby-на-рельсах #ruby #ruby-on-rails
Вопрос:
У меня есть следующие модели: пользователь имеет множество целей, Цель имеет множество задач, задача имеет множество day_tasks. Я пытаюсь написать метод, который находит все day_tasks, которые
- принадлежит определенному пользователю
- есть
:target_date == Date.today
(target_date — это столбец в таблице day_tasks).
Я хочу поместить результаты в массив @day_tasks.
мой код:
@user = current_user
@day_tasks = DayTask.find { |x| x.task.goal.user == @user amp;amp; x.target_date == Date.today }
Этот код возвращает только первую запись, соответствующую этим критериям. Я также пробовал использовать DayTasks.где метод с тем же кодом в фигурных скобках, но у меня просто ошибка «Неправильное количество аргументов (0 для 1)». Может ли кто-нибудь объяснить, почему мой метод возвращает только первое вхождение и в чем именно разница.найти и .где?
Комментарии:
1. Я не использую rails, но предполагается, что обычный ruby
find
возвращает первый найденный элемент, в то времяfind_all
как возвращает все из них, возможно, стоит попробовать, еслиfind_all
работает в вашем случае.2. @derp Я попытался использовать find_all, но получил ошибку неопределенного метода. Запустил DayTask.response_to? :find_all и, конечно же, вернул false …
3. @derp:
find_all
устарел в Rails 3, заменен наfind(:all)
. Лучшим решением является использованиеwhere
, как показано в моем ответе.4. Спасибо, Райан, я еще не изучал Rails, но подумал, что, возможно, стоит попробовать.
Ответ №1:
Вы написали это:
@day_tasks = DayTask.find { |x| x.task.goal.user == @user amp;amp; x.target_date == Date.today }
find
Метод здесь фактически возвращается к Enumerable
‘s find
, который является псевдонимом for detect
, который принимает блок и возвращает первый элемент в этой коллекции, который соответствует условиям блока или будет возвращен nil
.
Чтобы исправить это, вам нужно будет использовать материал запросов ARel, встроенный в ActiveRecord.
DayTask.joins(:task => { :goals => :user }).where("users.id = ? AND day_tasks.target_date = ?", @user.id, Date.today)
Приведенный joins
здесь метод будет объединять таблицы, которые соответствуют именам ассоциаций в вашей DayTask
модели и связанных моделях. Это означает, что у вас должна быть task
ассоциация с DayTask
моделью, и для этой модели есть goals
ассоциация, а для модели целей есть одна user
.
Затем where
будет создано условие SQL, которое будет запрашивать объединения, чтобы найти все записи, принадлежащие пользователю и имеющие target_date
значение на сегодняшний день.
Комментарии:
1. Очень информативно, спасибо за это объяснение! Хотя прямо сейчас я просто пытаюсь заставить этот метод работать, я рассмотрю правильный способ сделать это позже.
2. @Grant: этот способ — это способ заставить его работать и правильный способ.
3. В качестве небольшого улучшения предложение where должно работать просто как where(:target_date => Date.today, :goals => {:user => current_user}) . Я думаю, нет необходимости переходить на SQL.
Ответ №2:
пожалуйста, проверьте интерфейс запроса ActiveRecord для Rails 3.x :
http://m.onkey.org/active-record-query-interface
http://guides.rubyonrails.org/active_record_querying.html
вероятно, вам понадобится find(:all, …) или where()
Комментарии:
1. Спасибо за ссылки, они очень пригодятся в будущем!
2. извините.. это была опечатка с моей стороны … 😛
3. Пожалуйста, добавьте соответствующую информацию в свой ответ.