I find that I'm frequently writing code that could be described in English as "If there is an incumbent ActiveRecord that meets some specific criteria, then update one or more of its fields. Otherwise create a new record with the same criteria and new field values."
ActiveRecord's dynamic finder methods (find_or_create_by_xxx) are not usually expressive enough to do this. But I haven't been able to create a general method that smells right. It's been bugging me, so I turn to the mavens of style in this forum for suggestions.
As an example, I just wrote this monstrosity:
def set_xattribute(name, v1, v2) symbol_name = self.class.intern_symbol_name(name) incumbent = SymbolValue. where(:symbol_values => {:symbol_name_id => symbol_name.id}). where(:symbol_values => {:owner_id => self.id}). where(:symbol_values => {:xclass_id => self.class.xclass_id}).first if (incumbent) incumbent.update_attributes(:v1 => v1, :v2 => v2) else SymbolValue.create(:symbol_name_id => symbol_name.id, :owner_id => self.id, :xclass_id => self.class.xclass_id, :v1 => v1, :v2 => v2) end end
Note the code fragments repeated among the "finder" (incumbent = ...), the "updater" (update_attributes(...), and the "creator" (SymbolValue.create(...)). There may be a clever way to use scopes for this, but what do the mavens of style in this forum suggest?
- ff