When defining a class method at an ActiveRecord, if I return self
, the indirect reference is lost.
I'm not sure if I am using the right vocabulary, as I am just learning Ruby on Rails, so here is an example:
class User < ActiveRecord::Base
has_many :orchids
end
class Orchid < ActiveRecord::Base
belongs_to :user
def self.search(query)
if query.present?
query = '%' + query.gsub(/\s+/, '%') + '%'
where 'gender ILIKE :query OR variety ILIKE :query', query: query
else
# Problematic line:
self
end
end
end
Using the above definition, this is what happens:
% User.last.orchids.count
(0.8ms) SELECT COUNT(*) FROM "orchids" WHERE "orchids"."user_id" = $1 [["user_id", 2]]
=> 0
% User.last.orchids.search('').count
(1.2ms) SELECT COUNT(*) FROM "orchids"
=> 449
% User.last.orchids.search('cat').count
(1.2ms) SELECT COUNT(*) FROM "orchids" WHERE "orchids"."user_id" = $1 AND (gender ILIKE '%cat%' OR variety ILIKE '%cat%') [["user_id", 2]]
=> 0
So, returning self
seems to make the indirect scope of "only the orchids of this user" go away. Returning self
there means I'm returning the Orchid
class instead of the ActiveRecord::Relation
?
Reading a bit at the internet, I did find about scopes and why I should use them. Scopes do work the way I expect and I am using them now. I just do not get why this behaves like this when using class method definitions.
Self will return the class because self is the class. As scope returns an ActiveRecord::Relation instance. So the Orchid.where method builds and returns a new ActiveRecord::Relation whereas the self will just return the class itself.
Both can still be chained with additional scopes should you choose. If you really want an AR::Relation back, change self to Orchid.none.