I created a form with client and server side validations using the model and html5 as seen in the code. Everything is working fine, but everytime e click in the link "New Ingredient" and I fill the form below it doesn't work. Moreover, it only works if I refresh the page.
Why it's not working at first?
ingredient.rb
class Ingredient < ActiveRecord::Base
has_many :meal_ingredients
has_many :meals, through: :meal_ingredient
before_save { self.name = name.capitalize }
validates :name, presence: true, length: { minimum: 2, maximum: 25 }, uniqueness: true
validates :unit, presence: true validates :carb, :prot, :fat, numericality: true,
length: { minimum: 1, maximum: 5 }
end
/new.html.erb
<div class = "row">
<div class= "col-md-10 col-md-offset-1 well">
<table class= "table">
<%= form_for #ingredient do |f| %>
<thead>
<tr>
<td>
<%= f.label "Nome" %>
</td>
<td>
<%= f.label "Unidade" %>
</td>
<td>
<%= f.label "Carbo" %>
</td>
<td>
<%= f.label "Prot" %>
</td>
<td>
<%= f.label "Gordura" %>
</td>
<td>
<%= f.label "kcal" %>
</td>
</tr>
</thead>
<tbody>
<tr>
<td scope="row" class="col-md-5">
<%= f.text_field :name, required: true, class: "form-control" %>
</td>
<td class="col-md-3">
<%= f.text_field :unit, required: true, class: "form-control" %>
</td>
<td class="col-md-1">
<%= f.text_field :carb, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= f.text_field :prot, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= f.text_field :fat, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
</td>
</tr>
</tbody>
<tfooter>
<tr>
<td class="pull-right">
<%= f.submit #ingredient.new_record? ? 'Create Ingredient' : 'Edit Ingredient', class: "btn btn-success" %>
</td>
<td>
<%= link_to "Voltar", ingredients_path, class: "btn btn-warning" %>
</td>
</tr>
</tfooter>
<% end %>
</table>
</div>
</div>
/ingredients_controller.rb
def new
#ingredient = Ingredient.new
end
def create
#ingredient = Ingredient.new(ingredient_params)
#ingredient.kcal = #ingredient.carb * 4 + #ingredient.prot * 4 + #ingredient.fat * 9
if #ingredient.save
flash[:success] = "Ingrediente criado com sucesso"
redirect_to ingredients_path
else
render 'new'
end
end
This is probably being caused by Turbolinks, which "speeds" up loading time by refreshing small parts of the DOM without reloading the whole entire page. As such, you'll need to trigger your script with an event that accounts for a partial refresh:
Try wrapping your JS in this:
var ready;
ready = function() {
# Your code here
};
$(document).ready(ready);
$(document).on("page:load", ready);
Here it is in CoffeeScript:
ready = ->
# Your code here
$(document).ready ready
$(document).on "page:load", ready
You can also disable Turbolinks from your "New Ingredient" link, which will cause the entire form page to be reloaded:
<%= link_to('New Ingredient', ..., data: { no_turbolink: true }) %>
Related
The main form
<%= p.fields_for :prd_province_vise_deliveries do |j| %>
<%= render(:partial => 'prd_province_vise_delivery_field', :locals => {:k => j})%>
<% end %>
and this is my prd_province_vise_delivery_field partial
<div>
<table class="table-striped">
<thead>
<tr>
<th> Province name </th>
<th> Delivery rate (Rs)</th>
<th> Delivery period(Days) </th>
</tr>
</thead>
<tbody>
<tr>
<td><%= k.label :province_name , 'Western'%></td>
<td><%= k.text_field(:delivery_rate, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%> </td>
<td> <%= k.text_field(:delivery_period, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%></td>
</tr>
<tr>
<td><%= k.label :province_name , 'Southern'%> </td>
<td><%= k.text_field(:delivery_rate, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%> </td>
<td> <%= k.text_field(:delivery_period, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%></td>
</tr>
<tr>
<td><%= k.label :province_name , 'Nothern'%> </td>
<td><%= k.text_field(:delivery_rate, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%> </td>
<td> <%= k.text_field(:delivery_period, {placeholder: '0', class: 'form-control input_border input_field_text_align_right'})%></td>
</tr>
</tbody>
</table>
</div>
but with this approach i could not get the params for the request
can anyone suggest a method
If you are using CoffeeScript to send the data from the FORM
create the array first, and loop through the text boxes and collect data
arr = []
$('input#day_id').each ->
arr.push $(this).val()
convert the array
sample_array = JSON.stringify(arr)
Call the ajax
$.ajax '/controller',
type: "POST",
data: { schedule: { days: sample_array }},
async: true
success:(data) ->
If you are submitting the form
create the form as follows
<% #class_variable.each do |f| %>
<%= text_field_tag 'delivery_rate[]', delivery_rate %>
<%= text_field_tag 'delivery_amount[]', delivery_amount %>
<% end %>
I am new to spree and ruby on rails.While clicking the 'reviews' in spree back-end, it's throwing an error.
Thanks in Advance.
NoMethodError in Spree::Admin::Reviews#index
Showing - var/lib/gems/2.3.0/ruby/2.3.0/bundler/gems/spree_reviews-e51cae9627f9/app/views/spree/admin/reviews/index.html.erb where line #25 raised:
index.html.erb:
<% content_for :page_title do %>
<%= Spree.t('reviews') %>
<% end %>
<% render 'spree/admin/shared/product_sub_menu' %>
<% content_for :table_filter_title do %>
<%= Spree.t('search') %>
<% end %>
<% content_for :table_filter do %>
<div data-hook="admin_reviews_index_search">
<%= search_form_for [:admin, #search] do |f| %>
<div class="alpha three columns">
<div class="field">
<%= label_tag nil, Spree.t(:user) %><br />
<%= f.text_field :name_cont, :size => 25 %>
</div>
</div>
<div class="seven columns">
<div class="field">
<%= label_tag nil, Spree.t(:title) -%><br/>
<%= f.text_field :title_cont, :size => 25 -%>
</div>
</div>
<div class="four columns">
<div class="field">
<%= label_tag nil, Spree.t(:review) -%><br/>
<%= f.text_field :review_cont, :size => 25 -%>
</div>
</div>
<div class="two columns omega">
<div class="field">
<%= label_tag nil, Spree.t(:approval_status)-%><br/>
<%= f.select :approved_eq, [[Spree.t('all'), nil],
[Spree.t('approved_reviews'), true],
[Spree.t('unapproved_reviews'),false]] -%>
</div>
</div>
<div class="clear"></div>
<div class="form-buttons actions filter-actions" data-
hook="admin_reviews_index_search_buttons">
<%= button Spree.t(:search), 'icon-search' %>
</div>
<%- end -%>
</div>
<%- end -%>
<% paginate #reviews %>
<% if #reviews.any? %>
<table class="index">
<colgroup>
<col style="width: 25%;">
<col style="width: 10%;">
<col style="width: 10%;">
<col style="width: 20%;">
<col style="width: 15%;">
<col style="width: 17%;">
</colgroup>
<thead>
<tr>
<th><%= Spree.t('product') %></th>
<th><%= Spree::Review.human_attribute_name(:rating) %></th>
<th><%= Spree.t('feedback') %></th>
<th><%= Spree::Review.human_attribute_name(:user) %></th>
<th><%= Spree::Review.human_attribute_name(:created_at) %></th>
</tr>
</thead>
<tbody>
<%- #reviews.each do |review| -%>
<tr id="<%= dom_id review %>">
<td>
<% if review.product %>
<%= link_to review.product.name, product_path(review.product) %>
<% end %>
</td>
<td class="align-center">
<%= txt_stars(review.rating) %>
</td>
<td class="align-center">
<%= link_to "(#{review.feedback_stars}/#{review.feedback_reviews.size})", admin_review_feedback_reviews_path(review) %>
</td>
<td class="align-center">
<%= review.user_id ? link_to(review.user.try(:email), [:admin, review.user]) : Spree.t(:anonymous) %></p>
<p><%= Spree::Review.human_attribute_name(:ip_address) %>: <%= review.ip_address ? link_to(review.ip_address, "http://whois.domaintools.com/#{review.ip_address}") : '-' %></p>
</td>
<td class="align-center">
<%= l review.created_at, :format => :short %>
</td>
<td class="actions">
<%= link_to_with_icon 'check', Spree.t('approve'), approve_admin_review_url(review), :no_text => true, class: 'approve' unless review.approved %>
<%= link_to_edit review, :no_text => true, :class => 'edit' %>
<%= link_to_delete review, :no_text => true %>
</td>
</tr>
<% end %>
</tbody>
</table>
<% else %>
<div class="no-objects-found">
<%= Spree.t(:no_results) %>
</div>
<% end %>
<%= paginate #reviews -%>
reviews_controller
class Spree::Admin::ReviewsController <
Spree::Admin::ResourceController
helper Spree::ReviewsHelper
def index
#reviews = collection
params[:q] ||= {}
#search = Spree::Review.ransack(params[:q])
#collection = #search.result.includes([:product, :user,
:feedback_reviews]).page(params[:page]).per(params[:per_page])
end
def approve
r = Spree::Review.find(params[:id])
if r.update_attribute(:approved, true)
flash[:notice] = Spree.t("info_approve_review")
else
flash[:error] = Spree.t("error_approve_review")
end
redirect_to admin_reviews_path
end
def edit
if #review.product.nil?
flash[:error] = Spree.t("error_no_product")
redirect_to admin_reviews_path and return
end
end
private
def collection
params[:q] ||= {}
#search = Spree::Review.ransack(params[:q])
#collection = #search.result.includes([:product, :user,
:feedback_reviews]).page(params[:page]).per(params[:per_page])
end
end
review.rb
class Spree::Review < ActiveRecord::Base
belongs_to :product, touch: true
belongs_to :user, :class_name => Spree.user_class.to_s
has_many :feedback_reviews
after_save :recalculate_product_rating, :if => :approved?
after_destroy :recalculate_product_rating
validates :name, presence: true
validates :review, presence: true
validates :rating, numericality: { only_integer: true,
greater_than_or_equal_to: 1,
less_than_or_equal_to: 5,
message: Spree.t('you_must_enter_value_for_rating') }
default_scope { order("spree_reviews.created_at DESC") }
scope :localized, ->(lc) { where('spree_reviews.locale = ?', lc) }
scope :most_recent_first, -> { order('spree_reviews.created_at DESC') }
scope :oldest_first, -> { reorder('spree_reviews.created_at ASC') }
scope :preview, -> { limit(Spree::Reviews::Config[:preview_size]).oldest_first }
scope :approved, -> { where(approved: true) }
scope :not_approved, -> { where(approved: false) }
scope :default_approval_filter, -> { Spree::Reviews::Config[:include_unapproved_reviews] ? all : approved }
def feedback_stars
return 0 if feedback_reviews.size <= 0
((feedback_reviews.sum(:rating) / feedback_reviews.size) + 0.5).floor
end
def set_search
#search=Product.search(params[:q])
end
def recalculate_product_rating
self.product.recalculate_rating if product.present?
end
end
Try to add result method after ransack:
#search = Spree::Review.ransack(params[:q]).result
I am using nested_forms gem in my project, nested_forms uses a partial view to render the line with my nested object attributes, here is my partial view code:
<tr class="fields">
<td>
<%= f.text_field :nombre, class: 'form-control craf' %>
</td>
<td>
<%
concat f.select :idtipodocumento, CrTipoDocumento.all.collect {|p| [ p.nombre, p.id ] }, {prompt: 'Seleccione el tipo de documento'}, :class=>'form-control'
%>
</td>
<td>
<%= f.text_field :documento, class: 'form-control', maxlength: '50' %>
</td>
<% if current_user.email.include? '#cifco.gob.sv' %>
<td>
<%= f.check_box :activo %>
</td>
<td>
<%= f.check_box :impresa %>
</td>
<td>
<%= f.check_box :extra %>
</td>
<% end %>
<td>
<%= f.link_to_remove raw('<i class="fa fa-minus-circle" aria-hidden="true"></i>'), :class =>'btn btn-danger hidden-print' %>
</td>
And here is the code block of the view where this partial is rendering:
<tbody>
<fieldset id="acreditados">
<%= f.fields_for :cr_acreditados, :wrapper => false %>
</fieldset>
</tbody>
So, what I want to do is evaluate if 'impresa' == false and only then render it, but if try f.impresa it says the method 'impresa' doesnt exist for f
Here is the form full code:
<%= nested_form_for(#cr_acreditacion_cliente, :validate => true) do |f| %>
<% if #cr_acreditacion_cliente.acreditaciones == nil %>
<% else %>
<table class="table table-striped table-bordered table-hover" id="AC">
<thead>
<tr>
<th>Evento</th>
<th>Cliente</th>
<th>Stand</th>
<th>Acreditaciones</th>
<th>Acreditaciones Disponibles</th>
<th>Tipo de Acreditacion</th>
</tr>
</thead>
<tbody>
<td><%= #cr_acreditacion_cliente.cr_evento.nombre %></td>
<td><%= #cr_acreditacion_cliente.cr_cliente.nombre %></td>
<td><%= #cr_acreditacion_cliente.cr_stand.codigo %></td>
<td><%= #cr_acreditacion_cliente.acreditaciones %></td>
<td>
<p hidden id="cnt"><%= #cr_acreditacion_cliente.acreditaciones %></p>
<p id="acd">
<%= #counter = #cr_acreditacion_cliente.acreditaciones - #cr_acreditacion_cliente.cr_acreditados.count %>
</p>
</td>
<td><%= #cr_acreditacion_cliente.cr_tipocre.tipo %></td>
</tbody>
</table>
<table class="table table-striped table-bordered table-hover" id="DAC">
<thead>
<tr>
<th>Nombre</th>
<th>Tipo de Documento</th>
<th>Documento</th>
<% if current_user.email.include? '#cifco.gob.sv' %>
<th>Activo</th>
<th>Impresa</th>
<th>Extra</th>
<% end %>
<th class="hidden-print">Acciones</th>
</tr>
</thead>
<tbody>
<fieldset id="acreditados">
<%= f.fields_for :cr_acreditados, :wrapper => false %>
</fieldset>
</tbody>
</table>
<div id="addBtn">
<% if #counter >= 1 %>
<p><%= f.link_to_add raw('<i class="fa fa-plus-circle" aria-hidden="true"></i>'), :cr_acreditados, id: 'btna', :class => 'btn btn-primary lta hidden-print', "data-target" => "#DAC" %></p>
<% else %>
<p class="text-center"><h3>No dispone de mas acreditaciones</h3></p>
<% end %>
</div>
<div class="actions text-center">
<%= f.submit "Guardar Credenciales", :class => 'btn btn-success hidden-print', data: { confirm: 'Favor verifique los datos antes de almacenarlos' }%>
</div>
<% end %>
<% end %>
I didn't find anything related to my problem.
I have these models:
class Meal < ActiveRecord::Base
has_many :meal_ingredients
has_many :ingredients, through: :meal_ingredients
accepts_nested_attributes_for :ingredients, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :meal_ingredients
end
class Ingredient < ActiveRecord::Base
has_many :meal_ingredients
has_many :meals, through: :meal_ingredients
end
class MealIngredient < ActiveRecord::Base
belongs_to :meal
belongs_to :ingredient
end
In the meal_ingredient model I have a quantity column and I want to let the user set this quantity when creating a new meal with many ingredients. To allow that, I used the cocoon gem. And that's when the problem comes: I must set the ingredient_id and the meal_id to build the association with the quantity but I just hit the database when submiting the "Create Meal" buttom.
Part of the solution I thought is creating a fields_forinside the form and set an instance variable in the controller.
But how can I get these ids? I'm stuck.
class MealsController < ApplicationController
before_action :set_meal, only: [:edit, :update, :show]
autocomplete :ingredients, :name
def index
#meals = Meal.order(updated_at: :desc).paginate(:page => params[:page], :per_page => 4)
end
def show
end
def new
#meal = Meal.new
#qtd = MealIngredient.new
end
def create
#meal = Meal.new(meal_params)
#qtd = #meal.ingredients.map{|r| MealIngredient.new(quantity: params[:quantity], ingredient_id: r.id, meal_id: #meal)}
if #meal.save
flash[:success] = "Refeição criada com sucesso!"
redirect_to meals_path
else
render :new
end
end
def edit
end
def update
if #meal.update(meal_params)
flash[:success] = "Your meal was updated succesfully!"
redirect_to meal_path(#meal)
else
render :edit
end
end
private
def meal_params
params.require(:meal).permit(:name, :picture, ingredients_attributes: [:name, :unit, :carb, :prot, :fat])
end
def set_meal
#meal = Meal.find(params[:id])
end
end
This is what I got so far... I don't think the main problem is being caused by cocoon gem. I think it's about concepts...
The params
Parameters: {"utf8"=>"✓", "authenticity_token"=>"dTYOiz8+pwNfwt432qhy7Yuj0hSVksj0bsTzxp8vD6QaupIJueSO1ASDkwiOB92qCiLO33Ke61aUBGbyvGZJfA==", "meal"=>{"name"=>"tests", "ingredients_attributes"=>{"1449471543091"=>{"name"=>"uva", "unit"=>"und", "carb"=>"1", "prot"=>"1", "fat"=>"1", "_destroy"=>"false"}}}, "meal_ingredient"=>{"quantity"=>"14"}, "commit"=>"Create Meal"}
View
_form.html.erb
<div class = "row">
<div class= "col-md-10 col-md-offset-1">
<%= simple_form_for(#meal) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
</div>
<h3>ingredientes</h3>
<div id="ingredients">
<%= f.simple_fields_for :ingredients do |ingredient| %>
<%= render "ingredient_fields", :f => ingredient %>
<% end %>
</div>
<div class="form-actions">
<div><%= link_to_add_association 'adicionar ingrediente', f, :ingredients, :class => "btn btn-default" %></div>
<div><%= f.button :submit, class: "btn btn-success" %></div>
</div>
<% end %>
</div>
</div>
_ingredient_fields.html.erb
<%= render 'shared/errors', obj: #meal %>
<div class = "nested-fields">
<table class= "table">
<thead>
<tr>
<td>
<%= f.label "Nome" %>
</td>
<td>
<%= f.label "Unidade" %>
</td>
<td>
<%= f.label "Carbo" %>
</td>
<td>
<%= f.label "Prot" %>
</td>
<td>
<%= f.label "Gordura" %>
</td>
<td>
<%= f.label "Quantidade" %>
</td>
<td>
<%= f.label "kcal" %>
</td>
</tr>
</thead>
<tbody>
<tr>
<td scope="row" class="col-md-4">
<%= f.text_field :name, required: true, class: "form-control" %>
</td>
<td class="col-md-2">
<%= f.text_field :unit, required: true, class: "form-control" %>
</td>
<td class="col-md-1">
<%= f.text_field :carb, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= f.text_field :prot, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= f.text_field :fat, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= fields_for #qtd do |f| %>
<%= f.hidden_field :ingredient_id %>
<%= f.number_field :quantity, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
<% end %>
</td>
<td class="col-md-1">
</td>
<td class="col-md-1">
<%= link_to_remove_association "remove item", f, :class => "btn btn-danger" %>
</td>
</tr>
</tbody>
</table>
</div>
Following this tutorial and looking at the cocoon's demo app. It was easy to solve my problem, although I actually don't know exactly what I did here the
<%= link_to_add_association 'adicionar ingrediente', f, :meal_ingredients, 'data-association-insertion-node' => "#ingredients ol", 'data-association-insertion-method' => "append", :wrap_object => Proc.new {|quantity| quantity.build_ingredient; quantity }, :class => "btn btn-default" %>
I hate coding this way but this time I just went with the flow very carefully...
If someone has already used cocoon for that purpose and can explain better I - and the community - would appreciate :D
Changes made:
Model
class MealIngredient < ActiveRecord::Base
belongs_to :meal
belongs_to :ingredient
accepts_nested_attributes_for :ingredient, :reject_if => :all_blank
end
Controller
class MealsController < ApplicationController
before_action :set_meal, only: [:edit, :update, :show]
autocomplete :ingredients, :name
def index
#meals = Meal.order(updated_at: :desc).paginate(:page => params[:page], :per_page => 4)
end
def show
end
def new
#meal = Meal.new
end
def create
#meal = Meal.new(meal_params)
if #meal.save
flash[:success] = "Refeição criada com sucesso!"
redirect_to meals_path
else
render :new
end
end
def edit
end
def update
if #meal.update(meal_params)
flash[:success] = "Your meal was updated succesfully!"
redirect_to meal_path(#meal)
else
render :edit
end
end
private
def meal_params
params.require(:meal).permit(:name, :picture, :tcarb, :tprot, :tfat, :tkcal, meal_ingredients_attributes: [:quantity, ingredient_attributes: [:id, :name, :unit, :carb, :prot, :fat, :_destroy]])
end
def set_meal
#meal = Meal.find(params[:id])
end
end
Views
_form.html.erb
<div class = "row">
<div class= "col-md-10 col-md-offset-1">
<%= simple_form_for(#meal) do |f| %>
<%= f.error_notification %>
<div class="form-inputs">
<%= f.input :name %>
</div>
<h3>ingredientes</h3>
<fieldset id="ingredients">
<ol>
<%= f.fields_for :meal_ingredients do |meal_ingredient| %>
<%= render "meal_ingredient_fields", :f => meal_ingredient %>
<% end %>
</ol>
<div class="form-actions">
<div><%= link_to_add_association 'adicionar ingrediente', f, :meal_ingredients, 'data-association-insertion-node' => "#ingredients ol", 'data-association-insertion-method' => "append", :wrap_object => Proc.new {|quantity| quantity.build_ingredient; quantity }, :class => "btn btn-default" %></div>
</div>
</fieldset>
<div class="form-actions">
<div><%= f.button :submit, class: "btn btn-success" %></div>
</div>
<% end %>
</div>
</div>
_meal_ingredient_fields.html.erb
<div class = "nested-fields">
<table class= "table">
<thead>
<tr>
<td>
<%= f.label "Nome" %>
</td>
<td>
<%= f.label "Unidade" %>
</td>
<td>
<%= f.label "Carbo" %>
</td>
<td>
<%= f.label "Prot" %>
</td>
<td>
<%= f.label "Gordura" %>
</td>
<td>
<%= f.label "Quantidade" %>
</td>
<td>
<%= f.label "kcal" %>
</td>
</tr>
</thead>
<tbody>
<tr>
<%= f.fields_for :ingredient do |fi| %>
<td scope="row" class="col-md-4">
<%= fi.text_field :name, required: true, class: "form-control" %>
</td>
<td class="col-md-2">
<%= fi.text_field :unit, required: true, class: "form-control" %>
</td>
<td class="col-md-1">
<%= fi.text_field :carb, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= fi.text_field :prot, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
<%= fi.text_field :fat, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<% end %>
<td class="col-md-1">
<%= f.number_field :quantity, required: true, :pattern => '^\d+(\.\d+)*$', title: "Apenas números separados por pontos", class: "form-control" %>
</td>
<td class="col-md-1">
</td>
<td class="col-md-1">
<%= link_to_remove_association "remove item", f, :class => "btn btn-danger" %>
</td>
</tr>
</tbody>
</table>
</div>
I used cocoon also, and had some troubles setting it up. I think you have to realiaze that Rails is smarter then you think. You can easily just call save on the parameter string. Just make sure the parameters are all accepted. You will also need :id for ingredients_attributes for instance (and :_destroy, if you allow deletion as well). Oh, and loose the nested_attributes for your join table as well.
I think something like this should work:
def new
#meal = Meal.new
end
def create
#meal = Meal.new(meal_params)
if #meal.save
flash[:success] = "Refeição criada com sucesso!"
redirect_to meals_path
else
render :new
end
end
private
def meal_params
params.require(:meal).permit(:name, :picture, ingredients_attributes: [:id, :name, :unit, :carb, :prot, :fat, :_destroy])
end
If it doensn't, please post your views that contain the main form and the partials.
I have the following in one of my forms. With this code I can dynamically add divisions, sub_divisions and sub_sub_divisions on the page. The problem is the sub_sub_divisions I add are saved to the first sub_division even though they are correctly displayed on other sub_divisions on the view. I don't know what is happening between the view and what is passed to controller to make this error. Thanks a lot.
<%= nested_form_for #division do |f| %>
<%= render 'shared/error_messages', object: f.object %>
<table>
<tr>
<td>
<%= f.label t("name") %>
<%= f.text_field :name, class: 'form-control' %>
</td>
<td>
<%= f.label t("description") %>
<%= f.text_field :description, class: 'form-control' %>
</td>
</tr>
<tr><td><h3><%=t :sub_divisions %></h3></td></tr>
<tr>
<td colspan=4>
<table id="sub_divs" class="table table-condensed table-striped">
<tr><th><%=t :name %></th><th><%=t :description %></th></tr>
<%= f.fields_for :sub_divs, :wrapper => false do |sub_div| %>
<tr class="fields">
<td><%= sub_div.text_field :name, class: 'form-control' %></td>
<td><%= sub_div.text_field :description, class: 'form-control' %></td>
<td><%= sub_div.link_to_remove t("delete") %></td>
</tr>
<td colspan=3>
<table id="<%= 'sub_sub_divs' + sub_div.index.to_s %>">
<tr><th><%=t :name %></th><th><%=t :description %></th></tr>
<%= sub_div.fields_for :sub_sub_divs,
:wrapper => false do |sub_sub_div| %>
<tr class="fields">
<td><%= sub_sub_div.text_field :name,
class: 'form-control' %></td>
<td><%= sub_sub_div.text_field :description, class:
'form-control' %></td>
<td><%= sub_sub_div.link_to_remove t("delete") %></td>
<td><%= sub_sub_div.hidden_field :id,
value: sub_sub_div.object.sub_div_id %></td>
</tr>
<% end %>
</table>
</td>
</tr>
<tr>
<td colspan=3 class="pull-right">
<%= sub_div.link_to_add t("add") +
t("sub") + t('sub') + t('div'), :sub_sub_divs,
:data => { :target => "#"+"sub_sub_divs" +
#{sub_div.index.to_s}", id: sub_div.object.id} %>
</td>
</tr>
<% end %>
</table>
</td>
</tr>
<tr><td colspan=2 class="pull-right">
<%= f.link_to_add t("add") + t("sub") + t('div'),
:sub_divs, :data => { :target => "#sub_divs"} %></td></tr>
<tr><td><%= f.submit t("update"), class: "btn btn-primary" %></td></tr>
</table>
<% end %>
Outside of your call to
<%= f.fields_for :sub_divs, :wrapper => false do |sub_div| %>
You should iterate over the sub_divs:
<%= #division.sub_divs.each do |sub_div| %>
And then pass each one to the fields_for call as the 2nd parameter:
<%= f.fields_for :sub_divs, sub_div, :wrapper => false do |sub_div| %>
Do the same for the next nested sub_sub_div and finally:
<%= sub_sub_div.hidden_field :id,
value: sub_sub_div.object.sub_div_id %>
...will have the correct sub_div_id