Brioproject Brioproject - 5 months ago 35
Ruby Question

cocoon gem attributes not saving when creating new recipe

week 3 of mckenziechild-recipe box, I am experience 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 existing recipe everything is fine. error message is: Ingredients recipe must exist, directions recipe must exist What am I doing wrong. I am using rails 5

recipe model

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


recipe controller
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 flaish message and render to new page for another shot to 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 flasha 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


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'


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'

Answer

But when i update 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:

Comments