RoR - create record on many-to-many join table

我是研究僧i 提交于 2020-01-06 18:00:57

问题


I have the following models:

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 

On the show view of the Client I created a <%= link_to "New Establishment", new_client_address_path(@client)%> in order to create a new Address record and a new Establishment to the client.

On the AddressController I have:

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

  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

this will create the new Address but does not create the new Establishment. Can this automatically create the new Establishment that links the Client and the Address? Before you ask, I really need to have this Establishment model.


回答1:


First things first - you won't be able to use the accepts_nested_attributes_for :addresses call - you can only pass associative data through immediately connected models

I'll explain how to pass the data you want, but first let me explain how to do this correctly:

--

Collection Data

If you want to associate two existing objects through a join table, you'll be able to use some of the collection methods in ActiveRecord, namely 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 %>

This will populate the [other]_ids method in your Client model, which will essentially populate the has_many :through join model you have.

This will only work if you have Establishment records you already wish to associate with your newly created Client.

--

Nested Attributes

If you want to create a new Establishment record, you'll have to send the data to the Address model, and then to the Establishment model:

#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

This will allow you to call:

#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

This will allow you to use the following form:

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



回答2:


Here:

In you models:

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

in your controller:

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

in your view:

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

and you're all set!!



来源:https://stackoverflow.com/questions/25595309/ror-create-record-on-many-to-many-join-table

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!