i'm developing in Rails 4 with bootstrap rails forms and i'm trying to make a form that saves a product to a table. The product has many inputs and the input could belong to many products. The DB is postgres.
My main issue here is to save the product_id and the input_id to a join table I've created, named "productinput". this could be an example of what i'm trying to accomplish:
productinput table values example to generate each time i generate a new product with many inputs selected from a checkbox select:
product_id: 1 input_id: 1 product_id: 1 input_id: 2 product_id: 1 input_id: 3 product_id: 1 input_id: 4
I've done most of the configuration in my app. please take a look:
**productinput model**
class Productinput < ActiveRecord::Base
belongs_to :input, inverse_of: :productinputs
belongs_to :product, inverse_of: :productinputs
validates_presence_of :user_id
validates_presence_of :input_id
validates_presence_of :product_id
end
**product model**
class Product < ActiveRecord::Base
has_many :productinputs, inverse_of: :product, :dependent => :destroy
has_many :inputs, :through => :productinputs
accepts_nested_attributes_for :inputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :clientproducts, inverse_of: :product
has_many :worktasks, inverse_of: :product
validates_presence_of :user_id
accepts_nested_attributes_for :clientproducts, :allow_destroy => true
accepts_nested_attributes_for :worktasks
end
**input model**
class Input < ActiveRecord::Base
has_many :productinputs, inverse_of: :input, :dependent => :destroy
has_many :products, :through => :productinputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :inputproviders, inverse_of: :input
validates_presence_of :user_id
accepts_nested_attributes_for :inputproviders
end
Then the product form i'd like to have updated with the Input field to add inputs dinamically with a multiple select:
<%= bootstrap_form_for( @product, layout: :horizontal, label_col: "col-sm-2 hide", control_col: "col-sm-12", label_errors: true) do |f| %>
<div class="container-fluid">
<div class="row">
<%= f.alert_message "Please fix the errors below." %>
</div>
<div class="row">
<div class="col-xs-12">
<%= f.text_field :name, hide_label: true, placeholder: "Name", icon: "tag" %>
<%= f.text_field :description, hide_label: true, placeholder: "Description", icon: "align-justify" %>
<%= f.text_field :stock, hide_label: true, placeholder: "Stock", icon: "book" %>
<%= f.text_field :price, hide_label: true, placeholder: "Price", icon: "usd" %>
</div>
</div>
<div class="row text-center">
<%= f.submit "Submit Product", :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
products_path, :class => 'btn btn-default' %>
</div>
</div>
i've tried cocoon, nested_form, formtastic, simple_form gems, many tutorials and more that 2 weeks investigating this and i still don't understand how can i manage to do this, would you give me a hand please ?
Thanks,
This is how i manage to create children records in the join table from the parent form view:
Models:
class Product < ActiveRecord::Base
has_many :productinputs, :dependent => :destroy
has_many :inputs, through: :productinputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :clientproducts, inverse_of: :product
has_many :worktasks, inverse_of: :product
validates_presence_of :user_id
end
class Productinput < ActiveRecord::Base
belongs_to :product
belongs_to :input
#validates_presence_of :user_id
#validates_presence_of :input_id
#validates_presence_of :product_id
end
class Input < ActiveRecord::Base
has_many :productinputs
has_many :products, through: :productinputs
accepts_nested_attributes_for :productinputs, :allow_destroy => true
has_many :inputproviders, inverse_of: :input
validates_presence_of :user_id
accepts_nested_attributes_for :inputproviders
end
Controller:
Key here, the :inputs_ids[] fills up with an array of input elements from the "check_box_tag "product[input_ids][]"" in the form:
def product_params
parameters = params.require(:product).permit(:name, :description, :stock, :price, :input_ids => [], productinputs_attributes: [:user_id, :quantity])
parameters[:user_id] = current_user.id
parameters
end
Form:
<%= simple_form_for @product, defaults: { input_html: { class: 'form-horizontal' } } do |f| %>
<div class="row"> <%= f.error_notification id: 'user_error_message', class: 'form_error' %>
</div>
<div class="row">
<div class="col-xs-12 col-md-6">
<%= f.input :name, placeholder: 'Product Name', error: 'Username is mandatory, please specify one', label: false %>
<%= f.input :description, placeholder: 'Enter Description', label: false %>
<%= f.input :stock, placeholder: 'Stock', label: false %>
<%= f.input :price, placeholder: 'Price', label: false %>
</div>
<div class="col-xs-12 col-md-6">
<%= hidden_field_tag "product[input_ids][]", nil %>
<% Input.where("user_id = ?", current_user.id).each do |input| %>
<%= check_box_tag "product[input_ids][]", input.id,
@product.input_ids.include?(input.id), id: dom_id(input) %>
<%= label_tag dom_id(input), input.name %><br>
<% end %>
</div>
</div>
<div class="row text-center">
<%= f.button :submit, :class => 'btn btn-primary' %>
<%= link_to t('.cancel', :default => t("helpers.links.cancel")),
products_path, :class => 'btn btn-default' %>
</div>
<% end %>
Hope this helps anyone who has the same issue that i did.
Sorry if some people didn't understand what i was looking for.
P.S: just to let you know, i could simplify the multiple checkbox with simple form from this:
<%= hidden_field_tag "product[input_ids][]", nil %>
<% Input.where("user_id = ?", current_user.id).each do |input| %>
<%= check_box_tag "product[input_ids][]", input.id, @product.input_ids.include?(input.id), id: dom_id(input) %>
<%= label_tag dom_id(input), input.name %><br>
<% end %>
to this:
<%= f.association :inputs, :as => :check_boxes %>