3

Hoping someone can suggest a fix here. I am fairly new to Rails, and exploring the changes in Rails 4.0. I built this simple recipe book app in Rails 4.0. I have a main model for recipes (name, cook_time, oven_temp, instructions, etc.). Because some recipes may have 5 ingredients and others may have 20, I wanted to break ingredients out in a separate model with a has_many association. So Recipes has_many Ingredients and accepts_nested_attributes_for :ingredients. Here are the models:

recipe.rb

class Recipe < ActiveRecord::Base
  belongs_to :user
  belongs_to :category
  has_many :ingredients, :dependent => :destroy

  validates :name, presence: true, length: { maximum: 50 }

  accepts_nested_attributes_for :ingredients, 
                :reject_if => lambda { |a| a[:name].blank? },
                            :allow_destroy => true
end

ingredient.rb

class Ingredient < ActiveRecord::Base
  belongs_to :recipe
end

Reminder: Rails 4.0 no longer uses attr_accessible, but moves assignment into the controller with strong params.

recipes_controller.rb

class RecipesController < ApplicationController
  before_action :find_recipe, only: [:show, :edit, :update, :destroy]
  before_action :set_current_user, except: [:index, :show]
  respond_to :html, :js

  ...

  def edit
  end

  def update
    if @recipe.update_attributes(recipe_params)
      redirect_to @recipe
    else
      render :edit
    end
  end

...

  def find_recipe
    @recipe = Recipe.find(params[:id])
  end

private

  def recipe_params
    params.require(:recipe).permit( :id, :name, :category_id, :cook_time, :oven_temp, :calories, :instructions, :notes, :email, ingredients_attributes: [:id, :name])
  end

end

I'm using the excellent Cocoon gem from nathanvda to manage nested form fields dynamically, and it works great in 'recipes#new', and saves the information correctly. However, the ingredients fields do not appear in the 'recipes#edit' view! Here is the code for my 'form' and ingredients_fields partials.

_form.html.erb (abbreviated)

<%= form_for @recipe, html: { class: 'form-horizontal' } do |f| %>

  <fieldset>
  <legend>Main Information</legend>

    <div class="field form-group">
      <%= f.label :name, "Recipe name", class: "col-lg-2 control-label" %>
      <div class="col-lg-5">
        <%= f.text_field :name, class: "form-control" %>
      </div>
    </div>

    <div class="field form-group">
      <%= f.label :cook_time, class: "col-lg-2 control-label" %>
      <div class="col-lg-5">
        <%= f.text_field :cook_time, class: "form-control" %>
      </div>
    </div>
...
  </fieldset>

  <legend>Ingredients</legend>
  <p>Number of ingredients: <%= f.object.ingredients.count unless f.object.ingredients.nil? %></p>
  <fieldset id="ingredients">
    <% f.fields_for :ingredients do |builder| %>
      <%= render 'ingredient_fields', :f => builder %>
    <% end %>
    <p class="links">
      <%= link_to_add_association 'add ingredient', f, :ingredients, { class:"btn btn-primary" } %>
    </p>
  </fieldset>

  <fieldset>
  <legend>How to make it</legend>
  <div class="field form-group">
    <%= f.label :instructions, class: "col-lg-2 control-label" %>
      <div class="col-lg-5">
        <%= f.text_area :instructions, class: "form-control", rows: "7" %>
      </div>
    </div>
 ...
    </div>
  </fieldset>
<% end %>

_ingredients_fields.html.erb

<div class="nested-fields">
  <div class="form-group">
    <%= f.label :name, "Ingredient", class: "col-lg-2 control-label" %>
    <div class="col-lg-5">
      <%= f.text_field :name, class: "form-control" %>
    </div>
    <%= link_to_remove_association "remove", f %>
  </div>
</div>

As I said, pretty simple, removed all error checking and messaging, just the basics. Any ideas about what I am missing? I know there are ingredients in the recipe as I load edit from a show view. Thanks in advance for any advice!

Kevin

Andrew Grimm
  • 78,473
  • 57
  • 200
  • 338
user2670683
  • 243
  • 1
  • 3
  • 7

2 Answers2

6

Ack. it was as simple as an '=' sign - must have looked at the <% f.fields_for... %> a thousand times and just didn't notice I'd missed adding the <%=.

user2670683
  • 243
  • 1
  • 3
  • 7
0
<%= f.fields_for :ingredients do |builder| %>
NathanOliver
  • 171,901
  • 28
  • 288
  • 402
  • 1
    Welcome to Stack Overflow! While this code snippet may solve the question, [including an explanation](//meta.stackexchange.com/questions/114762/explaining-entirely-code-based-answers) really helps to improve the quality of your post. Remember that you are answering the question for readers in the future, and those people might not know the reasons for your code suggestion. Please also try not to crowd your code with explanatory comments, this reduces the readability of both the code and the explanations! – Suraj Rao Jul 19 '17 at 11:32