I have two models, Recipe
and Tag
, with a has_and_belongs_to_many
relation. For this relation I have a simple join table, RecipesTags
.
Recipe:
has_and_belongs_to_many :tags
Tag:
has_and_belongs_to_many :recipes
Now upon creating a new recipe, the user gets to fill in which category the recipe belongs to in forms of checkboxes, like "Meat", "Fish", and so on. These categories are in fact just tags in the database.
Problem: the recipes doesn't get any tags saved to it.
Recipe new
and create
controller methods:
def new
@recipe = Recipe.new
@ingredients = Ingredient.all
@tags = Tag.all
respond_to do |format|
format.html # new.html.erb
format.json { render json: @recipe }
end
end
# POST /recipes
# POST /recipes.json
def create
@recipe = Recipe.new(params[:recipe])
if (params[:tags])
@recipe.tags << params[:tags]
end
respond_to do |format|
if @recipe.save
format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
format.json { render json: @recipe, status: :created, location: @recipe }
else
format.html { render action: "new" }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
end
The view:
<%= form_for(@recipe, :html => {:multipart => true}) do |f| %>
<% if @recipe.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(@recipe.errors.count, "error") %> prohibited this recipe from being saved:</h2>
# [ fields that get's saved for the recipe and works fine ]
<% @tags.each do |t| %>
<%= f.label t.name %>
<%= f.check_box :tags, t.name %>
<br />
<% end %>
<%= f.submit 'Submit recipe', :class => 'btn btn-primary' %>
<% end %>
At the moment, I get an error message saying: undefined method `merge' for "Meat":String
"Meat" is the tag name.
So, what am I doing wrong here?
I think the issue is this line @recipe.tags << params[:tags]
.
The association method you're calling with <<
takes an object (in this case expecting a tag object), but in this case it seems you might be passing it a string.
For more info this link may be helpful http://guides.rubyonrails.org/association_basics.html#has_and_belongs_to_many-association-reference, in particular where it refers to collection<<(object, …)
.
In your controller you'll want to do something like @recipe.tags << tag
where tag is a specific tag object.
So, try this:
In your controller
params[:tags].each do |k,v|
@recipe.tags << Tag.find(k)
end
In your view
<% @tags.each do |t| %>
<%= f.label t.name %>
<%= f.check_box "tags[#{t.id}]" %>
<br />
<% end %>
Try this:
def create
@recipe = Recipe.new(params[:recipe])
params[:tags].each do |tag|
@recipe.tags << Tag.find_by_name(tag)
end
respond_to do |format|
if @recipe.save
format.html { redirect_to @recipe, notice: 'Recipe was successfully created.' }
format.json { render json: @recipe, status: :created, location: @recipe }
else
format.html { render action: "new" }
format.json { render json: @recipe.errors, status: :unprocessable_entity }
end
end
end
In view:
<% @tags.each do |t| %>
<%= label_tag t.name %>
<%= check_box_tag "tags[#{t.name}]", t.name %>
<br />
<% end %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With