RoR – 在多对多连接表上创建记录

我有以下型号:

Client.rb has_many :establishments accepts_nested_attributes_for :establishments has_many :addressess, through: :establishments accepts_nested_attributes_for :addresses Establishment.rb belongs_to :address belongs_to :client Address.rb has_many :establishments 

Clientshow视图中,我创建了一个 ,以便为客户端创建一个新的Address记录和一个新的Establishment。

AddressController我有:

      def new
         @client = Client.find(params [:client_id])
         @address = @ client.addresses.build
      结束 

  def create @address = Address.new(address_params) respond_to do |format| if @address.save format.html { redirect_to @address, notice: 'Estabelecimento criado com sucesso.' } format.json { render action: 'show', status: :created, location: @address } else format.html { render action: 'new' } format.json { render json: @address.errors, status: :unprocessable_entity } end end end 

这将创建新地址,但不会创建新的建立。 这可以自动创建链接ClientAddress的新企业吗? 在你问之前,我真的需要这个Establishment模型。

首先 – 您将无法使用accepts_nested_attributes_for :addresses调用 – 您只能通过立即连接的模型传递关联数据

我将解释如何传递您想要的数据,但首先让我解释一下如何正确地执行此操作:

收集数据

如果要通过连接表关联两个现有对象,您将能够使用ActiveRecord中的一些collection方法 ,即other_ids

 #app/views/clients/new.html.erb <%= form_for @client do |f| %> <%= f.collection_select :establishment_ids, Establishment.all, :id, :name %> <%= f.submit %> <% end %> 

这将填充Client模型中的[other]_ids方法,该方法将基本上填充has_many :through join模型。

只有在您拥有已与新创建的Client关联的Establishment记录时,此方法才有效。

嵌套属性

如果要创建新的Establishment记录,则必须将数据发送到Address模型, 然后发送到Establishment模型:

 #app/models/client.rb class Client < ActiveRecord::Base has_many :establishments has_many :addresses, through: :establishments end #app/models/establishment.rb class Establishment < ActiveRecord::Base belongs_to :client belongs_to :address accepts_nested_attributes_for :address end #app/models/address.rb class Address < ActiveRecord::Base has_many :establishments has_many :clients, through: :establishments end 

这将允许您致电:

 #app/controllers/clients_controller.rb class ClientsController < ApplicationController def new @client = Client.new @client.establishments.build.build_address end def create @client = Client.new client_params @client.save end private def client_params params.require(:client).permit(establishments_attributes: [address_attributes:[]]) end end 

这将允许您使用以下表单:

 #app/views/cients/new.html.erb <%= form_for @client do |f| %> <%= f.fields_for :establishments do |e| %> <%= e.fields_for :address do |a| %> ... <% end %> <% end %> <%= f.submit %> <% end %> 

这里:

在你的模特:

 Client.rb has_many :establishments accepts_nested_attributes_for :establishments has_many :addresses, through: :establishments accepts_nested_attributes_for :addresses Establishment.rb belongs_to :address belongs_to :client Address.rb has_many :establishments has_many :clients, through: :establishments 

在你的控制器中:

 class AddressController < ApplicationController def new @client = Client.find(params[:client_id]) @client.establishments.build.build_address # if you have a column in establishment, for example: name # you can do something like this to set establishment's name: # @client.establishments.build(name: 'First connection').build_address end # create method doesn't need to be changed!! end 

在你看来:

 <%= form_for(@client) do |form| %> <%= form.input :name %> <%= form.fields_for(:establishments) do |establishment_form| %> <% establishment = establishment_form.object.name.titleize %> <%= establishment_form.input :name, as: :hidden %> <%= establishment_form.fields_for(:address) do |address_form| %> <%= address_form.input :address1, label: "#{establishment} address1" %> <%= address_form.input :address2, label: "#{establishment} address2" %> <% end %> <% end %> <%= form.submit "Submit" %> <% end %> 

你们都准备好了!!