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,