Read more

Take care when joining and selecting on scopes

Arne Hartherz
November 25, 2010Software engineer at makandra GmbH

Occasionally some complex query must be processed on the database because building thousands of Ruby objects is impracticable.

Illustration online protection

Rails Long Term Support

Rails LTS provides security patches for old versions of Ruby on Rails (2.3, 3.2, 4.2 and 5.2)

  • Prevents you from data breaches and liability risks
  • Upgrade at your own pace
  • Works with modern Rubies
Read more Show archive.org snapshot

Many times you would use scope options, like this:

users = User.scoped(
  :joins => 'INNER JOIN orders joined_orders ON users.id = joined_orders.user_id',
  :conditions => [ 'joined_orders.date BETWEEN ? AND ?', start_date, end_date ],
  :select => '*, SUM(joined_orders.amount) AS amount_sum',
  :group => 'users.id'
)

You get ActiveRecord objects and you can ask each of them about its amount_sum -- which is great, but your User objects may not have the actual ID from their row in the users table but one of the joined table.

Ensure that you get the correct user IDs by selecting only from the users table:
users = User.scoped(
:joins => 'INNER JOIN orders joined_orders ON users.id = joined_orders.user_id',
:conditions => [ 'joined_orders.date BETWEEN ? AND ?', start_date, end_date ],
:select => 'users., SUM(joined_orders.amount) AS amount_sum', # note the "users." instead of "*" above
:group => 'users.id'
)

Posted by Arne Hartherz to makandra dev (2010-11-25 11:40)