1

I am working on a Rails 4 app and trying to implement HABTM relationship between Category and Recipe. I am getting the above error. I followed a railscast that worked in the video but didn't work for me. I added strong parameters.

Schema:

create_table "categories", force: :cascade do |t|
    t.string   "name"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  create_table "categories_recipes", id: false, force: :cascade do |t|
    t.integer "category_id"
    t.integer "recipe_id"
  end

  create_table "recipes", force: :cascade do |t|
    t.string   "name"
    t.string   "source"
    t.string   "servings"
    t.string   "comment"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

Models:
class Category < ActiveRecord::Base
  has_and_belongs_to_many :recipes

  validates :name, :presence => true
end

class Recipe < ActiveRecord::Base
  has_and_belongs_to_many :categories

  validates :name, :presence => true
  validates :source, :presence => true
  validates :servings, :presence => true
  validates :comment, :presence => true
end

Form:

<%= form_for @recipe do |f| %>
  <p>
    <%= f.label :name %>
    <%= f.text_field :name %>
  </p>
  <p>
    <%= f.label :source %>
    <%= f.text_field :source %>
  </p>
  <p>
    <%= f.label :servings %>
    <%= f.text_field :servings %>
  </p>
  <p>
    <%= f.label :comment %>
    <%= f.text_field :comment %>
  </p>

  <%= hidden_field_tag 'recipe[category_ids]', nil %>
  <% Category.all.each do |category| %>
    <p>
      <%= check_box_tag 'recipe[category_ids][]', category.id, @recipe.category_ids.include?(category.id) %>
      <%= category.name %>
    </p>
  <% end %>

  <%= f.submit %>
<% end %>

recipes_controller.rb:

def create
    @recipe = Recipe.new(recipe_params)
    if @recipe.save
      redirect_to recipes_path
    else
      render :new
    end
  end

  private
  def recipe_params
    params.require(:recipe).permit(:name, :source, :servings, :comment, {category_ids:[]})
  end

layout.html.erb

<!DOCTYPE html>
<html>
<head>
  <title>Friends</title>
  <%= stylesheet_link_tag    'application', media: 'all', 'data-turbolinks-track' => true %>
  <%= javascript_include_tag 'application', 'data-turbolinks-track' => true %>
  <%= csrf_meta_tags %>
</head>
<body>

<%= yield %>

</body>
</html>
jkfairless
  • 41
  • 5
  • 1
    Have you checked out this question? http://stackoverflow.com/questions/3364492/actioncontrollerinvalidauthenticitytoken – wspurgin Oct 20 '15 at 23:05
  • 1
    try removing the {braces} from around `category_ids:[]` in the strong parameters. – Toby 1 Kenobi Oct 20 '15 at 23:06
  • I tried that but it didn't change anything. Thanks anyway. – jkfairless Oct 20 '15 at 23:35
  • are you caching the page that has the new recipe form, or are you working behind a proxy that caches pages? – Toby 1 Kenobi Oct 21 '15 at 00:33
  • Your form is not including the authenticity token that Rails is expecting. Check the link in the first comment for solutions. – Sunil D. Oct 21 '15 at 02:19
  • You appear to be using `form_for` correctly so the authenticity token should be included. Check the page source for the form in a browser and look for a hidden field with the token near the top of the form. Is it there? – Toby 1 Kenobi Oct 21 '15 at 02:41

1 Answers1

0

The error is to do with CSRF (Cross-Site Request Forgery)

This basically means you've either not got your csrf_meta_tags meta tag set in your layout, or you've got an issue within your controller itself.

Using the form_for helper (as you are) with the CSRF meta tag should fix this.


As an aside, you may wish to use the multi declaration for your validates:

#app/models/recipe.rb
class Recipe < ActiveRecord::Base
  validates :name, :source, :servings, :comment, presence: true
end

... and some loops for your form:

<%= form_for @recipe do |f| %>
  <% %i(name source servings comment).each do |attr| %>
     <%= f.label attr %>
     <%= f.text_field attr %>
  <% end %>   
  <%= f.collection_check_boxes :category_ids, Category.all, :id, :name %>
  <%= f.submit %>
<% end %>

You also shouldn't be using <p> tags for formatting - use CSS.

You can use the margin property in CSS to achieve the result you want:

form input {
   margin: 10px 0;
}
Richard Peck
  • 73,250
  • 8
  • 84
  • 139
  • 1
    I have the scrf_meta_tags in my layout. See above. Can't see any problems with my controller. Im a newbie, so I don't fully understand all of this, but would like to. Thanks for the tips! I really like the looping thru the form! – jkfairless Oct 23 '15 at 01:43