0

Мне хотелось узнать, возможно ли это, давая следующий сценарий, создать запись в таблице соединений, используя has_many: через отношения в Rails 5 с коконом и simple_form, используя: id что он еще не создан. Я прошу об этом, потому что единственный способ создать эти записи в «таблице соединений» - это отредактировать продукт, а затем добавить входы, но для пользователей я считаю, что было бы лучше сделать все сразу, ввести новые параметры продукта, добавлять входы и после отправки формы, создать продукт с его ID, записями нарисуйте таблицы для связанных входов и т.д.:рельсы 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 

Параметры продукта, необходимые для управления товарами:

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. Однако в вашем коде, я вижу, вы пропускаете inverse_of: спецификаторов из has_many ассоциаций. См. recent commits

Rails 5 был изменен, поэтому по умолчанию требуется отношение belongs_to. При сохранении новых позиций id устанавливается только после сохранения, поэтому проверка не будет выполнена. Однако правильное указание рельсов inverse_of может корректно проверять ваши новые элементы.

+0

Я действительно очень ценю вашу помощь. Это решило мою проблему. 'has_many: product_inputs, inverse_of:: product' – Esteban

Смежные вопросы