I an struggling with the syntax of the controller for nested models. There are many other questions out there but i am not having any luck and i have reached my 2 day struggling threshold, so its time to ask!
I have 3 Models, User, Farm, Product. - User has_many Farms, Farm has_many Products.
On the user show page i display a list of farm/s created by the user in a partial...
#users_controller
def show
#user = User.find(params[:id])
#farms = #user.farms
end
#show.html.erb
<% if #user.farms.any? %>
<center><h4>My Farms(<%= #user.farms.count %>)</h4></center>
<hr>
<%= render #farms %>
This works as expected.
What i would like to do is display all the products of the farm, within the _farm partial, as a list. However I dont know what to add to the controller? Adding
#products = Product.find(params[:id])
obviously displays all products, not just one made by that farm. So how to i create the controller code and/or the partial code to only show the products created by that particular farm?
I was thinking along the lines of...
#products = Product.find(params[:farm_id])
but it does not work and seems to simple!
I obviously need to pass a key somewhere to the partial within the partial, but i have no idea how to do it!
Any Help will be massively appreciated...its driving me nuts!
Many thanks, Alex
EDIT ::
#product.rb
class Product < ActiveRecord::Base
attr_accessible :description, :farm_id, :name, :ammount, :price, :category, :pic, :longitude,
:latitude, :image
belongs_to :farm
mount_uploader :image, ImageUploader
#farm.rb
class Farm < ActiveRecord::Base
attr_accessible :content, :name, :user_id, :description, :street_name, :bldg_name, :region, :post_code,
:province, :contact_number, :swap, :organic, :deliver, :image, :products_attributes
belongs_to :user
has_many :products
acts_as_followable
validates :user_id, presence: true
accepts_nested_attributes_for :products
mount_uploader :image, ImageUploader
#user.rb
class User < ActiveRecord::Base
mount_uploader :avatar, ImageUploader
# Include default devise modules. Others available are:
# :token_authenticatable, :confirmable,
# :lockable, :timeoutable and :omniauthable
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :confirmable
# Setup accessible (or protected) attributes for your model
attr_accessible :email, :password, :password_confirmation, :remember_me, :name, :region,
:description, :avatar, :street_name, :bldg_name, :post_code, :province, :contact_number, :avatar,
:avatar_cache, :remove_avatar, :products_attributes, :product
# attr_accessible :title, :body
acts_as_follower
has_many :farms
has_many :swaps
has_many :products, :through => :farms
# validates_presence_of :image
# validates_integrity_of :image
# validates_processing_of :image
has_private_messages
EDIT 2 ::
#_products.html.erb
<hr>
<div class="row-fluid">
<div class="span3"> <%= image_tag product.image_url(:thumb) %> </div>
<div class="span5">
<h2><%= product.name %></h2>
<table>
<tr>
<td><strong>Ammount Available ::</strong></td>
<td><center><%= product.ammount %></center></td>
<td><strong>Kilos</strong></td>
</tr>
<tr>
<td><strong>Price/Kilo ::</strong></td>
<td><center><%= product.price %></center></td>
<td><strong>Euros</strong></td>
</tr></table>
</div>
<br><br><br>
<div class="span3">
<%= link_to "View Product", product, class: "btn btn-small btn-secondary" %>
<% if correct_user?(#user) %>
<%= link_to "delete", product, class: "btn btn-small btn-secondary", method: :delete, confirm: "You sure?" %><% end %>
</div>
-
#_farm.html.erb
<div class="<%= cycle("even", "odd") %>">
<div class="container">
<div class="row-fluid">
<div class="span2">
<%= image_tag farm.image_url %>
</div>
<div class="span2">
<%= farm.name %>
</div>
<div class="span4">
<span><%= " Location :: " %><%= farm.user.region %></span><br>
<span><%= " Can it be delivered :: " %><%= farm.deliver ? 'No' : 'Yes' %></span><br>
<span><%= " Is it Organic :: " %><%= farm.organic ? 'Yes' : 'No' %></span><br>
<span class="timestamp">Listed on <%= farm.created_at.strftime("%d %b. %Y") %> </span>
</div>
<div class="span4">
<br>
<br>
<br>
<%= link_to 'Sell A Product', new_farm_product_path(farm), class: "btn btn-small btn-secondary" %>
<%= link_to 'Edit Grow Spot', farm, class: "btn btn-small btn-secondary" %>
</div>
</div><!-- end container -->
</div>
<div class="row-fluid">
<div class="span2"></div>
<div class="span8">
<% for product in farm.products do %>
<%= render :partial => "product", :product => product %>
<% end %>
</div>
<div class="span2"></div>
Using <%= render #farms %> in a view means you must have a partial called _farm.html.erb in app/views/farms
in that partial you can use farm variable:
<% for product in farm.products do %>
<%= product.name %>
<%= product.price %>
....
<% end %>
no need to add something in controller.
update
<% for product in farm.products do %>
<%= render :partial => "product", :locals => { :product => product } %>
<% end %>
in app/views/farms/_product.html.erb
<div class="zzz">
<div><%= product.price %></div>
</div>
Related
Hi I have a primary model, recipes with a has_many association with ingredients, which also has_many recipes, my join table is recipes_ingredients, the join table has the columns recipe_id, ingredient_id, and quantity. The quantity is just a string for how many times that ingredient will be used in that recipe.
I have a form that creates the recipe and saves it in the database at the same time it creates and saves any ingredients that are given in the form with a nested attribute... I cannot for the life of me figure out how to add the quantity for this join-table using this same form. I would appreciate any help you can afford me... thank you so much in advance.
# models/recipe.rb
class Recipe < ApplicationRecord
belongs_to :user
has_many :recipe_ingredients
has_many :ingredients, through: :recipe_ingredients
validates :name, :content, :cook_time, presence: true
def ingredients_attributes=(ingredients_hash)
ingredients_hash.each do |i, ingredients_attributes|
if ingredients_attributes[:name].present?
ingredient = Ingredient.find_or_create_by(name: ingredients_attributes[:name].capitalize!)
if !self.ingredients.include?(ingredient)
self.recipe_ingredients.build(:ingredient => ingredient)
end
end
end
end
# models/ingredient.rb
class Ingredient < ApplicationRecord
has_many :recipe_ingredients
has_many :recipe, through: :recipe_ingredients
validates :name, presence: true
end
# models/recipe_ingredient.rb
class RecipeIngredient < ApplicationRecord
belongs_to :ingredient
belongs_to :recipe
end
# form
<%= form_with(model: instruction, local: true) do |form| %>
<% if instruction.errors.any? %>
<div id="error_explanation">
<h4><%= pluralize(instruction.errors.count, "error") %> prohibited
this instruction from being saved:</h4>
<ul>
<% instruction.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="container">
<div class="row">
<div class="col-sm-6">
<h3 class="text-center">Recipe</h3>
<div class="fields">
<%= form.label :name %><br>
<%= form.text_field :name, :placeholder => "Name" %><br>
<%= form.label "Instructions" %><br>
<%= form.text_area :content, :placeholder => "Recipe
Instructions" %><br>
<%= form.label :cook_time %><br>
<%= form.text_field :cook_time, :placeholder => "(ex,. 45
mins)" %><br>
<%= form.hidden_field :user_id, value: params[:user_id] %>
</div>
</div>
<div class="col-sm-6">
<h3 class="text-center">Ingredients</h3>
<div class="row">
<div class="col-sm-6 checkbox">
<%= form.collection_check_boxes(:ingredient_ids,
Ingredient.all, :id, :name) %>
</div>
<div class="col-sm-6">
<%= form.fields_for :ingredients do
|ingredient_builder| %>
<%= ingredient_builder.text_field :name %><br>
<% end %>
</div>
</div>
</div>
</div>
<div class="row justify-content-center submit-row">
<div class="fields text-center">
<%= form.submit %>
</div>
</div>
</div>[![enter image description here][1]][1]
You should use accepts accepts_nested_attributes_for
Visit for more information:
Rails has_many :through nested form
https://www.pluralsight.com/guides/ruby-ruby-on-rails/ruby-on-rails-nested-attributes
http://guides.rubyonrails.org/form_helpers.html#building-complex-forms
I'm using Rails 3 and have a form that incorporates fields from multiple associated records using fields_for. My models w/relationships are as follows:
class Company < ActiveRecord::Base
has_many: locations, dependent: :destroy
has_many :addresses, through: :locations
has_many :contacts
accepts_nested_attributes_for :locations, :addresses, :contacts
end
class Address < ActiveRecord::Base
has_many :locations
has_many :companies, through: :locations
accepts_nested_attributes_for :locations, :companies
end
class Contact < ActiveRecord::Base
belongs_to :company
accepts_nested_attributes_for :company
end
class Location < ActiveRecord::Base
belongs_to :company
belongs_to :address
accepts_nested_attributes_for :company, :address
end
My controller currently looks like this:
class CompaniesController < ApplicationController
def new
#company = Company.new
#location = #company.locations.build
#address = #company.addresses.build
#contact = #company.contacts.build
end
def create
#company = Company.new(params[:company])
if #company.save
#handle a successful save
flash[:success] = "Company Created Successfully"
redirect_to #company
else
render 'new'
end
end
end
When the form is submitted I get this error: Can't mass-assign protected attributes: addresses_attributes, locations_attributes, contacts_attributes
I've tried changing the create method in the controller to the following:
def create
#company = Company.new(params[:company_name])
#company.addresses.build(params[:address])
#company.locations.build(params[:location])
#company.contacts.build(params[:contact])
if #company.save
#handle a successful save
flash[:success] = "Company Created Successfully"
redirect_to #company
else
render 'new'
end
end
The result with this create method is a server log that says:
> Processing by CompaniesController#create as HTML
Parameters: {"utf8"=>"✓", "authenticity_token"=>"SVDIk5IzY7foo9DULhzY+RWgh/HAA9NqRp6FafWwFDg=", "company"=>{"company_name"=>"New Co", "
addresses_attributes"=>{"0"=>{"address_line_1"=>"231 Main", "address_line_2"=>"", "address_line_3"=>"", "city"=>"Dallas", "state"=>"AL",
"country"=>"USA", "zipcode"=>"74343"}}, "locations_attributes"=>{"0"=>{"location_type"=>"11", "location_name"=>"DFW"}}, "contacts_attribu
tes"=>{"0"=>{"first_name"=>"Joe", "last_name"=>"User", "title"=>"CEO"}}}, "commit"=>"Save Info"}
SQL (24.9ms) BEGIN TRANSACTION
Address Exists (27.6ms) EXEC sp_executesql N'SELECT TOP (1) 1 AS one FROM [addresses] WHERE ([addresses].[address_line_1] IS NULL AND
[addresses].[address_line_2] IS NULL AND [addresses].[address_line_3] IS NULL AND [addresses].[address_line_4] IS NULL AND [addresses].[a
ddress_line_5] IS NULL AND [addresses].[city] IS NULL AND [addresses].[state] IS NULL AND [addresses].[county] IS NULL AND [addresses].[c
ountry] IS NULL AND [addresses].[zipcode] IS NULL)'
SQL (50.8ms) IF ##TRANCOUNT > 0 ROLLBACK TRANSACTION
CACHE (0.0ms) SELECT ##TRANCOUNT
Rendered companies/new.html.erb within layouts/application (9.4ms)
Rendered layouts/_shim.html.erb (0.0ms)
User Load (32.1ms) EXEC sp_executesql N'SELECT TOP (1) [users].* FROM [users] WHERE [users].[remember_token] = N''TZlKZ6Sx06p3mMS9kUJY
GA'''
Notice that although the address_attributes are populated, the params[:address] that's queried is null for all fields. (*Note I have a validator in the address model to ensure each address is unique. There are currently no records in the address table).
How can I properly build and store the records for each model upon submit? Thanks!
UPDATE: I didn't have addresses_attributes, locations_attributes, and contacts_attributes listed in the Company model attr_accessible block. Adding these attributes seems to have resolved the problem of getting the child attributes loaded from the form in the controller and
#company = Company.new(params[:company])
now populates the addresses, locations and contacts, however when I call
if #company.save
the transaction still gets rolled back with the following server log
Started POST "/companies" for 127.0.0.1 at 2013-12-11 11:12:03 -0600
SQL (25.3ms) BEGIN TRANSACTION
SQL (50.4ms) IF ##TRANCOUNT > 0 ROLLBACK TRANSACTION
CACHE (0.0ms) SELECT ##TRANCOUNT
Not sure why the transaction appears to get rolled back on save. I'm using sql server 2008 and tinytds if that helps.
Nested attributes allow you to save attributes on associated records through the parent. Here the parent is the company record and the nested are location, address and contact. Only in company model there requires accepts_nested_attributes_for. There require no accepts_nested_attributes in address, contact and location models which are nested and not the parent.
Ok, so there were multiple problems with my code. I've weeded through them all and wanted to post the final working solution, in case someone else is dealing with has_many through associations and nested forms.
My final models look like this (using Rails 3.2.13):
Company.rb
class Company < ActiveRecord::Base
attr_accessible :locations_attributes, :contacts_attributes, :company_name
has_many :locations, dependent: :destroy
has_many :addresses, through: :locations
has_many :contacts
accepts_nested_attributes_for :locations, :reject_if => :all_blank, :allow_destroy => true
accepts_nested_attributes_for :addresses
accepts_nested_attributes_for :contacts
end
Location.rb
class Location < ActiveRecord::Base
attr_accessible :address_attributes, :address, :created_by, :is_active, :location_name, :location_type, :region_id, :updated_by, :website
belongs_to :company
belongs_to :address
accepts_nested_attributes_for :address, :reject_if => :all_blank
end
Address.rb
class Address < ActiveRecord::Base
attr_accessible :address_line_1, :address_line_2, :address_line_3, :address_line_4, :address_line_5, :city, :country, :county, :created_by, :province, :state, :updated_by, :zipcode
has_many :locations, dependent: :destroy
has_many :companies, through: :location
accepts_nested_attributes_for :locations
end
companies_controller.rb
class CompaniesController < ApplicationController
def new
#company = Company.new
#location= #company.locations.build
#address = #company.addresses.build
#contact = #company.contacts.build
end
def show
#company = Company.find(params[:id])
end
def create
#company = Company.new(params[:company])
if #company.save
#handle a successful save
flash[:success] = "Company Created Successfully"
redirect_to #company
else
render 'new'
end
end
end
new.html.erb
<% provide(:title, 'Create Company')%>
<h1>Create Company</h1>
<div class="container">
<%= form_for(#company) do |f| %>
<% if #company.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#company.errors.count, "error") %> prohibited this company from being saved:</h2>
<ul>
<% #company.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="row">
<%= f.label :company_name, "Company Name" %>
<%= f.text_field :company_name %>
<hr>
</div>
<div class="row">
<div class="col-md-6"><h3>Primary Location</h3><hr></div>
<div class="col-md-6"><h3>Location Information</h3><hr></div>
</div>
<%= f.fields_for(:locations) do |lf| %>
<%= lf.fields_for(:address_attributes) do |af| %>
<%= f.fields_for(:contacts) do |cf| %>
<div class="row" >
<div class="col-md-6"><%= af.label "Address 1"%><%= af.text_field :address_line_1 %></div>
<div class="col-md-6"><%= lf.label "Location Type" %> <%= lf.select(:location_type, options_for_select([["Headquarters",11], ["Office", 12]])) %></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Address 2"%><%= af.text_field :address_line_2 %></div>
<div class="col-md-6"><%= lf.label "Location Name" %> <%= lf.text_field :location_name %></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Address 3"%><%= af.text_field :address_line_3 %></div>
<div class="col-md-6"><h3>Other Location Information</h3><hr></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "City"%><%= af.text_field :city %></div>
<div class="col-md-3"><button type="button" class="btn btn-primary btn-small btn-block">Services Offered</button></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "State"%><%= af.select(:state, options_for_select([["Alabama","AL"], ["Alaska","AK"]])) %></div>
<div class="col-md-3"><button type="button" class="btn btn-primary btn-small btn-block">Materials Accepted</button></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Country"%><%= af.select(:country, options_for_select([["United States","USA"], ["United Kingdom","UK"]])) %></div>
<div class="col-md-3"><button type="button" class="btn btn-primary btn-small btn-block">Location Certifications</button></div>
</div>
<div class="row" >
<div class="col-md-6"><%= af.label "Zipcode"%><%= af.text_field :zipcode %></div>
</div>
<div class="row" >
<div class="col-md-12"><h3>Tell us about you</h3></div>
<hr>
</div>
<div class="row">
<div class="col-md-6"><%= cf.label "First Name"%><%= cf.text_field :first_name %></div>
</div>
<div class="row">
<div class="col-md-6"><%= cf.label "Last Name"%><%= cf.text_field :last_name %></div>
</div>
<div class="row">
<div class="col-md-6"><%= cf.label "Title"%><%= cf.text_field :title %></div>
</div>
<div class="row">
<div class="col-md-2"><%= f.submit "Save Info", class: "btn btn-small btn-primary" %></div>
</div>
<% end %>
<% end %>
<% end%>
<% end %>
The things to notice are how the accepts_nested_attributes_for statements link up the associations, the need to add the appropriate model_attributes in each models attr_accessible statement, and how the form nests the address form (af) within the locations_form (lf) using :addresses_attributes.
Additionally, I had to remove foreign Key (company_id, address_id) validations from Location.rb because they caused the transaction to rollback prior to the Address or Company record being created (a prereq for creating a location)
I am making a polymorphic association with devise and simple for but for some reason i cant get the params to work
here is my code:
User:
class User < ActiveRecord::Base
devise :database_authenticatable,
:rememberable, :trackable, :validatable
belongs_to :loginable, polymorphic: true
end
Designer:
class Designer < ActiveRecord::Base
has_one :user, as: :loginable
accepts_nested_attributes_for :user
end
Layout:
<%= simple_form_for [:admin, #designer] , :html => { :class => 'form-horizontal' } do |f| %>
<% if f.error_notification %>
<div class="alert alert-error fade in">
<a class="close" data-dismiss="alert" href="#">×</a>
<%= f.error_notification %>
<% if #designer.errors.any? %>
<ul>
<% #designer.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
<% end %>
</div>
<% end %>
<div class="control-group">
<%= f.label :profile_name, :class => 'control-label' %>
<div class="controls">
<%= f.text_field :profile_name, :class => 'text_field' %>
</div>
</div>
<%= f.simple_fields_for users do |u| %>
<div class="control-group">
<%= u.label :email, :class => 'control-label' %>
<div class="controls">
<%= u.text_field :email, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= u.label :password, :class => 'control-label' %>
<div class="controls">
<%= u.password_field :password, :class => 'text_field' %>
</div>
</div>
<div class="control-group">
<%= u.label :type, :class => 'control-label' %>
<div class="controls">
<%= u.input :role, :label => false do %>
<%= u.select :role_id, Role.all.map { |r| [r.name, r.id] } %>
<% end %>
</div>
</div>
<div class="control-group">
<%= u.label :firstname, :class => 'control-label' %>
<div class="controls">
<%= u.text_field :firstname, :class => 'text_field' %>
</div>
</div>
<% end %>
<div class="form-actions">
<%= f.submit nil, :class => 'btn btn-primary' %>
</div>
<% end %>
Controller:
def create
#user = User.new(designer_params)
#designer = Designer.new(designer_params)
#user.loginable = #designer
respond_to do |format|
if #user.save! && #designer.save!
format.html { redirect_to admin_designers_path, notice: 'Designer was successfully created.' }
format.json { render action: 'show', status: :created, location: admin_designer_path(#designer) }
else
format.html { render action: 'new' }
format.json { render json: [designer: #designer.errors, user: #user.errors], status: :unprocessable_entity }
end
end
end
def designer_params
params.permit(:profile_name, :user, user_attributes: [:email, :password, :password, :firstname, :lastname, :address, :postalcode, :city, :country, :role, :role_id])
end
My params seems to ignore the user attributes, i only see profile name for some reason.
Any ideas on how to fix this would be greatly appreciated
Thanks!
I managed to resolve my own issues. so i am posting the answer hoping to save someone else lots of time.
i ended up creating another private method for the user params
def designer_params
params.require(:designer).permit(:profile_name, user_attributes: [:email, :password, :password, :firstname, :lastname, :address, :postalcode, :city, :country, :role, :role_id])
end
def user_params
params[:designer][:user_attributes].permit(:email, :password, :password, :firstname, :lastname, :address, :postalcode, :city, :country, :role, :role_id)
end
and then using those to create my relationship
def create
#designer = Designer.new(designer_params)
#user = User.new(user_params)
#user.loginable = #designer
#designer.save!
end
also if you are having trouble viewing the nested form make sure to use the
build_ method
def new
#designer = Designer.new
#user = #designer.build_user
end
I have succsfuly set up an image upload with the carrierwave gem.
but when I try to add an optional online url like so:
<%= form_for #rating, :html => {:multipart=>true} do |f| %>
<div class="field">
<%= f.file_field :pic_url %>
</div>
<div class="field">
<%= f.label :remote_pic_url_url, 'or image url' %>
<br/>
<%= f.text_field :remote_pic_url_url %>
</div>
<div class="actions">
<%= f.submit 'Upload Picture', :class => 'btn btn-primary' %>
</div>
<% end %>
then I get this error:
Can't mass-assign protected attributes:
my model is
class Rating < ActiveRecord::Base
attr_accessible :pic_url, :rating
mount_uploader :pic_url , ImageUploader
end
You need to be able to mass-assign the remote_pic_url_url attribute:
class Rating < ActiveRecord::Base
attr_accessible :pic_url, :remote_pic_url_url, :rating
mount_uploader :pic_url , ImageUploader
end
I am working on building a blog with categorization. I am a bit stuck on how to implement categorization in the form. I have setup a has many through relationship and want to add check boxes to associate a blog with multiple categories. What I have so far is passing the categories through to the view, and I can list them out, however I cannot get the form_for method working for some reason.
Here is my code.
blog model
class Blog < ActiveRecord::Base
attr_accessible :body, :title, :image
has_many :categorizations
has_many :categories, through: :categorizations
has_attached_file :image, :styles => { :medium => "300x300>", :thumb => "100x100>" }
validates :title, :body, :presence => true
end
Category Model
class Category < ActiveRecord::Base
has_many :categorizations
has_many :blogs, through: :categorizations
attr_accessible :name
end
Categorization Model
class Categorization < ActiveRecord::Base
attr_accessible :blog_id, :category_id
belongs_to :blog
belongs_to :category
end
Blog new controller
def new
#blog = Blog.new
#categories = Category.all
respond_to do |format|
format.html # new.html.erb
format.json { render json: #blog }
end
end
Blog new form view
<%= form_for(#blog, :url => blogs_path, :html => { :multipart => true }) do |f| %>
<% if #blog.errors.any? %>
<div id="error_explanation">
<h2><%= pluralize(#blog.errors.count, "error") %> prohibited this blog from being saved:</h2>
<ul>
<% #blog.errors.full_messages.each do |msg| %>
<li><%= msg %></li>
<% end %>
</ul>
</div>
<% end %>
<div class="field">
<%= f.label :title %><br />
<%= f.text_field :title %>
</div>
<div class="field">
<%= f.file_field :image %>
</div>
<div class="field">
<%= f.label :body %><br />
<%= f.text_area :body %>
</div>
<div class="field">
Categories:
<% #categories.each do |category| %>
<% fields_for "blog[cat_attributes][]", category do |cat_form| %>
<p>
<%= cat_form.check_box :name %>
</p>
<% end %>
<% end %>
</div>
<div class="actions">
<%= f.submit %>
</div>
<% end %>
This code is my failing point
<% #categories.each do |category| %>
<% fields_for "blog[cat_attributes][]", category do |cat_form| %>
<p>
<%= cat_form.check_box :name %>
</p>
<% end %>
<% end %>
Although I am not positive I am approaching any of it right since I am currently learning. Any advice on how to accomplish this.
Thanks,
CG
First of all, you probably don't need a separate Categorization model unless there's a use case you haven't described here. You can set up a many-to-many relationship like this:
class Blog < ActiveRecord::Base
has_and_belongs_to_many :categories
end
class Category < ActiveRecord::Base
has_and_belongs_to_many :blogs
end
You should have a database table like this:
class CreateBlogsCategories < ActiveRecord::Migration
def change
create_table :blogs_categories, id: false do |t|
t.references :blog
t.references :category
end
end
end
Then you can construct the view like this:
<div class="field">
Categories:
<% #categories.each do |category| %>
<%= label_tag do %>
<%= check_box_tag 'blog[category_ids][]', category.id, #blog.category_ids.include?(category.id) %>
<%= category.name %>
<% end %>
<% end %>
</div>
Lastly, in your form_for, you specify url: blogs_path - you should remove this if you plan to use this form for the edit action as well, because that should generate a PUT request to /blogs/:id. Assuming you used resources :blogs in routes.rb, Rails will determine the correct path for you based on the action used to render the form.