Using AlterEgo with ActiveRecord
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
, andbanned
on yourUser
model, your instances will have#active?
,#inactive?
, and#banned?
- It properly sets and gets the state of the row and loads it into AlterEgo.
Here is the code:
module AlterEgo
def 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 called
def method_missing_with_states(method, *args, &block)
begin
method_missing_without_states(method, *args, &block)
rescue NoMethodError => e
state_found = false
result = nil
base.states.keys.each do |state|
if method.to_s == "#{state}?" && !state_found
self.class.send :define_method, "#{state}?" do
self.state == state
end
state_found = true
result = self.__send__(method)
end
end
raise(e) unless state_found
result
end
end
alias_method_chain :method_missing, :states
# state setter to write to database
define_method :state= do |value|
write_attribute(:state, value.to_s)
end
# state getter to read from database
define_method :state_with_active_record do
(read_attribute(:state) || (self.state = state_without_active_record)).to_sym
end
alias_method_chain :state, :active_record
end
end
end
Comments
None yetYou need to login with GitHub in order to comment.