Rails,在一个表单上填充具有关联模型的数据库

时间:2016-10-12 19:32:23

标签: ruby-on-rails

我已经查看了类似问题的各种答案,并没有完全破解它。 wine模型定义为has_one :register, :dependent => :destroy,正确或错误地添加了accepts_nested_attributes_for :registerregister定义为belongs_to :wine

wines_controller.rb create内的代码为:

def new
  @wine = Wine.new
  @register = Register.new

def create
  @wine = Wine.new(wine_params)
  @register = @wine.registers.build(register_params)
  respond_to do |format|
    if @wine.save 
    #success
    else
      format.json { render json: @wine.errors, status: :unprocessable_entity }
      format.json { render json: @register.errors, status: :unprocessable_entity }
    end
  end 
end

我创建new wine的表单包含以下代码:

<%= simple_form_for @wine do |f| %>  
# various working elements
<div class="field">
  <% f.fields_for :register do |r| %>
    <%= r.label :short_name %>
    <%= r.text_field :short_name %>
    <%= r.label :barcode %>
    <%= r.text_field :barcode %>
  <% end %>
</div>

当调用此表单时,不会从f.fields_for命令创建任何字段,但会执行此块,因为我可以在其中添加测试按钮以证明它已被访问。

如果我尝试创建葡萄酒,我会收到以下错误消息:

undefined method `registers' for #<Wine:0x007f1204375330> Did you mean? register register= register_id

我认为使用.build确保数据完整性:我不想创建没有相应wine的{​​{1}}。我已经尝试过考虑它的嵌套属性,但这似乎被许多人认为是一个糟糕的计划。这种当前的方法感觉正确,但我认为我至少缺少对语法的一些理解。

日后,有必要将与register相关联的其他模型与葡萄酒无关。我正在考虑类似的方法,但我很高兴被告知重新考虑!

2 个答案:

答案 0 :(得分:2)

如果我理解正确,你有2个问题:

首先,未显示注册字段 - 部分原因是@ wine.register为零。

您应该将新操作更改为:

def new
  @wine = Wine.new
  @wine.register = Register.new

此外,由于您使用的是simple_form_for,因此您需要使用simple_fields_for代替fields_for

导致异常的第二个问题告诉你一切......你正试图访问@ wine.registers,而不是@ wine.register

将创建方法更改为:

  @register = @wine.register.build(register_params)

这将解决这个问题......但是......你真正需要做的就是从params构建@wine对象 - 你的params应该被配置为允许正确的嵌套属性 - 如果它设置正确的话在构建@wine对象时也将构建register对象。

您的模型已设置为accept_nested_attributes,因此在调用@ wine.save时也将验证并保存寄存器对象 - 无需显式保存寄存器对象。

你应该有类似的东西:

def wine_params
    params.require(:wine).permit(
          :attribute1, :attribute2,
          register_attributes: [:id, :short_name, :barcode])
end

答案 1 :(得分:0)

试试这个

葡萄酒和注册模型

class Wine < ApplicationRecord
    has_one :register, inverse_of: :wine,  :dependent => :destroy
    accepts_nested_attributes_for :register
end

class Register < ApplicationRecord
    belongs_to :wine, inverse_of: :register
    validates_presence_of :wine
end

葡萄酒控制器

class WinesController < ApplicationController
  def new
    @wine = Wine.new
    @wine.build_register
  end


  def create
    @wine = Wine.new(wine_params)

    if @wine.save
        redirect_to @wine
    else
        render :new
    end
  end

  private
    def wine_params
        params.require(:wine).permit(:name, register_attributes: [:simple_name])
    end
end

我的wine_params特定于

rails g model wine name:string
rails g model register name:string wine_id:integer

最后,葡萄酒形式应如下所示

<%= form_for @wine do |f|%>
    <p>
        <%= f.label :name%>
        <%= f.text_field :name%>
    </p>

    <%= f.fields_for :register do |r|%>
    <p>
        <%= r.label :simple_name%>
        <%= r.text_field :simple_name%>
    </p>    
    <% end %>

    <%= f.submit %>
<% end %>

因此,您可以修改wine_params并为您的应用程序细节形成部分