Default Data Templates

In my database, I have a lot of duplicated data between entries. For
example, I might have a database of foods where Meats is the parent
object and Cheeseburger is one of its children.

o=Food.New
o.name = "Meats"
o.text = "This food is really unhealthy....lots of text"
o.category = "Meats"
o.save

p=Food.New
p.parent = o.id
p.name = "Cheeseburger"
p.save

If unpopulated, I'd like the parent's data to be accessed. I
implemented this inside the model on an attribute-by-attribute basis,
but this seems to stink of bad design, since every time I add a new
field, I have to write duplicate code that checks if the attribute is
empty.

Any ideas would be greatly appreciated.

you could do something like

class << self
   def attr_parent *names
     names.each do |name|
       define_method name do
         self.read_attribute(name) || parent.send(name)
       end
     end
   end
end

then you can stick
attr_parent :name, :text, ... in your model (try and pick a better name than me) and it will call the parent object if the attribute is nil (if you also want this to happen on a empty string just change the conditions. You could also stick this in a module and extend ActiveRecord::Base with it, and then all ActiveRecord subclasses will be able to use it

Fred

Thank you very much Fred. It took me some time to learn Ruby's OO
implementation well enough to understand your post, but I was
successful.

For anyone with similar problems, I've pasted my code below.
Incidentally, my code smells bad again, in that I am explicitly
testing for specific classes (i.e., string or not,) and I would think
this would be better handled by extending the class for each data type
(string, etc.) Any thoughts?

Thanks,
Jeff

class FoodItem < ActiveRecord::Base
  class << self
    def attr_parent *names
      names.each do |name|
        define_method name do
          self.read_attribute( name )
          if self.read_attribute( name ).is_a? String
            if self.read_attribute( name ).empty? && !
self.DuplicateOf.nil?
              FoodItem.find(self.DuplicateOf).send(name)
            else
              self.read_attribute( name )
            end
          else
            self.read_attribute(name) ||
FoodItem.find(self.DuplicateOf).send(name)
          end
        end
      end
    end
  end

    attr_parent :FoodType, :FoodPrice
end

Thank you very much Fred. It took me some time to learn Ruby's OO
implementation well enough to understand your post, but I was
successful.

For anyone with similar problems, I've pasted my code below.
Incidentally, my code smells bad again, in that I am explicitly
testing for specific classes (i.e., string or not,) and I would think
this would be better handled by extending the class for each data type
(string, etc.) Any thoughts?

I'm not entirely sure what you're doing there, but it sounds like you
could simplify it to

if self.read_attribute( name ).blank?
   FoodItem.find(self.DuplicateOf).send(name)
else
   self.read_attribute( name )
end
(blank? returns true for nil, an empty string, an empty array etc...

You might also want to use an association (so that the find is cached
rather than hitting the database each time. It's also ruby convention
that method names be underscored, not camelcased (which is used for
constants, eg class names), as it is it makes your code look very odd.

Fred