I'm getting NoMethodError for this line <%= link_to product.category.name, category_path(product.category) %> which are in products_path/index. I'm not sure what's wrong, so asking for help. Thank for any help!
My code
products_controller.rb
class ProductsController < ApplicationController
before_action :set_product, only: [:show, :edit, :update, :destroy]
before_action :authenticate_user!, except: [:index, :show]
def index
@products = Product.all
end
# GET /products/1
def show
@comments = @product.comments.order("created_at DESC").paginate(:page => params[:page], :per_page => 5)
end
# GET /products/new
def new
@product = Product.new
@categories = Category.all.map{|c| [ c.name, c.id ] }
end
# GET /products/1/edit
def edit
@categories = Category.all.map{|c| [ c.name, c.id ] }
end
# POST /products
def create
@product = Product.new(product_params)
@product.category_id = params[:category_id]
respond_to do |format|
if @product.save
format.html { redirect_to :back, notice: 'Product was successfully created.' }
format.json { render :show, status: :created, location: @product }
else
format.html { render :new }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /products/1
def update
@product.category_id = params[:category_id]
respond_to do |format|
if @product.update(product_params)
format.html { redirect_to @product, notice: 'Product was successfully updated.' }
format.json { render :show, status: :ok, location: @product }
else
format.html { render :edit }
format.json { render json: @product.errors, status: :unprocessable_entity }
end
end
end
# DELETE /products/1
def destroy
@product.destroy
respond_to do |format|
format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_product
@product = Product.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def product_params
params.require(:product).permit(:name, :description, :image_url, :color, :price, :year_of_manufacture)
end
end
categories_controller.rb
class CategoriesController < ApplicationController
before_action :set_category, only: [:show, :edit, :update, :destroy]
# GET /categories
def index
@categories = Category.all
end
# GET /categories/1
def show
end
# GET /categories/new
def new
@category = Category.new
end
# GET /categories/1/edit
def edit
end
# POST /categories
def create
@category = Category.new(category_params)
respond_to do |format|
if @category.save
format.html { redirect_to @category, notice: 'Category was successfully created.' }
format.json { render :show, status: :created, location: @category }
else
format.html { render :new }
format.json { render json: @category.errors, status: :unprocessable_entity }
end
end
end
# PATCH/PUT /categories/1
def update
respond_to do |format|
if @category.update(category_params)
format.html { redirect_to @category, notice: 'Category was successfully updated.' }
format.json { render :show, status: :ok, location: @category }
else
format.html { render :edit }
format.json { render json: @category.errors, status: :unprocessable_entity }
end
end
end
# DELETE /categories/1
def destroy
@category.destroy
respond_to do |format|
format.html { redirect_to categories_url, notice: 'Category was successfully destroyed.' }
format.json { head :no_content }
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_category
@category = Category.find(params[:id])
end
# Never trust parameters from the scary internet, only allow the white list through.
def category_params
params.require(:category).permit(:name, :desc)
end
end
Rails routes
products GET /products(.:format) products#index
POST /products(.:format) products#create
new_product GET /products/new(.:format) products#new
edit_product GET /products/:id/edit(.:format) products#edit
product GET /products/:id(.:format) products#show
PATCH /products/:id(.:format) products#update
PUT /products/:id(.:format) products#update
DELETE /products/:id(.:format) products#destroy
category_products GET /categories/:category_id/products(.:format) products#index
POST /categories/:category_id/products(.:format) products#create
new_category_product GET /categories/:category_id/products/new(.:format) products#new
edit_category_product GET /categories/:category_id/products/:id/edit(.:format) products#edit
category_product GET /categories/:category_id/products/:id(.:format) products#show
PATCH /categories/:category_id/products/:id(.:format) products#update
PUT /categories/:category_id/products/:id(.:format) products#update
DELETE /categories/:category_id/products/:id(.:format) products#destroy
categories GET /categories(.:format) categories#index
POST /categories(.:format) categories#create
new_category GET /categories/new(.:format) categories#new
edit_category GET /categories/:id/edit(.:format) categories#edit
category GET /categories/:id(.:format) categories#show
PATCH /categories/:id(.:format) categories#update
PUT /categories/:id(.:format) categories#update
DELETE /categories/:id(.:format) categories#destroy
Solved
I'm not sure what was wrong, but deleted my codes which are below and rewrote it and now I don't get NoMethodError.
_product.html.erb (index.html.erb)
<% cache product do %>
<div class="col-lg-3 col-sm-4 col-md-4 col-xs-12 products">
<div class="product-block">
<div class="product-img-list">
<h3 id="product-name"><%= product.name %></h3>
<%= link_to product_path(product), class: 'product_link' do %>
<span class="product-img-text"><span><h4><i class="glyphicon glyphicon-usd"></i><%= product.price %></h4></span></span>
<%= image_tag(product.image_url, class: "img-responsive") %>
<% end %>
</div>
<p id="product-description"><%= truncate product.description, length: 100 %></p>
<%= link_to Category.find(product.category_id).name, category_path(product.category_id) %>
</div>
<% if signed_in? && current_user.admin? %>
<ul>
<li><%= link_to 'Show', product %></li>
<li><%= link_to 'Edit', edit_product_path(product) %></li>
<li><%= link_to 'Destroy', product, method: :delete, data: { confirm: 'Are you sure?' } %></li>
</ul>
<% end %>
</div><!-- /col -->
<% end %>
If the error says
undefined method `category' for # Product
it is because you did not define the association properly. Please include
belongs_to :category
line in product.rb
model.
If the error description says
undefined method `name' for nil:NilClass
then you need to check whether there are any products
with category
is nil
.