On Mar 13, 1:23 pm, "Robert Klemme" <shortcut... / googlemail.com> wrote: > 2008/3/13, Trans <transf... / gmail.com>: > > > > > > > On Mar 13, 4:42 am, "Robert Klemme" <shortcut... / googlemail.com> > > wrote: > > > 2008/3/13, Trans <transf... / gmail.com>: > > > > > Which approach is better: parametric module or an injecting class > > > > method. > > > > Are you writing a book on best practices? There seem to be quite a > > > few of these questions recently. :-)) > > > Ha... I probably should be! But right now I'm just working through > > some old "TODO" questions in Facets. > > LOL > > > > > > > # Generates identity/key methods based on specified attributes. > > > > # > > > > # equate_on :a, :b > > > > # > > > > # _is equivalent to_ > > > > # > > > > # def ==(o) > > > > # self.a == o.a && self.b == o.b > > > > # end > > > > # > > > > # def eql?(o) > > > > # self.a.eql?(o.a) && self.b.eql?(o.b) > > > > # end > > > > # > > > > # def hash() > > > > # self.a.hash ^ self.b.hash > > > > # end > > > > > def equate_on(*fields) > > > > code = "" > > > > code << "def ==(o) " << fields.map {|f| "self.#{f} == > > > > o.#{f}" }.join(" && ") << " end\n" > > > > code << "def eql?(o) " << fields.map {|f| "self.#{f}.eql? > > > > (o.#{f})" }.join(" && ") << " end\n" > > > > code << "def hash() " << fields.map {|f| > > > > "self.#{f}.hash" }.join(" ^ ") << " end\n" > > > > class_eval( code ) > > > > fields > > > > end > > > > I opt for the second solution because the anonymous module does not > > > have any reuse effects - unless you cache it based on field names. :-) > > > :) And if we do cache based on field names? > > Aw, com' on. Interesting additional question: should order matter? > I'd say probably yes, but that will reduce reuse of cached entries. I explored the cache idea a bit more, and it made me see why a Module approach appealed to me over the injection method, but generating parametric modules, even if cached seemed somehow wrong too. I derived this instead: module EquateOn def ==(o) equate_fields.all?{ |f| send(f) == o.send(f) } end def eql?(o) equate_fields.all?{ |f| send(f).eql?(o.send(f)) } end def hash equate_fields.inject(0){ |memo, f| memo ^ send(f).hash } end end def EquateOn(*fields) define_method(:equate_fields){ fields } return EquateOn end Much better, but I still wonder if it is enough to be preferable over the a helper method. T.