Newb - Active Records question

Can you sort a result set? I’d like to have a generic query, but be
able to order it by one of the cols if a param is set.

ie
@records = Cars.find(:all, :conditions => [“color = ‘Red’”], :order =>
“sales” )
@records.Orderby(“Year”)

Sure, a result set is really just an array of model objects, so you can
do something like:

@records.sort_by {|record| record.year}

but why wouldn’t you just do the sort in the find? Your original code
retrieves the records ordered by sales and then immediately discards
that order to reorder by year. It makes more sense to just retrieve the
records in the order you want in the first place:

if param_is_set
@records = Cars.find(:all, :conditions => [‘color = ?’, ‘red’], :order
=> ‘year’)
else
@records = Cars.find(:all, :conditions => [‘color = ?’, ‘red’], :order
=> ‘sales’)
end

Thanks for the tip Chris.

The reason I wanted to know how to sort was in a few instances I need
information that would come from the same set of data but sorted
differently. Just trying to skip a few trips to the DB.

If I can ask another question, how do you simplify this:

cars
id, model_id,…

models
id, description…

and if I want to have the query pull in that model description how would
I do so? Currenly I was using joins, but thought Active Record must
have a better way of doing so.

@records = Car.find(:all,
:select => " cars.*, model.description",
:joins => " models",
:conditions => [‘color = ? AND models.id = cars.model_id’, ‘red’],
:order => ‘year’)

It works, but looks fugly.

Alex T. wrote:

@records = Car.find(:all,
:select => " cars.*, model.description",
:joins => " models",
:conditions => [‘color = ? AND models.id = cars.model_id’, ‘red’],
:order => ‘year’)

It works, but looks fugly.

Yep, that’s definitely more complicated than it needs to be. All you
need to do is:

@records = Car.find(:all,
:include => :model,
:conditions => [‘color = ?’, ‘red’],
:order => ‘year’)

ActiveRecord will create the join for you. (You can also leave the
select line as you had it, if you want to make sure no other columns
from the models table get loaded for some reason.)

Just make sure you have belongs_to :model in your Car model and has_many
:cars in your Model … uh … model. :smiley:

Hope this helps!

Hmm, its not quite working how I expected.

I put the has and belongs to in the model, and even after a reboot I get
the following:
test = Cars.find(:all, :include => :make, :conditions => […])

:I changed Model to Make, just to make things a little less murky

and when I run a debug on the screen I see:

  • !ruby/object:Car
    attributes:
    model_id: 2322
    id: 3551
    date: 2006-11-03 00:00:00 -06:00

    Make: &id001 !ruby/object:Make
    attributes:
    description: “BMW”
    id: 2322

  • !ruby/object:Car
    attributes:
    model_id: 2322
    id: 3547
    date: 2006-11-03 00:00:00 -06:00
    Make: *id001

  • !ruby/object:Car
    attributes:
    employee_id: 2457
    id: 3583
    pay_date: 2006-12-03 00:00:00 -06:00
    pay_type_id: 4
    active: 1
    Make: &id002 !ruby/object:Employee
    attributes:
    id: 2457
    description: “Buick”

Which pulls in the info, but if I try to access the data
<% test.each do |x| %>
<%= x.description %>
<% end %>

I get
“undefined method `description’ for #Car:0x2afab44d08b8

but the following works
<% test.each do |x| %>
<%= x.make.description %>
<% end %>

Any way to do this w/o having to write the ‘make’ in there? I can
rewrite my code, just wondering if there is another way to do this.

Thanks

Alex

Alex T. wrote:

but the following works
<% test.each do |x| %>
<%= x.make.description %>
<% end %>

Any way to do this w/o having to write the ‘make’ in there? I can
rewrite my code, just wondering if there is another way to do this.

You could probably do it by defining your own “description” method in
your Car model, but in my opinion, you’ll be much better off in the long
run changing your code to the way you have it above. This is the
standard way to access columns in related tables, and sticking to it
will make it easier for other people to read your code, and for you to
read other people’s code.

It more accurately reflects your actual database structure: your cars
table doesn’t have a description, but it does have a make (through the
make_id column), and your make table has a description column. So, car
-> make -> description … which matches up perfectly in your ruby code
with car.make.description. Does this make sense?

Yep, that is crystal clear. With that being the standard way of writing
the code, I will just plan on changing things to that style.

By all means tell me to stop bugging you at any point, but heres another
one.

I have an employees table, and another table (sales) references it…
twice.
so I have an employee_id, and supervisor columns, both of which are just
employee_id numbers.

So if I wanted to write a query to get their names, how would I do it?

this would work for one column:
@records = Sale.find(:all,
:include => :employee, #matches on employee_id column
)

but how to do the second?

sweet, thanks again!

Just to ask it right away, if you have more tables would it be

@records = Car.find(:all,
:include => :model,
:include => :engine,
:conditions => [‘color = ?’, ‘red’],
:order => ‘year’)

or more like
@records = Car.find(:all,
:include => [:model, :engine],
:conditions => [‘color = ?’, ‘red’],
:order => ‘year’)

or something else?

Just make sure you have belongs_to :model in your Car model and has_many
:cars in your Model … uh … model. :smiley:

yeah, for examples, I should pick better names sometimes. =P

Chris G. wrote:

Alex T. wrote:

@records = Car.find(:all,
:select => " cars.*, model.description",
:joins => " models",
:conditions => [‘color = ? AND models.id = cars.model_id’, ‘red’],
:order => ‘year’)

It works, but looks fugly.

Yep, that’s definitely more complicated than it needs to be. All you
need to do is:

@records = Car.find(:all,
:include => :model,
:conditions => [‘color = ?’, ‘red’],
:order => ‘year’)

ActiveRecord will create the join for you. (You can also leave the
select line as you had it, if you want to make sure no other columns
from the models table get loaded for some reason.)

Just make sure you have belongs_to :model in your Car model and has_many
:cars in your Model … uh … model. :smiley:

Hope this helps!