Newbie: displaying a denormalized list of records


#1

I am trying to list my orders showing customer names rather than
customer IDs. I am not having much luck.

I have a table called orders, having a ‘customer_id’ field. I also have
a table called customers, which has a field called ‘id’, as well as a
field called ‘name’.

In the orders model, I specify that order belongs_to customer, and in
the customer model, I specify that the customer has_many orders.

As a first shot, I assumed that in the list view for orders, I could
replace the working line

           <td><%=h order.send('customer_id') %></td>

with something like

           <td><%=h order.send('order.customer.name') %></td>.

That didn’t work.

My current iteration defines the following method in order.rb

def self.find_all_denormalized
	sql = "	SELECT orders.*,  						               customers.name as 

customerName
From orders left join customers
on customer_id = customers.id
"
orders_denormalized = Order.find_by_sql(sql)
return orders_denormalized
end

and in order_controller.rdb, I have redefined list as

def list
@order_pages, @orders = paginate Order.find_all_denormalized,
:per_page => 10
end

This is not working. I am getting a message like:

wrong constant name
#Order:0x394ba68#Order:0x394ba20#Order:0x394b9d8#Order:0x394b990#Order:0x394b948


Two questions: why is my approach not working, and is there a
fundamentally better (more Rails) way to do this?

Thanks in advance

Ed


#2

hi Ed,

I think part of your problem is that you’re using the built-in paginate
instead of this one:

def paginate_collection(collection, options = {})
default_options = {:per_page => 10, :page => 1}
options = default_options.merge options

 pages = Paginator.new self, collection.size, options[:per_page], 

options[:page]
first = pages.current.offset
last = [first + options[:per_page], collection.size].min
slice = collection[first…last]
return [pages, slice]
end

You should use the above function anytime you want to paginate a
collection returned from a custom query (just add this func to your
application.rb).

As for the rails way to get the customer name, you should be able to do:

order.customer.name

anywhere you have an actual object named ‘order’ (in which case you
won’t need a custom query at all (or the alternate paginate method above
(but it was included for future reference I suppose :)))). This
statement is actually calling a method named ‘customer_id’ of the order
object (see documentation on ‘send’).

<%=h order.send(‘customer_id’) %>

The reason why that part of your code isn’t working is because order has
no method named ‘customer.name’. The proper way to do what you intended
is:

<%=h order.customer.name %>

Hope this helps!
–Jonathan

Ed Schechter wrote:

I am trying to list my orders showing customer names rather than
customer IDs. I am not having much luck.

I have a table called orders, having a ‘customer_id’ field. I also have
a table called customers, which has a field called ‘id’, as well as a
field called ‘name’.

In the orders model, I specify that order belongs_to customer, and in
the customer model, I specify that the customer has_many orders.

As a first shot, I assumed that in the list view for orders, I could
replace the working line

           <td><%=h order.send('customer_id') %></td>

with something like

           <td><%=h order.send('order.customer.name') %></td>.

That didn’t work.

My current iteration defines the following method in order.rb

def self.find_all_denormalized
sql = " SELECT orders.*, customers.name as
customerName
From orders left join customers
on customer_id = customers.id
"
orders_denormalized = Order.find_by_sql(sql)
return orders_denormalized
end

and in order_controller.rdb, I have redefined list as

def list
@order_pages, @orders = paginate Order.find_all_denormalized,
:per_page => 10
end

This is not working. I am getting a message like:

wrong constant name
#Order:0x394ba68#Order:0x394ba20#Order:0x394b9d8#Order:0x394b990#Order:0x394b948


Two questions: why is my approach not working, and is there a
fundamentally better (more Rails) way to do this?

Thanks in advance

Ed