Как создать двойную вложенную модель с изюминкой в Rails 3?
Я создаю регистрацию, где у меня есть модели "Персона", "Ребенок" и "Питание". Человек может иметь много детей и может зарегистрировать много блюд для себя, а также много блюд для детей.
Дело в том, что блюда принадлежат только человеку (нет смысла назначать их детям), поэтому у меня есть одна часть творения для питания в форме, а также другое творение под детьми.
Когда я отправляю форму, я получаю сообщение " Не удается массово назначить защищенные атрибуты: ошибка питания" в контроллере пользователя.
Вопрос в том, как я могу создать экземпляры Meals в разделе Children fields_for, не получая эту ошибку и не устанавливая связь между Meals и Children?
Вот моя модель Персона
class Person < ActiveRecord::Base
has_many :meals
has_many :registrations, :dependent => :destroy
has_many :programs, :through => :registrations
has_many :children
attr_accessible :email_address, :first_name, :home_country, :payment, :phone_number, :price_category, :price_method, :reference_number, :second_name, :meals_attributes, :registrations_attributes, :children_attributes
validate :first_name, :second_name, :home_country, :email_address, :payment, :price_method, :presence => true
accepts_nested_attributes_for :meals, :allow_destroy => true, :reject_if => proc { |attributes| attributes['meal_type'].blank? }
accepts_nested_attributes_for :registrations, :allow_destroy => true
accepts_nested_attributes_for :children, :allow_destroy => true
Моя модель еды
class Meal < ActiveRecord::Base
attr_accessible :food_type, :meal_date, :meal_type, :person_id, :meal_id
validate :food_type, :meal_date, :meal_type, :presence => true
belongs_to :person
end
Новая часть моего контроллера Person
def new
@person = Person.new
meal = @person.meals.build
@meal_dates = ["2013-07-09","2013-07-10","2013-07-11","2013-07-12","2013-07-13","2013-07-14"]
registration = @person.registrations.build
child = @person.children.build
@programs = Program.all
respond_to do |format|
format.html # new.html.erb
format.json { render json: @person }
end
Это детская часть главной формы
<h2>Children</h2>
<%= f.fields_for :children do |builder| %>
<%= render "child_fields", :f => builder %>
<% end %>
<%= link_to_add_fields 'Add Children', f, :children %>
А ребенок поля с едой
<fieldset>
<div class="field">
<%= f.label :name %><br />
<%= f.text_field :name %>
</div>
<div class="field">
<%= f.label :age %><br />
<%= f.number_field :age %>
</div>
<div class="field">
<%= f.label :language %><br />
<%= f.text_field :language %>
</div>
<div class="field">
<%= f.label :child_care %><br />
<%= f.check_box :child_care %>
</div>
<h3>Child's meals</h3>
<table>
<tr>
<th>Date</th>
<th>Food type</th>
<th>Meal type</th>
</tr>
<% @meal_dates.each do |meal_date| %>
<%= f.fields_for :meals do |f3| %>
<tr>
<td><%= f3.text_field :meal_date, :value => meal_date %></td>
<td><%= f3.hidden_field :food_type, :class => 'FoodType', :value => 'vegetarian'%></td>
<td><%= f3.select(:meal_type, [['Lunch', 1], ['Three Meals', 3], ['None', nil]]) %></td>
</tr>
<% end %>
<% end %>
</table>
<%= f.hidden_field :_destroy %>
<%= link_to "remove", '#', class: "remove_fields" %>
</fieldset>
Вы можете найти полный код в моем github: https://github.com/szabcsee/brk2013
1 ответ
В моделировании ИМО есть некоторая путаница.
Модель питания, отличающаяся от здравого смысла, на самом деле является своего рода порядком в вашем случае. Имея это в виду, я могу понять логику в принципе.
Для решения вашей проблемы предлагаю добавить поле в модель Meal(заказ). Поле для хранения, кто будет есть эту еду. Имя может быть for_whom
, eater
или как угодно понятно.
Значение этого поля по умолчанию равно 0, что означает, что эта еда предназначена для самого человека.(Почему не идентификатор этого человека? Потому что вам нужно искать идентификатор ребенка с помощью этого поля. Идентификатор этого человека уже сохранен в заказчике)
Когда человек заказывает еду, он видит вариант ("Радио" или "Выбор"), спрашивая его, для кого предназначена еда. Опция будет заполнена идентификаторами или его детьми, и им самим (как 0).
Если при обработке формы значение параметра больше 0, это будет означать идентификатор ребенка. Тогда вы можете справиться с этим соответственно.
Чтобы показать еду ребенка, просто запросите таблицу еды с идентификатором ребенка.