Question

I have a model with a has_many relationship, and a scope to determine whether or not it has any children, such as:

  scope :with_nomination, :include => [:nomination], :conditions => "nominations.service_id IS NOT NULL"

Using this, I can do something like Service.with_nomination and receive a list of all services with nomination children.

The problem is that when I do something like Service.select("id, firstName, lastName").with_nomination ActiveRecord in essense does a SELECT * FROM services which is very bad and does not utilize the indexes I so painstakingly set up.

How can I either rephrase my query or modify my scopes to work with the .select() command?

Was it helpful?

Solution

Turns out in the syntax I was using, a select is not possible, so it does a select * and any further selects are already overriden.

I re-wrote the scopes like so:

scope :no_nomination, joins("LEFT JOIN nominations ON nominations.service_id = services.id").where("nominations.service_id IS NULL")
# important distinction here, the left join allows you to find those records without children

scope :with_nomination, joins(:nomination).where("nominations.service_id IS NOT NULL")

Using this syntax allows me to do something like Service.select(:id,:user,:otherfield).with_nomination

OTHER TIPS

8 years later...

This is ugly, but you could also convert the resulting ActiveRecord::Relation into to sql with to_sql and run the command manually with ActiveRecord::Base.connection.execute.

It might look like this:

query = Service.select("id, firstName, lastName").with_nomination.to_sql
records = ActiveRecord::Base.connection.execute(query)
records.first["firstName"] # => First Name

This doesn't eliminate the excess columns that the scope retrieves, and you have to access each field with string keys, but hey, at least you can still access them!

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top