问题
In week 3 of mackenziechild-recipe_box, I am experiencing some issues with Cocoon. I have devise installed, as well, and my ingredients
and directions
attributes are not being saved when I create a new Recipe
. But when I update an existing Recipe
, everything is fine. The error message is:
Ingredients recipe must exist, directions recipe must exist
What am I doing wrong? I am using rails 5
app/models/recipe.rb
class Recipe < ApplicationRecord
validates :title, :description, :image, presence: true
has_attached_file :image, styles: { medium: "400x400#" }
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
belongs_to :user
has_many :ingredients
has_many :directions
accepts_nested_attributes_for :ingredients, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :directions, :reject_if => :all_blank, :allow_destroy => true
end
app/controllers/recipes_controller.rb
def new
@recipe = Recipe.new
@recipe = current_user.recipes.build
end
def create
@recipe = Recipe.new(recipe_params)
@recipe = current_user.recipes.build(recipe_params)
if @recipe.save
# show a success flash message and redirect to the recipe show page
flash[:success] = 'New recipe created successfully'
redirect_to @recipe
else
# show fail flash message and render to new page for another shot at creating a recipe
flash[:danger] = 'New recipe failed to save, try again'
render 'new'
end
end
def update
if @recipe.update(recipe_params)
# display a success flash and redirect to recipe show page
flash[:success] = 'Recipe updated successfully'
redirect_to @recipe
else
# display an alert flash and remain on edit page
flash[:danger] = 'Recipe failed to update, try again'
render 'edit'
end
end
private
def recipe_params
params.require(:recipe).permit(:title, :description, :image,
directions_attributes: [:id, :step, :_destroy],
ingredients_attributes: [:id, :name, :_destroy])
end
def recipe_link
@recipe = Recipe.find(params[:id])
end
app/views/recipes/_ingredient_fields.html.haml partial
.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'
app/views/recipes/_direction_fields.html.haml partial
.form-inline.clearfix
.nested-fields
= f.input :step, input_html: { class: 'form-input form-control' }
= link_to_remove_association 'Remove', f, class: 'form-button btn btn-default'
回答1:
But when I update an existing
Recipe
, everything is fine.
That's your answer. When you're creating a new recipe, you don't have the recipe object, because it's in the server memory. But when you're updating it, the recipe object is persisted.
That's why you're getting the Ingredients recipe must exist
and directions recipe must exist
error.
To fix that you have to add the inverse_of
in the associations.
class Recipe
has_many :ingredients, inverse_of: :recipe
has_many :directions, inverse_of: :recipe
class Ingredient
belongs_to :recipe, inverse_of: :ingredients
class Direction
belongs_to :recipe, inverse_of: :directions
When you include the inverse_of
, Rails now knows about those associations and will "match" them in memory.
More about inverse_of
:
- http://guides.rubyonrails.org/association_basics.html
- http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
来源:https://stackoverflow.com/questions/37796204/cocoon-gem-attributes-not-saving-when-creating-new-recipe