scope through associations : joins and merge

2019-08-08 03:07发布

问题:

I have three models : User, Product and Transaction. (Transaction belongs_to both, and User has many Product and Product has many User, through Transaction)

In my Transaction model, I have a scope for current transactions :

scope :current, -> { where 'transactions.start_date IS NOT NULL AND transactions.end_date IS NULL' }

I want to be able to do that in the console, in order to retrieve all the products that have a current transaction :

User.first.products.owned

In the console, I can make it happen with :

User.first.products.merge(Transaction.current.ownership)

First try

So I add this in my Product model :

def self.owned
  merge(Transaction.current.ownership)
end

I type that in the console :

User.first.products.owned

But here what's rails console tells me :

NoMethodError: undefined method `merge' for #<Class:0x00000004e2c0f8>
    from /home/flo/.rvm/gems/ruby-2.0.0-p195/gems/activerecord-4.0.0.rc1/lib/active_record/dynamic_matchers.rb:22:in `method_missing'

Other try

If I add this in my Product model :

def self.owned
  joins(:transactions).merge(Transaction.current.ownership)
end

I type that in the console :

User.first.products.owned

But it retrieve all products with a current transaction, and not only the first user's products with a current transaction.

Do you have any idea of what I'm doing wrong ?

回答1:

Of cause you just didnt oder or limit your products.

scope :current, where('transactions.start_date IS NOT NULL AND transactions.end_date IS NULL').order("by whatever").limit(1)

You may need to order it the right product is selected if not you can remove the order method.



回答2:

  1. First try : you're calling merge on a Product but merge I believe needs to be called explicitly on an AR::Relation unlike where, joins & so on.

  2. Second try : the joins is messing up the User scope.

I suggest you use the method scoped (for rails < 4) or all (for rails >= 4) which will proxy an AR::Relation needed for the method merge to function.

def self.owned
  scoped.merge(Transaction.current.ownership)
end