【发布时间】:2013-12-11 17:28:50
【问题描述】:
我正在尝试创建一个嵌套表单,其中包含三个关联的模型。
这是架构:
这些是模型:
../app/models/alimento.rb:
class Alimento < ActiveRecord::Base
attr_accessible :calorias, :nome, :refeicaos_attributes
validates :nome, :calorias, :presence => { :message => "nao pode ficar em branco" }
has_many :controles, :dependent => :destroy
has_many :refeicaos, through: :controles
has_many :diarios, through: :controles
accepts_nested_attributes_for :controles
end
../app/models/refeicao.rb:
class Refeicao < ActiveRecord::Base
attr_accessible :nome, :alimentos_attributes, :controles_attributes, :diario_attributes
validates :nome, :presence => { :message => "nao pode ficar em branco" }
has_many :controles, dependent: :destroy
has_many :alimentos, through: :controles
has_many :diarios, through: :controles
accepts_nested_attributes_for :controles
end
../app/models/diario.rb:
class Diario < ActiveRecord::Base
has_many :controles, dependent: :destroy
has_many :refeicaos, through: :controles
has_many :alimentos, through: :controles
accepts_nested_attributes_for :controles
attr_accessible :data, :controles_attributes, :refeicaos_attributes, :alimentos_attributes
end
../app/models/controle.rb:
class Controle < ActiveRecord::Base
belongs_to :alimento
belongs_to :refeicao
belongs_to :diario
attr_accessible :quantidade, :alimento_id, :refeicao_id, :diario_id
accepts_nested_attributes_for :alimento
accepts_nested_attributes_for :refeicao
accepts_nested_attributes_for :diario
end
我创建了许多alimentos(食物)和refeições(膳食),现在我需要创建一个
通过Controle(控制)模型可以包含许多alimentos和refeições的模型Diario。
../app/controllers/diarios_controller.rb:
class DiariosController < ApplicationController
# GET /diarios
# GET /diarios.json
def index
@diarios = Diario.all
respond_to do |format|
format.html # index.html.erb
format.json { render json: @diarios }
end
end
# GET /diarios/1
# GET /diarios/1.json
def show
@diario = Diario.find(params[:id])
respond_to do |format|
format.html # show.html.erb
format.json { render json: @diario }
end
end
# GET /diarios/new
# GET /diarios/new.json
def new
@diario = Diario.new
end
# GET /diarios/1/edit
def edit
@diario = Diario.find(params[:id])
end
# POST /diarios
# POST /diarios.json
def create
@diario = Diario.new(params[:diario])
respond_to do |format|
if @diario.save
format.html { redirect_to @diario, notice: 'Diario was successfully created.' }
format.json { render json: @diario, status: :created, location: @diario }
else
format.html { render action: "new" }
format.json { render json: @diario.errors, status: :unprocessable_entity }
end
end
end
# PUT /diarios/1
# PUT /diarios/1.json
def update
@diario = Diario.find(params[:id])
respond_to do |format|
if @diario.update_attributes(params[:diario])
format.html { redirect_to @diario, notice: 'Diario was successfully updated.' }
format.json { head :no_content }
else
format.html { render action: "edit" }
format.json { render json: @diario.errors, status: :unprocessable_entity }
end
end
end
# DELETE /diarios/1
# DELETE /diarios/1.json
def destroy
@diario = Diario.find(params[:id])
@diario.destroy
respond_to do |format|
format.html { redirect_to diarios_url }
format.json { head :no_content }
end
end
end
我正在尝试做“Nested Model Form (revised)”的例子。
观看次数:
../app/views/diarios/new.html.erb:
<%= form_for @diario do |f| %>
<div class="field">
<%= f.label :data %>
<%= f.date_select :data %>
<br>
</div>
<%= f.fields_for :refeicaos do |builder| %>
<%= render 'refeicao_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Adicionar Refeição", f, :refeicaos %>
</br>
</br>
<div class="actions">
<%= f.submit "Cadastrar Controle" %>
</div>
<% end %>
</br>
<%= link_to 'Voltar', root_path %>
../app/views/diarios/_refeicao_fields.html.erb:
<fieldset>
<strong>Refeição: </strong></br>
<%= f.label :nome, "Nome da Refeição", :style => 'margin-left: 5px;' %>
<%= collection_select(:refeicao, :id, Refeicao.order(:nome), :id, :nome) %>
<%= f.check_box :_destroy %>
<%= f.label :_destroy, "Remover Refeição" %>
</br>
</br>
<strong>Alimentos:</strong></br>
<%= f.fields_for :alimentos do |builder| %>
<%= render 'alimento_fields', f: builder %>
<% end %>
<%= link_to_add_fields "Adicionar Refeição", f, :alimentos %>
</fieldset>
../app/views/diarios/_alimento_fields.html.erb:
<fieldset>
<%= f.label :alimento, "Nome do Alimento:" %>
<%= collection_select(:alimento, :id, Alimento.order(:nome), :id, :nome) %>
<%= f.hidden_field :_destroy %>
<%= f.fields_for :controles do |builder| %>
<%= render 'controle_fields', f: builder %>
<% end %>
<%= link_to "Remover alimento", '#', class: "remove_fields" %></br>
</fieldset>
../app/views/diarios/_controle_fields.html.erb:
<fieldset>
<%= f.label :alimento, "Quantidade:", :style => 'margin-left: 42px;' %>
<%= f.number_field :quantidade, :style => 'width: 50px;' %>
</fieldset>
已创建自定义助手:
module ApplicationHelper
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
id = new_object.object_id
fields = f.fields_for(association, new_object, child_index: id) do |builder|
render(association.to_s.singularize + "_fields", f: builder)
end
link_to(name, '#', class: "add_fields", data: {id: id, fields: fields.gsub("\n", "")})
end
end
我收到此错误:
NoMethodError in Diarios#new
Showing D:/aplicacoes_indie/AppDieta/app/views/diarios/_refeicao_fields.html.erb where line #13 raised:
undefined method `alimentos' for nil:NilClass
Extracted source (around line #13):
10: <%= f.fields_for :alimentos do |builder| %>
11: <%= render 'alimento_fields', f: builder %>
12: <% end %>
13: <%= link_to_add_fields "Adicionar Refeição", f, :alimentos %>
14: </fieldset>
我尝试了很多方法,但我无法解决这个问题。想法是:日记 > 有 1 个或多个 refeicoes > 有 1 个或多个 alimentos 并通过控制模型保存每个关联。
我哪里错了?
已编辑*
感谢回答,现在表格出现了
但应该在从 alimento 中选择下方出现来自 controle 的数字字段“quantidade”,如下所示:
http://uploaddeimagens.com.br/images/000/123/917/full/model2.jpg?1385480010
../app/view/diarios/_alimento_fields.html.erb
<fieldset>
<%= f.label :alimento, "Nome do Alimento:" %>
<%= collection_select(:alimento, :id, Alimento.order(:nome), :id, :nome) %>
<%= f.hidden_field :_destroy %>
<%= f.fields_for :controles do |builder| %>
<%= render 'controle_fields', f: builder %>
<% end %>
<%= link_to "Remover alimento", '#', class: "remove_fields" %></br>
</fieldset>
../app/view/diarios/_controle_fields.html.erb
<fieldset>
<%= f.label :controle, "Quantidade:", :style => 'margin-left: 42px;' %>
<%= f.number_field :quantidade, :style => 'width: 50px;' %>
</fieldset>
还有一件事,我如何安装 Diario 的创建操作来获取 alimentos 和 refeicaos 选择的所有值并将每个值保存在 controle 模型中?因为我保存并只创建了一个没有关联的 Diario 对象。
../app/controllers/diarios_controller.rb 动作创建
def create
@diario = Diario.new(params[:diario])
respond_to do |format|
if @diario.save
format.html { redirect_to @diario, notice: 'Diario was successfully created.' }
format.json { render json: @diario, status: :created, location: @diario }
else
format.html { render action: "new" }
format.json { render json: @diario.errors, status: :unprocessable_entity }
end
end
end
【问题讨论】:
-
我相信您会收到此错误,因为
Diario只能接受:controles而不是:refeicaos或:alimentos的嵌套属性
标签: ruby-on-rails ruby ruby-on-rails-3 forms model