【问题标题】:RoR - create record on many-to-many join tableRoR - 在多对多连接表上创建记录
【发布时间】:2023-03-09 00:02:01
【问题描述】:

我有以下型号:

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 视图中,我创建了一个<%= link_to "New Establishment", new_client_address_path(@client)%>,以便为客户创建一个新的地址记录和一个新的机构。

AddressController 我有:

定义新 @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 模型。

【问题讨论】:

    标签: ruby-on-rails many-to-many jointable


    【解决方案1】:

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

    我会解释如何传递你想要的数据,但首先让我解释一下如何正确地做到这一点:

    --

    收集数据

    如果你想通过一个连接表关联两个现有对象,你可以使用collection methods in ActiveRecord中的一些,即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 连接模型。

    这只有在您已经希望将Establishment 记录与新创建的Client 关联时才有效。

    --

    嵌套属性

    如果您想创建一个新的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 %>
    

    【讨论】:

    • 我想你误解了我的问题。表格将在地址控制器处。客户端将被发送到 AddressController,它将为客户端创建一个新地址。 accept_nested_attributes_for 正在与客户和地址合作
    【解决方案2】:

    这里:

    在你的模型中:

    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 %>
    

    一切准备就绪!

    【讨论】:

    • 您所指的视图是针对地址还是客户端?
    • 我的错。您已经有客户并希望创建机构和地址?请查看更新代码。查看地址/new.html.erb
    猜你喜欢
    • 1970-01-01
    • 2021-07-25
    • 2022-03-08
    • 2016-06-27
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多