I have what I am sure is a nooby question…
I have a view where I am showing a list of products delivered to customers. I used a couple of Ryan Bates’ railscasts as models for having a search field and sortable columns plus pagination.
Pagination and Search work fine. However, I have two issues that I can’t seem to find:
1) If I try and show the name of the customer, instead of their ID, for a product, I get an error saying the ‘name’ method is not defined.
2) When I click on the column heading to change the sort order, nothing happens.
Here is my code:
Products Controller:
class ProductsController < ApplicationController
# GET /products
# GET /products.json
helper_method :sort_column, :sort_direction
def index
@products = Product.search(params[:search]).order(sort_column + " " + sort_direction).paginate(:per_page => 25, :page => params[:page])
respond_to do |format|
format.html # index.html.erb
format.json { render json: @products }
end
end
.
.
.
private
def sort_column
Product.column_names.include?(params[:sort]) ? params[:sort] : "name"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
end
Products Model:
# == Schema Information
#
# Table name: products
#
# id :integer(4) not null, primary key
# name :string(255)
# serial_number :string(255)
# date_ordered :date
# date_received :date
# date_invoiced :date
# vendor_invoice :string(255)
# scc_invoice :string(255)
# quantity :integer(10)
# dollar_amount :integer(10)
# warranty_years :integer(4)
# warranty_days :integer(4)
# item :integer(4)
# comments :text
# created_at :datetime not null
# updated_at :datetime not null
# vendor_id :integer(4)
# customer_id :integer(4)
# category_id :integer(4)
# department :string(255)
#
class Product < ActiveRecord::Base
attr_protected :id
belongs_to :customer
belongs_to :vendor
belongs_to :category
def self.search(search)
if search
where('name LIKE ?', "%#{search}%")
else
scoped
end
end
end
Product Index View:
<% title "Products" %>
<%= form_tag products_path, :method => 'get', :id => "products_search" do %>
<p>
<%= text_field_tag :search, params[:search] %>
<%= submit_tag "Search", :name => nil%>
</p>
<div id="products"><%= render 'products' %></div>
<% end %>
<p><%= link_to 'Add Product', new_product_path %></p>
Products partial view: _products.html.erb
<%= hidden_field_tag :direction, params[:direction] %>
<%= hidden_field_tag :sort, params[:sort] %>
<table class="pretty">
<tr>
<th><%= sortable "name" %></th>
<th><%= sortable "serial_number" %> </th>
<th><%= sortable "date_invoiced" %></th>
<th>Scc invoice</th>
<th>Customer</th>
<th></th>
<th></th>
</tr>
<% for product in @products %>
<tr>
<td><%= product.name %></td>
<td><%= product.serial_number %></td>
<td><%= product.date_invoiced %></td>
<td><%= product.scc_invoice %></td>
<td><%= product.customer.name %></td>
<td><%= link_to 'Show', product %></td>
<td><%= link_to 'Edit', edit_product_path(product) %></td>
</tr>
<% end %>
<%= will_paginate @products %>
I am not sure what else someone might need to get an idea of what is on so let me know if there is more information needed.
Here is what I see on the server when it runs:
Started GET “/products” for 127.0.0.1 at 2012-06-27 14:04:11 -0600
Connecting to database specified by database.yml
Processing by ProductsController#index as HTML
←[1m←[36mProduct Load (60.0ms)←[0m ←[1mSELECT products.* FROM products ORDER BY name asc LIMIT 25 OFFSET 0←[0m
←[1m←[35m (0.0ms)←[0m SELECT COUNT() FROM products
←[1m←[36mCustomer Load (0.0ms)←[0m ←[1mSELECT customers. FROM customers WHERE customers.id = 0 LIMIT 1←[0m
Rendered products/_products.html.erb (535.0ms)
Rendered products/index.html.erb within layouts/application (660.0ms)
Completed 500 Internal Server Error in 895ms
ActionView::Template::Error (undefined method name' for nil:NilClass):block in _app_views_products__products_html_erb__429528032_35444568′
20: <td><%= product.serial_number %></td>
21: <td><%= product.date_invoiced %></td>
22: <td><%= product.scc_invoice %></td>
23: <td><%= product.customer.name unless product.customer.name.nil? %></td>
24: <td><%= link_to 'Show', product %></td>
25: <td><%= link_to 'Edit', edit_product_path(product) %></td>
26: </tr>
app/views/products/_products.html.erb:23:in
app/views/products/_products.html.erb:16:in _app_views_products__products_html_erb__429528032_35444568'block in _app_views_products_index_html_erb___506300995_27575616′
app/views/products/index.html.erb:8:in
app/views/products/index.html.erb:3:in _app_views_products_index_html_erb___506300995_27575616'index’
app/controllers/products_controller.rb:11:in
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-3.2.5/lib/action_dispatch/middleware/template
s/rescues/_trace.erb (5.0ms)
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-3.2.5/lib/action_dispatch/middleware/template
s/rescues/_request_and_response.erb (5.0ms)
Rendered C:/RailsInstaller/Ruby1.9.3/lib/ruby/gems/1.9.1/gems/actionpack-3.2.5/lib/action_dispatch/middleware/template
s/rescues/template_error.erb within rescues/layout (65.0ms)
OK from your stacktrace we can see that:
This means your customer object is null. So the SQL is not returning a customer object attached to your products objects.
your code here:
does not catch it since you are testing the nil on the name attribute, not the customer object
This should fix the error, but you still wont see the customer name!
To really fix your problem, you have to verify your relationship between Products and Customers in your model code and debug the SQL you get from it to be sure to see a JOIN between products and customer.
Check to see if you have a has_many : products declared in customer object.
UPDATE: I also see in your product model that you declared the customer_id in the product table?! That means your Products can only have 1 customer!!! Not sure it is what you want! 😉
here is a link on the rails guide to relationship, it was my bible when i worked with rails
UPDATE 2
After reviewing the Active Record Query interface, to get what i think you want, you should do something like that: