8

How can I write the following default scope:

class SimilarMerchant < ActiveRecord::Base

  # relationships
  belongs_to :merchant
  belongs_to :similar_merchant, :foreign_key => 'similar_merchant_id', :class_name => "Merchant"

  # scopes
  default_scope order('merchants.is_paid DESC').order('score DESC')

end

Basically I want to sort by a merchant.is_paid field (which belongs to a related model)

Any advice?

Jacob
  • 6,317
  • 10
  • 40
  • 58

3 Answers3

14

Try this:

default_scope joins(:merchant).order('merchants.is_paid DESC, score DESC')

And please bear in mind it can be slow, depending on the number of the records

Marek Sebera
  • 39,650
  • 37
  • 158
  • 244
Marek Příhoda
  • 11,108
  • 3
  • 39
  • 53
6

here's what you could do to have required functionality but it's not great idea to do so, please read until the end

you can define your default scope to also include merchants association and then order by merchants.is_paid DESC, score DESC

would look something like

default_scope includes(:merchants).order('merchants.is_paid DESC, score DESC')

however that means every time you grab similar merchant objects for any reason you will have association loaded as well

this is not great and i would suggest to have a explicit scope for loading similar merchants with association and ordering:

scope :with_merchants, includes(:merchants).order(...)

that way you always know in your code what exactly is being loaded from database

keymone
  • 8,006
  • 1
  • 28
  • 33
2

So, do you want all the queries from SimilarMerchant model to be ordered by a column in the merchants? I doubt your requirement, but if it is so you will have to join merchants table also in the default scope

default_scope joins(:merchant).order('merchants.is_paid DESC, similar_merchants.score DESC')

It will be better if you define this as a separate scope and call this scope when you need it like this. Also, you need to decide whether you need the relation merchant or similar_merchant. If you want similar_merchant, you will have to do joins(:similar_merchant).

Note that :merchant is singular. i.e. you have to specify the relationship name specified in model (as in belongs_to :merchant).

rubyprince
  • 17,559
  • 11
  • 64
  • 104