Using AlterEgo with ActiveRecord
- 0 comments
- tagged with alterego, rails, ruby, code
Today after finding the gem AlterEgo and falling in love with the API, @chendo and I came to a sad realisation that its beauty was skin-deep. It seems it is not ActiveRecord-aware and overrides #state and #state= on your models. This means that your state column goes untouched and your models are always in the default state.
To get around this, @chendo and I hacked together this little monkey patch which does two things:
- It adds question methods for each of your defined states. So if you have states:
active,inactive, andbannedon yourUsermodel, your instances will have#active?,#inactive?, and#banned?defined. - It properly sets and gets the state of the row and loads it into AlterEgo.
Here is the code:
module AlterEgodef self.included(base)base.instance_eval do# This will allow us to define a question method for each state in a class# For instance if user has states :active and :inactive, methods active? and inactive?# will be defined when first calleddef method_missing_with_states(method, *args, &block)beginmethod_missing_without_states(method, *args, &block)rescue NoMethodError => estate_found = falseresult = nilbase.states.keys.each do |state|if method.to_s == "#{state}?" && !state_foundself.class.send :define_method, "#{state}?" doself.state == stateendstate_found = trueresult = self.__send__(method)endendraise(e) unless state_foundresultendendalias_method_chain :method_missing, :states# state setter to write to databasedefine_method :state= do |value|write_attribute(:state, value.to_s)end# state getter to read from databasedefine_method :state_with_active_record do(read_attribute(:state) || (self.state = state_without_active_record)).to_symendalias_method_chain :state, :active_recordendendend