【问题标题】:Rails, populate database with associated models on one formRails,在一个表单上使用关联模型填充数据库
【发布时间】:2017-02-21 17:51:56
【问题描述】:

我查看了类似问题的各种答案,但还没有完全破解。 wine 模型是用 has_one :register, :dependent => :destroy 定义的,我添加了 accepts_nested_attributes_for :register 是对还是错。 register 定义为 belongs_to :wine

wines_controller.rbcreate 的代码是:

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 可以确保数据完整性:我不想创建没有对应registerwine。我尝试过考虑嵌套属性,但这似乎被许多人认为是一个糟糕的计划。这种当前的方法感觉是正确的,但我认为我至少缺少对语法的一些理解。

以后有必要将其他模型链接到register,这些模型不会与葡萄酒相关联。我正在考虑采用类似的方法,但我很高兴被告知要重新考虑!

【问题讨论】:

    标签: ruby-on-rails


    【解决方案1】:

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

    首先没有显示注册字段 - 这部分是因为 @wine.register 为 nil。

    您应该将新操作更改为:

    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)
    

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

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

    你应该有类似的东西:

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

    【讨论】:

    • 好的,感谢您的意见。您建议的第一个调整会导致 WinesController#new 中的 ActiveModel::MissingAttributeError 和 can't write unknown attribute 'wine_id'
    • 如果我尝试创建新的葡萄酒条目会出现该错误
    • 您能否澄清一下...我们在谈论@wine.register = Register.new 行吗?如果是这样,请检查您的 Register 表......它应该有一个 wine_id 参考
    • wines 确实有一个列wine_id,由Rails 自动创建。错误信息指向行@wine.register = Register.new
    • 我尝试添加 wine_id into the attributes of register` 但很高兴这并没有解决它。如果有的话,我只会感到困惑!
    【解决方案2】:

    试试这个

    葡萄酒和注册模型

    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 并根据您的应用程序细节形成部分

    【讨论】:

    • 注册会在你创建wine时自动保存
    • 您也可以使用 simple_form_for 和 simple_fields_for 代替 form_for 和 fields_for
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-07
    • 2019-01-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多