Hi I was recently taught about the useful ActiveRecord::Base#serialize. It''s very useful for persisting arbitrary objects through the regular database. For example, say you want to store a Set of all the years a Convention took place. You do: class Convention < ActiveRecord::Base serialize :years, Set end This effectively creates a Convention#years attribute, which is a set: you can add items (years) to it, check if a certain year is contained (included?) within, etc. Generally wonderful. But there''s a deficiency: when you instantiate con = Convention.new con.years would be nil. Trying to rely in any way on con.years'' Set properties would fail, since until you explicitly do con.years = Set.new the Set is simply not there. This could lead to many bugs if you forget to assign a set to con.years. Common calls like "con.years << 2001" and "con.years.include? 2002" would raise exceptions. So generally, I think everyone using "serialize :foo, Set" would want to have also: class Convention < ActiveRecord::Base ... def after_initialize self.years = Set.new end end Maybe there should be some automagic way to do this? Seeing that the the after_initialize flows from the serialize call, that even looks like a DRY violation. Also, it''s somewhat obscure: the self.yearssyntax isn''t newbie-obvious, and after_initialize doesn''t appear in the Rails method glossary [1]. To sum up, I think there should be a feature request. -Alder [1] http://api.rubyonrails.com/fr_method_index.html
On May 9, 2006, at 11:21 PM, Alder Green wrote:> I was recently taught about the useful ActiveRecord::Base#serialize. > It''s very useful for persisting arbitrary objects through the regular > database. For example, say you want to store a Set of all the years a > Convention took place. You do: > > class Convention < ActiveRecord::Base > serialize :years, Set > end > > This effectively creates a Convention#years attribute, which is a set: > you can add items (years) to it, check if a certain year is contained > (included?) within, etc.Yup: the second arg is an optional type restriction, not a default value.> Generally wonderful. But there''s a deficiency: when you instantiate > > con = Convention.new > > con.years would be nil. Trying to rely in any way on con.years'' Set > properties would fail, since until you explicitly do > > con.years = Set.new > > the Set is simply not there. This could lead to many bugs if you > forget to assign a set to con.years. Common calls like "con.years << > 2001" and "con.years.include? 2002" would raise exceptions.This is a poor situation. Also consider A = Struct.new(:a, :b, :c) class Foo < AR::Base serialize :bar, A end Automatically setting bar = A.new would fail since it needs params. We need a default value in addition to the type condition. class Foo < AR::Base serialize(:bar) { |foo| foo.bar = A.new(1,2,3) } end> To sum up, I think there should be a feature request.Would you file one? http://dev.rubyonrails.org/newticket Best, jeremy
On 5/10/06, Jeremy Kemper <jeremy@bitsweat.net> wrote:> On May 9, 2006, at 11:21 PM, Alder Green wrote: > > I was recently taught about the useful ActiveRecord::Base#serialize. > > It''s very useful for persisting arbitrary objects through the regular > > database. For example, say you want to store a Set of all the years a > > Convention took place. You do: > > > > class Convention < ActiveRecord::Base > > serialize :years, Set > > end > > > > This effectively creates a Convention#years attribute, which is a set: > > you can add items (years) to it, check if a certain year is contained > > (included?) within, etc. > > Yup: the second arg is an optional type restriction, not a default > value. > > > > Generally wonderful. But there''s a deficiency: when you instantiate > > > > con = Convention.new > > > > con.years would be nil. Trying to rely in any way on con.years'' Set > > properties would fail, since until you explicitly do > > > > con.years = Set.new > > > > the Set is simply not there. This could lead to many bugs if you > > forget to assign a set to con.years. Common calls like "con.years << > > 2001" and "con.years.include? 2002" would raise exceptions. > > This is a poor situation. Also consider > > A = Struct.new(:a, :b, :c) > class Foo < AR::Base > serialize :bar, A > end > > Automatically setting bar = A.new would fail since it needs params. > We need a default value in addition to the type condition. > > class Foo < AR::Base > serialize(:bar) { |foo| foo.bar = A.new(1,2,3) } > end > > > To sum up, I think there should be a feature request. > > Would you file one? http://dev.rubyonrails.org/newticketSubmitted! http://dev.rubyonrails.org/ticket/5049> Best, > jeremy > _______________________________________________ > Rails mailing list > Rails@lists.rubyonrails.org > http://lists.rubyonrails.org/mailman/listinfo/rails >Thanks for your comments and the efforts you and the other Rails-core members make to ensure Rails is such a wonderful framework to use. -Alder