Rails: получение данных из таблицы для каждой итерации цикла
У меня есть цикл (для элемента в @dataset), и я хочу на каждой итерации получить разные данные из другой таблицы и сделать некоторые операции, которые будут напечатаны в представлении. Я не могу получить эти данные из набора данных, используемого в цикле.
Как я могу это сделать в соответствии с MVC? Я могу поместить код в цикл, в представлении, но я думаю, что это ужасно.
Должен ли я использовать помощник для этого и вызывать функцию из представления?
Заранее спасибо,
- ARemesal
Ответы
Ответ 1
Если у вас есть одна таблица и вы хотите получить данные из другой таблицы, обычно она находится в состоянии отношения has_many
. Например, у нас есть модель @people
(Person
), и каждый человек has_many
адресует (Address
модель). В этих случаях лучше всего это сделать
# Controller
@people = Person.find(:all, :include => :addresses)
...
# View
@people.each do |p|
p.addresses.each do |address|
...
Если ваши данные - это не просто обычные таблицы базы данных (возможно, вы получаете их из веб-службы или так далее), тогда хорошо сделать это, чтобы собрать все данные в контроллере досрочно, а затем передать это к виду. Что-то вроде этого
# Controller
@people = Person.find(:all)
@people.each do |p|
# attach loaded data to the person object in controller
p.addresses = Address.load_from_somewhere_by_name(p.name)
...
Таким образом, код представления остается чистым, например:
# View
@people.each do |p|
p.addresses.each do |address|
...
Ответ 2
Трудно сказать о наилучшем решении вашей проблемы без подробностей о данных и отношениях между вашими моделями (таблицами). Общая идея следующая: держите свои взгляды глупыми. Получите все данные, необходимые для визуализации представления внутри действия ваших контроллеров. Внесите все изменения и вычисления внутри одного действия. Затем используйте эти данные.
btw, если вы говорите о проблеме N + 1, то читайте больше о параметрах "include" и "join" ActiveRecord.
Ответ 3
Если бы я был вами, я бы создал отдельный класс, который инкапсулирует набор данных и содержит всю логику, связанную с обработкой записей набора данных. Этот класс может быть итерируемым (отвечать каждому). Затем я передам экземпляр этого класса в представление и использую там только его методы.
Ответ 4
Person(id, name, other fields...)
Event(id, title, ...)
Date(id, date, time, event_id, ...)
Disponibility(id, percent, date_id, person_id, ...)
Конечно, все отношения определены в Модели.
У меня есть представление, которое показывает все даты для события, это легко. Но я хочу, чтобы на каждую дату печатать данные для всех людей, которые доступны для этой даты. На мой взгляд, забыв о шаблоне проектирования MVC, я мог бы написать что-то вроде этого:
<% for date in @Dates
available = Disponibility.find_by_date_id(date.id)
for item in available
guy = Person.find_by_id(item.person_id)
%>
Укажите дату и доступные люди...
Я хочу избежать этого в представлении. Я думаю, что ответ Ориона Эдвардса близок к тому, что мне нужно, но в этом примере адрес - пустое поле для таблицы Person? Или как добавить новый атрибут в класс Person?
Хотя, я пропустил какой-либо трюк SQL для этого?
Ответ 5
- Храните всю логику в элементе @dataset внутри действия контроллера.
- Использовать методы в ваших моделях для взаимодействия с другими объектами модели, которые вам нужны.
- Вам нужно оставить только @dataset для вашего представления, которое вы можете сделать частичным.
Вам нужно будет еще больше объяснить вашу ситуацию, чтобы ответить на этот вопрос. С какими операциями и другими моделями вам нужно взаимодействовать? Если вы опубликуете свои ассоциации моделей, я уверен, что мы действительно можем вас отделить.
Удачи!