Yet Another request to help DRY some code

Basically, I'm looking for a hook that will let me iterate through all my has_one relationships.

The idea of this class is that each PageAttribute should have exactly one XX_page_attribute. There are several possibilities for this, so it's supposed to be encapsulated by the att_value attribute. (and attribute that returns and sets the proper XX_page_attribute) the decision about which XX_page_attribute is based on another column of PageAttribute: class_name.

any ideas? thanks, Jacob

class PageAttribute < ActiveRecord::Base

  belongs_to :page

  has_one :boolean_page_attribute, :class_name => 'BooleanPageAttribute', :dependent => :destroy   has_one :date_page_attribute, :class_name => 'DatePageAttribute', :dependent => :destroy   has_one :string_page_attribute, :class_name => 'StringPageAttribute', :dependent => :destroy   has_one :page_link_page_attribute, :class_name => 'PageLinkPageAttribute', :dependent => :destroy   has_one :uploaded_file_page_attribute, :class_name => 'UploadedFilePageAttribute', :dependent => :destroy

  def att_value     if(self.class_name.to_s == 'BooleanPageAttribute')       return self.boolean_page_attribute     end     if(self.class_name.to_s == 'DatePageAttribute')       return self.date_page_attribute     end     if(self.class_name.to_s == 'StringPageAttribute')       logger.debug "returning string_page_attribute" + string_page_attribute.to_s       return self.string_page_attribute     end     if(self.class_name.to_s == 'PageLinkPageAttribute')       return self.page_link_page_attribute     end     if(self.class_name.to_s == 'UploadedFilePageAttribute')       return self.uploaded_file_page_attribute     end   end

  def att_value=(val)     logger.debug("setting att_value from: " + val.to_s);

    if(self.class_name.to_s == 'BooleanPageAttribute')       if val.is_a? Hash         self.boolean_page_attribute = BooleanPageAttribute.new(val)       else         self.boolean_page_attribute = val       end     end     if(self.class_name.to_s == 'DatePageAttribute')       if val.is_a? Hash         self.date_page_attribute = DatePageAttribute.new(val)       else         self.date_page_attribute = val       end     end     if(self.class_name.to_s == 'StringPageAttribute')       if val.is_a? Hash         self.string_page_attribute = StringPageAttribute.new(val)       else         self.string_page_attribute = val       end     end     if(self.class_name.to_s == 'PageLinkPageAttribute')       if val.is_a? Hash         self.page_link_page_attribute = PageLinkPageAttribute.new(val)       else         self.page_link_page_attribute = val       end     end     if(self.class_name.to_s == 'UploadedFilePageAttribute')       if val.is_a? Hash         self.uploaded_file_page_attribute = UploadedFilePageAttribute.new(val)       else         self.uploaded_file_page_attribute = val       end     end   end

Basically, I'm looking for a hook that will let me iterate through all my has_one relationships.

http://rdoc.caboo.se/doc/classes/ActiveRecord/Reflection/ClassMethods.html

In particular, you probably want to look at reflect_on_all_associations(:has_one)

The idea of this class is that each PageAttribute should have exactly one XX_page_attribute. There are several possibilities for this, so it's supposed to be encapsulated by the att_value attribute. (and attribute that returns and sets the proper XX_page_attribute) the decision about which XX_page_attribute is based on another column of PageAttribute: class_name.

any ideas? thanks, Jacob

Hope that helps.

-Rob

Rob Biedenharn http://agileconsultingllc.com Rob@AgileConsultingLLC.com

This sounds like a classic use case for STI - have you considered using that?

Essentially, all the various models (BooleanPageAttribute, etc.) would look like this:

class BooleanPageAttribute < PageAttribute

any extra stuff

end

And PageAttribute would be:

class PageAttribute < ActiveRecord::Base

belongs_to :page inheritance_column :class_name end

(If you name your type indicator “type”, then you don’t need the inheritance_column statement)

The schema for the page_attributes table would contain all of the data from the various types.

The att_value methods above would be replaced with the normal page_attribute (from belong_to) methods on Page. And you can use the standard create()/new() syntax to initialize PageAttributes; just call them on the desired type. Example:

p = Page.new() p.page_attribute = BooleanPageAttribute.new(options)

etc.

Alternately, you could always use a serialized column to store a typed object opaquely (see the discussion in AWDWR, and/or the AR docs). This loses a lot of searchability, however.

And if you’re stuck with this as a legacy schema, well, we’ll pray for you… :slight_smile:

Hope this helps,