Constant caching, modules and STI


#1

Hi there,
I’ve been following one of the recipes in the Advanced Rails Recipes
books, and have arrived for my own particular needs at this scenario:

I want to cache some options data in constants at loadtime (as per the
recipe) for dropdown menus in a form
All of the different options are in a single table and use STI.

I have the following module in my initializer folder, with
caches_constant called on the main activerecord data class (RnData):

#######
module ConstantCache
module ClassMethods
def caches_constants
const_set(self.name.to_s.underscore.upcase, [‘my’, ‘array’,
‘here’])
end
end
end

ActiveRecord::Base.send(:extend, ConstantCache::ClassMethods)
########

What happens thus far is that all of the subclasses have a constant
defined with the name of the parent class.

e.g.
RnData::RN_DATA
=> ‘12345’
RnAuto::RN_DATA
=>‘12345’
RnAuto::RN_AUTO

LoadError: Expected /Users/dorian/Sites/mysite/app/models/rn/
rn_auto.rb to define RN_AUTO
from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/
active_support/dependencies.rb:428:in load_missing_constant' from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/ active_support/dependencies.rb:77:inconst_missing_not_from_s3_library’
from /opt/local/lib/ruby/gems/1.8/gems/aws-s3-0.5.1/lib/aws/s3/
extensions.rb:174:in const_missing' from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/ active_support/dependencies.rb:89:inconst_missing’
from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/
active_support/dependencies.rb:439:in load_missing_constant' from /opt/local/lib/ruby/gems/1.8/gems/activesupport-2.2.2/lib/ active_support/dependencies.rb:93:inconst_missing’
from (irb):2

Ideally I would like something along the lines of:

RnData::RN_DATA
RnData::RN_AUTO
RnData::RN_INCOME
or just
RnAuto::OPTIONS
RnIncome::OPTIONS

as long as it has the right info for the subclass in it, and not just
the parent inherited across all subclass.

So, I’m wondering if there’s a way to write this so that it will run
caches_constant for subclass, or do I have to include the
caches_constants line in all my subclasses?

I’ve replacing caches_constants with this which seems to work, but I’m
worried I may be overwriting something critical in activerecord:

class RnData < ActiveRecord::Base
def self.inherited(subclass)
subclass.caches_constants
end
end

any help much appreciated!
thanks
dorian


#2

On 23 Feb 2009, at 15:51, tachekent wrote:

as long as it has the right info for the subclass in it, and not just
the parent inherited across all subclass.

So, I’m wondering if there’s a way to write this so that it will run
caches_constant for subclass, or do I have to include the
caches_constants line in all my subclasses?

The inherited hook as you found below would do the trick. feels a bit
overkill to me - sometimes there is such a thing as too DRY.

I’ve replacing caches_constants with this which seems to work, but I’m
worried I may be overwriting something critical in activerecord:

class RnData < ActiveRecord::Base
def self.inherited(subclass)
subclass.caches_constants
end
end

at the very least call super here or you will be overwriting stuff here.

Fred


#3

The inherited hook as you found below would do the trick. feels a bit
overkill to me - sometimes there is such a thing as too DRY.

Yeah but I have at least 17 subclasses that are basically empty stubs
for looking up the data and setting relationships on a model.


#4

oh, and thanks for the ‘super’ I always wondered what that did :slight_smile: