More on Using Enums For Constant Data in Rails
So I got around to rollowing tip #3 on using Enums in AR, and found it worked…. mostly. The problem comes in where the value isn’t already set. I started with this in my model:
# game.rb # at the top of the file, define the list of genders GENDERS = %w( boy girl coed ) # and validations for it validates_inclusion_of :gender, :in => Game::GENDERS, :on => :create, :message => "extension %s is not included in the list" # finally define the gender as a symbol for lookups def gender read_attribute(:gender).to_sym end def gender=(value) write_attribute(:gender, value.to_s) end
This works fine until you have a nil value for gender. OK, next step, just check if the value is nil before you read it and return nil if it is. Only thing is that if you were to add something like
if self.gender.nil? return nil
But then you get an ugly “stack level too deep” error, because when you call ‘self.gender’ it’s calling the gender method, which checks to see if self.gender is nil, which calls the gender method, which… well, you get the picture.
Took a bit of looking, and I’m not sure if this is the “correct” solution, but it does work properly. I just modified the gender method as such:
#game.rb def gender attributes = attributes_before_type_cast if attributes["gender"] read_attribute(:gender).to_sym else nil end end
This uses the attributes_before_type_cast grabs all attributes into a hash (before they are mangled by whatever ActiveRecord does), checks to see if the ‘gender’ attribute is filled in and either returns it or nil. Depending on if you’re learning or not, you may want to just check out the activerecord_symbolize plugin though
All working, and ready to commit to the main branch.