0

我想知道是否有可能,给出以下方案,使用has_many在连接表中创建记录:通过Rails 5与cocoon和simple_form中的关系使用:id它尚未创建的记录。我问这个问题,因为我发现在“连接表”中创建这些记录的唯一方法是编辑产品,然后添加输入,但对于用户体验,我认为一次完成所有步骤会更好,请输入新产品的参数,增加投入和表单提交之后,打造的产品与它的ID,用于链接输入,等联接表记录:rails 5与茧嵌套窗体记录一次创建

场景:

Given i open a new form to create a "product" 
And i fill the "product" parameters in the form 
And i add with cocoon a dynamic field to link the product with an "input" that exists in order to create a new record in the join table "product_inputs" 
And i click the "submit" button 
Then the ID of the product created is submited in the new "product_inputs" table record, linked with the "input" id 

模型我的设置有以下几种:

class Product < ApplicationRecord 
belongs_to :user, inverse_of: :products 
    has_many :product_inputs 
    has_many :inputs, through: :product_inputs, :class_name => 'Input' 
    accepts_nested_attributes_for :inputs 
    accepts_nested_attributes_for :product_inputs, :reject_if => :all_blank, :allow_destroy => true 

    validates :name, :presence => true 
    validates :description, :presence => true 
    validates_presence_of :user_id 
end 


class Input < ApplicationRecord 
belongs_to :user, inverse_of: :inputs 
    has_many :input_providers 
    has_many :providers, through: :input_providers 
    has_many :product_inputs 
    has_many :products, through: :product_inputs 
    accepts_nested_attributes_for :products 
    accepts_nested_attributes_for :product_inputs, :reject_if => :all_blank 
    accepts_nested_attributes_for :providers 
    accepts_nested_attributes_for :input_providers, :reject_if => :all_blank, :allow_destroy => true 

    validates :name, :presence => true 
    validates :description, :presence => true 
    validates_presence_of :user_id 
end 


class ProductInput < ApplicationRecord 
belongs_to :product 
    belongs_to :input 
    accepts_nested_attributes_for :input, :reject_if => :all_blank 
    accepts_nested_attributes_for :product, :reject_if => :all_blank 

    validates_presence_of :input 
    validates_presence_of :product 
    validates :quantity, numericality: { only_integer: true }, :allow_nil => true 
end 

Product Controller required params:

def product_params 
     parameters = params.require(:product).permit(:id, :name, :description, :stock, :price, :user_id, 
             product_inputs_attributes: [:id, :input_id, :product_id, :quantity, :_destroy, 
             input_attributes: [:id, :name, :description, :_destroy]]) 
     parameters[:user_id] = current_user.id 
     parameters 
    end 

产品_form:

<%= simple_form_for @product, :html => { class: "smart-form product_validations" } do |f| %> 
    <fieldset> 
     <div class="row"> 
     <section class="col col-4"> 
      <%= f.input :name, placeholder: 'Product Name', label: false %> 
     </section> 
     <section class="col col-4"> 
      <%= f.input :description, placeholder: 'Enter Description', label: false %> 
     </section> 
     <section class="col col-4"> 
      <%= f.input :stock, placeholder: 'Stock', label: false %> 
     </section> 
     </div> 
     <% if params[:id] %> 
     <div class="row"> 
      <section class="col col-6"> 
      <%= link_to_add_association 'add an input', f, :product_inputs, class: 'btn btn-success btn-sm' %> 
      </section> 
     </div> 
     <div class="row smart-form"> 
      <section id="inputs" class="col col-12"> 
      <%= f.simple_fields_for :product_inputs do |product_input| %> 
       <%= render 'product_input_fields', :f => product_input %> 
      <% end %> 
      </section> 
     </div> 
     <% end %> 
    </fieldset> 
    <footer> 
     <%= link_to 'Cancel', products_path, class: 'btn btn-default' %> 
     <%= f.button :submit, :class => 'btn btn-primary' %> 
    </footer> 
<% end %> 

_product_input_fields.html.erb

<div class="nested-fields product_input-fields"> 
    <fieldset> 
    <div class="row"> 
     <section class="input_from_list col col-4"> 
     <%= f.association :input, :required => true, 
          collection: Input.order(:name), 
          prompt: 'Choose an existing input', label: false %> 
     </section> 
     <section class="nested-fields col col-4"> 
     <%= f.input :quantity, :required => true, :placeholder => 'Enter the input quantity', :label => false %> 
     </section> 
     <section class="col col-4"> 
     <%= link_to_remove_association f, class: 'remove-tag btn btn-danger btn-xs' do %> 
      <div class="glyphicon glyphicon-remove"></div> 
     <% end %> 
     </section> 
     </div> 
    <div class="row"> 
     <section class="col col-4"> 
     <%= link_to_add_association 'or create a new input', f, :input, class: 'btn btn-default btn-xs add-input' %> 
     </section> 
    </div> 
    </fieldset> 
</div> 

_input_fields.html.erb

<div class="nested-fields"> 
    <section class="col col-6"> 
    <div class="new_input"> 
     <%= f.input :name, :placeholder => 'Create this new input', :label => false %> 
    </div> 
    </section> 
    <section class="col col-6"> 
    <div class="new_input"> 
     <%= f.input :description, :placeholder => 'Enter a Description', :label => false %> 
    </div> 
    </section> 
    <%= link_to 'Cancel', class: 'btn btn-default' %> 
</div> 

Product.js

$('#inputs').on('cocoon:after-insert', 
    function (e, input) { 
     console.log('inserting new input ...'); 
     $(".product-input-fields a.add-tag").data("association-insertion-position", 'after').data("association-insertion-node", 'this'); 
     $(this).find('.product-input-fields').bind('cocoon:after-insert', 
      function() { 
       console.log('insert new input ...'); 
       console.log($(this)); 
       $(this).find(".input_from_list").remove(); 
       $(this).find("a.add_fields").hide(); 
      }); 
    }); 

$('.product-input-fields').bind('cocoon:after-insert', 
    function (e) { 
     console.log('replace OLD input ...'); 
     e.stopPropagation(); 
     console.log($(this)); 
     $(this).find(".input_from_list").remove(); 
     $(this).find("a.add_fields").hide(); 
    }); 

回答

1

从你的代码中没有检查example project,我可以确认,对轨道5.但是,在你的代码,我看你是缺少has_many协会inverse_of:符的工作。请参阅recent commits

导轨5已更改,因此belongs_to关系在默认情况下是必需的。保存新项目时,id仅在保存后设置,因此验证将失败。但是,正确指定inverse_of导轨可以正确验证您的新项目。

+0

我真的很感谢你的帮助。这解决了我的问题。 'has_many:product_inputs,inverse_of::product' – Esteban