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 received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 10 Jun 2008, at 04:41, glenviewjeff wrote:> > 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.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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
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 --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
On 14 Jun 2008, at 20:37, glenviewjeff wrote:> > 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> 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 > > >--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---