首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Rails多模型形式

Rails多模型形式
EN

Stack Overflow用户
提问于 2014-06-30 01:52:40
回答 2查看 188关注 0票数 0

我有5个模型,我需要创建一个独特的表单,可以为每个模型创建一个新的对象。模型是

代码语言:javascript
复制
Contract.rb
    belongs_to :establishment

Establishment.rb
    has_many :contracts
    belongs_to :address
    belongs_to :client

Address.rb
    has_many :establishments
    belongs_to :zip

Client.rb
    has_many :establishments

Zip.rb
    has_many :addresses

要创建对象的表单是Contract的表单。

我的第一种方法是分别创建fields_for --其他模型,例如:

代码语言:javascript
复制
_form.html.erb

<%= form_for(@contract) do |f| %>
<% if @contract.errors.any? %>
<div id="error_explanation">
  <h2><%= pluralize(@contract.errors.count, "error") %> prohibited this contract from being saved:</h2>
...#fields for contract
<%= f.fields_for @client do |client|%>
  <%=client.label 'Name'%><%=client.text_field :name%>
  ...#other fields for client
<%= f.fields_for @address do |address|%>
  <%=address.label 'Street'%><%=address.text_field :street%>
  ...#other fields for address
<%=f.fields_for @zip do |zip|%>
  <%=zip.label 'Code'%><%=zip.number_field :code%>
  ...#other fields for zip

表单工作正常,得到了所有字段,但是在ContractController.rb上,我无法访问params上的地址、客户端和Zip字段。如果我使用@client = Client.create(params[:client]),它将不会得到一个错误,但不会在模型上创建一个对象。我意识到,params[:client] (以及其他人认为不是合同的)是零的。然后我使用params[:contract][:client]得到了错误ForbiddenAttributesError..。

所以,我决定改变方法,开始用多级nested_attributes来思考,但我仍然没有.

我已经把模特改成:

代码语言:javascript
复制
Contract.rb
    belongs_to :establishment
    accepts_nested_attributes_for :establishment

    has_one :address, through: :establishment
    accepts_nested_attributes_for :address

    has_one :zip, through: :address
    accepts_nested_attributes_for :zip

    has_one :client, :through => :establishment
    accepts_nested_attributes_for :client

在我做的控制器上

代码语言:javascript
复制
ContractController.rb

def new
  @contract = Contract.new
  @establishment = @contract.build_establishment
  @address = @establishment.build_address
  @zip = @address.build_zip
  @client = @establishment.build_client
end

但是现在表单没有用于Client, Address and Zip的字段

可以创建这种类型的表单吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-06-30 23:56:57

-编辑的答案--删除_attributes[:contract][:client_attributes][:...] (和:zip和:address)处的地址

G.B.差点就拿到了,但这还不够。

回到第一种方法,在阅读了这个文章之后,我做了以下更改:

代码语言:javascript
复制
Contract
_form.html.erb

  <%= form_for(@contract) do |f| %>
  <% if @contract.errors.any? %>
  <div id="error_explanation">
    <h2><%= pluralize(@contract.errors.count, "error") %> prohibited this contract from                   being saved:</h2>
  ...#fields for contract
  <%= f.fields_for :client, @client do |client|%>
    <%=client.label 'Name'%><%=client.text_field :name%>
    ...#other fields for client
  <%= f.fields_for :address, @address do |address|%>
    <%=address.label 'Street'%><%=address.text_field :street%>
    ...#other fields for address
  <%=f.fields_for :zip, @zip do |zip|%>
    <%=zip.label 'Code'%><%=zip.number_field :code%>
    ...#other fields for zip

因此,它必须是f.fields_for @client do |client| (地址和zip相同),而不是f.fields_for :client, @client do |client|

ContractController

代码语言:javascript
复制
def new
  @contract = Contract.new
  @client = Client.new
  @address = Address.new
  @zip = Zip.new
end

def create
  @contract = Contract.new(contract_params)

  if !Zip.exists?(:cod_postal1 => params[:contract][:zip][:cod_postal1], :cod_postal2 => params[:contract][:zip][:cod_postal2])
    create_zip
  elsif
    @zip = Zip.where(:cod_postal1 => params[:contract][:zip][:cod_postal1], :cod_postal2 => params[:contract][:zip][:cod_postal2])
  end

  create_client
  create_address
  @address.zip = @zip
  @establishment = Establishment.new(:sede => true)
  @establishment.address = @address
  @establishment.client = @client
  @client.save
  @address.save
  @establishment.save
  @contract.establishment = @establishment

  respond_to do |format|
    if @contract.save
    ...
end

def create_client
  @client = Client.create(
                          :numero => params[:contract][:client][:numero],
                          ...#other client fields
                         )
end

def create_zip
  @zip = Zip.create(
                    :distrito => params[:contract][:zip][:distrito],
                    :concelho => params[:contract][:zip][:concelho],
                    ...#other zip fields
  )      
end

def create_address
  @address = Address.create(
                            :rua => params[:contract][:address][:rua],
                            ...#other address fields
  )
end

这起作用很大。在一个有一个提交按钮的表单中,创建了不同的模型

票数 0
EN

Stack Overflow用户

发布于 2014-06-30 05:23:35

如果要使用accepts_nested_attributes_for,请从API接口中记住这一点:

“嵌套属性允许您通过父属性在关联记录上保存属性”

因此,这样说是无效的:

代码语言:javascript
复制
Class Contract #child class 
   belongs_to :establishment
   accepts_nested_attributes_for :establishment

因为Contractchild。不是Parent

正确的做法是:

代码语言:javascript
复制
Class Establishment # parent class
    has_many :contracts
    accepts_nested_attributes_for :contracts

然后在Establishments控制器params中添加:

contracts_attributes: [:id, attribute1, attribute2] #不要忘记添加:id

对所有其他模型都采用相同的方法。阅读API接口中的示例

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24482021

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档