Exploring ActiveRecord::Base#serialize


#1

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.years=
syntax 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


#2

On May 9, 2006, at 11:21 PM, Alder G. wrote:

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.

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


#3

On 5/10/06, Jeremy K. removed_email_address@domain.invalid wrote:

This effectively creates a Convention#years attribute, which is a set:

end

To sum up, I think there should be a feature request.

Would you file one? http://dev.rubyonrails.org/newticket

Submitted!

http://dev.rubyonrails.org/ticket/5049

Best,
jeremy


Rails mailing list
removed_email_address@domain.invalid
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