Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Specify currently grabbed records within Model class method

I have a class method where I want to modify the records that are currently grabbed by an ActiveRecord::Relation object. But I don't know how to refer to the current scope in a class method. self does not do it.

Example:

class User < ActiveRecord::Base
  ...

  def self.modify_those_records
    #thought implicitly #to_a would be called on currently grabbed records but doesn't work
    temp_users_to_a = to_a
    ...
  end
end

I would use it like this:

User.some_scope.modify_those_records

So User.some_scope would return to me an ActiveRecord::Relation that contains a bunch of User records. I then want to modify those records within that class method and then return them.

Problem is: I don't know how to explicitly refer to "that group of records" within a class method.

like image 531
Neil Avatar asked Mar 16 '16 15:03

Neil


2 Answers

You can use current_scope:

def self.modify_those_records
  current_scope.each do |user|
    user.do_something!
  end
end

If you want to order Users based on their admin rights, you would be better to use ActiveRecord:

scope :order_admins_first, order('CASE WHEN is_admin = true THEN 0 ELSE 1 END, id')
User.some_scope.order_admins_first

This code implies that you have a boolean column is_admin on the users table.

like image 77
MrYoshiji Avatar answered Sep 22 '22 17:09

MrYoshiji


I would argue that a combination of a scope with each and an instance method is easier to understand than a class method. And as a bonus it is easier to test, because you can test all steps in isolation:

Therefore instead of User.some_scope.modify_those_records I would do something like:

User.some_scope.each(&:modify)

and implement a instance method:

# in user.rb
def modify
  # whatever needs to be done
end
like image 45
spickermann Avatar answered Sep 25 '22 17:09

spickermann