Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to always use the base class and ignore STI in Rails?

I have a module that I'm including in several models with this content:

self.class.find_by_foo(bar)

Everything was fine until I started using STI. That line should always generate the query

select * from table where foo=bar"

and not

select * from table where foo=bar AND type="Whatever"

Is there a simple way to avoid it?

I though of two solutions. Walking up the class hierarchy until I find the top-most class before ActiveRecord::Base or run the query by hand, like:

self.class.find_by_sql("select * from #{self.class.table_name} where foo=bar")

I don't like either solution. Is there a better one?

like image 400
pupeno Avatar asked Feb 11 '12 17:02

pupeno


2 Answers

First, you can always get to the base class with the method base_class:

self.class.base_class.find_by_foo(bar)

However, in your example above, you shouldn't have to access the base class. You can just do the following and Rails will know the correct table name:

self.class.where(:foo => bar)

There are actually very few cases when you need to access the base class.

like image 113
user1751223 Avatar answered Oct 24 '22 16:10

user1751223


Until there's a better answer, I'm using this code to find the base class of the STI chain:

klass = self.class
self.class.ancestors.each do |k|
  if k == ActiveRecord::Base
    break # we reached the bottom of this barrel
  end
  if k.is_a? Class
    klass = k
  end
end
like image 27
pupeno Avatar answered Oct 24 '22 15:10

pupeno