Research: [Rails 4 Nested Attributes with fields_for Don't Save to Database] [Rails 4 - nested attributes with Cocoon gem]1[Rails 4.1 Nested Attributes and Fields For Getting Unpermitted Parameters and Not Saving]2
My specific problem is:
I have two nested forms: Ingredients and Directions
The ingredients save but the directions do not save. It doesn't throw up an error, nor do the logs have a clue as to if there even is a problem.
First, let's get the most common problem out of the way: incorrectly named attributes parameters for strong parameters. Mine is correctly plural.
class RecipesController < ApplicationController
def recipe_params
params.require(:recipe).permit(:title, :image, directions_attributes: [:id, :name, :_destroy], ingredients_attributes: [:id, :name, :_destroy])
end
And my models are setup correctly as well
class Recipe < ActiveRecord::Base
has_many :ingredients
has_many :directions
belongs_to :user
accepts_nested_attributes_for :ingredients, reject_if: :all_blank, allow_destroy: true
accepts_nested_attributes_for :directions, reject_if: :all_blank, allow_destroy: true
validates :title, presence: true
mount_uploader :image, ImageUploader
end
#_form.html.haml
= simple_form_for @recipe, html: { multipart: true } do |f|
- if @recipe.errors.any?
#errors
%p
= @recipe.error.count
Prevented this recipe from saving
%ul
%li= msg
.panel-body
= f.input :title, label: "Name", input_html: { class: 'form-control' }
= f.input :image, label: "Picture",input_html: { class: 'form-control' }
.row
.col-md-6
%h3 Ingredients
#ingredients
= f.simple_fields_for :ingredients do |ingredient|
= render 'ingredient_fields', f: ingredient
.links
= link_to_add_association 'Add Ingredient', f, :ingredients, class: "btn btn-default add-button"
.col-md-6
%h3 Directions
#directions
= f.simple_fields_for :directions do |direction|
= render 'direction_fields', f: direction
.links
= link_to_add_association 'Add Step', f, :directions, class: "btn btn-default add-button"
= f.button :submit, class: "btn btn-primary"
Here are both my partials for ingredients and directions
_ingredient_fields.html.haml
.form-inline.clearfix
.nested-fields
= f.input :name, input_html: { class: "form-input form-control"}
= link_to_remove_association 'Remove', f, class: "form-button btn btn-default"
_direction_fields.html.haml
.form-inline.clearfix
.nested-fields
= f.input :name, input_html: { class: "form-input form-control"}
= link_to_remove_association 'Remove', f, class: "form-button btn btn-default"
Ok here is the funny thing, my app doesn't throw any errors. The name, image and ingredients save but the directions do not.
Here is the log
Started POST "/recipes" for ::1 at 2016-02-12 19:00:07 -0800 Processing by RecipesController#create as HTML Parameters: {"utf8"=>"✓", "authenticity_token"=>"YEXiv10mHkfdLPRFGHFGNJX2szJQVXK7gezeakEFbe+57afx6Ih1UjRS6tJNftDLsMI5NS1W84pf2sRhQi0J8g==", "recipe"=>{"title"=>"Honey Apple Chicken", "image"=>#, @original_filename="Honey-Mustard-Chicken-and-Apples.jpg", @content_type="image/jpeg", @headers="Content-Disposition: form-data; name=\"recipe[image]\"; filename=\"Honey-Mustard-Chicken-and-Apples.jpg\"\r\nContent-Type: image/jpeg\r\n">, "ingredients_attributes"=>{"1455332308170"=>{"name"=>"Chicken Thighs", "_destroy"=>"false"}, "1455332308175"=>{"name"=>"Honey", "_destroy"=>"false"}}, "directions_attributes"=>{"1455332325877"=>{"step"=>"Brown Chicken with skin on.", "_destroy"=>"false"}, "1455332325880"=>{"step"=>"Add apples", "_destroy"=>"false"}}}, "commit"=>"Create Recipe"} User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] Unpermitted parameter: step Unpermitted parameter: step (0.1ms) begin transaction Recipe Exists (0.2ms) SELECT 1 AS one FROM "recipes" WHERE "recipes"."image" = ? LIMIT 1 [["image", "1455332407-84040-0233/Honey-Mustard-Chicken-and-Apples.jpg"]] SQL (0.4ms) INSERT INTO "recipes" ("title", "image", "user_id", "created_at", "updated_at") VALUES (?, ?, ?, ?, ?) [["title", "Honey Apple Chicken"], ["image", "1455332407-84040-0233/Honey-Mustard-Chicken-and-Apples.jpg"], ["user_id", 1], ["created_at", "2016-02-13 03:00:07.756946"], ["updated_at", "2016-02-13 03:00:07.756946"]] SQL (0.2ms) INSERT INTO "ingredients" ("name", "recipe_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Chicken Thighs"], ["recipe_id", 1], ["created_at", "2016-02-13 03:00:07.758440"], ["updated_at", "2016-02-13 03:00:07.758440"]] SQL (0.1ms) INSERT INTO "ingredients" ("name", "recipe_id", "created_at", "updated_at") VALUES (?, ?, ?, ?) [["name", "Honey"], ["recipe_id", 1], ["created_at", "2016-02-13 03:00:07.759655"], ["updated_at", "2016-02-13 03:00:07.759655"]] (2.5ms) commit transaction Redirected to http://localhost:3000/recipes/1 Completed 302 Found in 1499ms (ActiveRecord: 3.5ms)
Started GET "/recipes/1" for ::1 at 2016-02-12 19:00:09 -0800 Processing by RecipesController#show as HTML Parameters: {"id"=>"1"} Recipe Load (0.3ms) SELECT "recipes".* FROM "recipes" WHERE "recipes"."id" = ? LIMIT 1 [["id", 1]] User Load (0.2ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1 [["id", 1]] Ingredient Load (0.3ms) SELECT "ingredients".* FROM "ingredients" WHERE "ingredients"."recipe_id" = ? [["recipe_id", 1]] Direction Load (0.1ms) SELECT "directions".* FROM "directions" WHERE "directions"."recipe_id" = ? [["recipe_id", 1]] User Load (0.1ms) SELECT "users".* FROM "users" WHERE "users"."id" = ? ORDER BY "users"."id" ASC LIMIT 1 [["id", 1]] Rendered recipes/show.html.haml within layouts/application (9.2ms) Completed 200 OK in 47ms (Views: 41.2ms | ActiveRecord: 1.0ms)
I don't understand Karl's answer to his own question: Rails 4.1 Nested Attributes and Fields For Getting Unpermitted Parameters and Not Saving If you can see anything, you are Macgyver!