Re: a generic solution to defaults in AR model initialization

Jonathan Viney
2008-09-08T12:48:31Z

Does the plugin I wrote a while back do what''s needed?

http://svn.viney.net.nz/things/rails/plugins/active_record_defaults/

Cheers,
-Jonathan.

On Mon, Sep 8, 2008 at 10:07 PM, tron <viktor.tron@gmail.com> wrote:

>
> This afterthought to this ancient but still relevant post
>
>
http://groups.google.com/group/rubyonrails-core/browse_thread/thread/b509a2fe2b62ac5
>
> After realizing that after_initialize callback is a serious misnomer,
> I had to figure out a way
> to implement a generic solution for defaults.
>
> Below is what I came up with.
> You can simply give a defaults class method in your models. Features:
>
> * It is also able to assign to associations
> * warns against undefined assigners (typos)
> * defaults can be overriden in the hash passed to the
''new''
> constructor
> * block given to new are correctly executed
>
> Comments welcome
>
> V
>
> E.g.
> class Person < ActiveRecord::Base
>  has_one :profile
>  def self.defaults
>   { :profile => Profile.new, :name => ''tron''  }
>  end
> end
>
> config/initializers/active_record_defaults.rb
>
> class ActiveRecord::Base
>  # this does not work with associations...
>
>  def initialize_with_defaults(attributes=nil,&block)
>    defaults = self.class.respond_to?(:defaults) ?
> self.class.defaults : false
>
>    initialize_without_defaults(attributes) do
>
>      if defaults then
>        defaults.each_pair do |a,v|
>          assigner_f = "#{a}="
>          # we force check of default attributes even if
>          # they are assigned already but do not override
>          if respond_to?(assigner_f) then
>            # assign value if it does not already have one
>            # nil is important cause value can be false!!
>            send(assigner_f,v) if send(a).nil?
>          else
>            raise(ArgumentError.new("unable to assign to
''%s''" % a))
>          end
>        end
>      end
>      yield self if block_given?
>    end
>  end
>  alias_method_chain :initialize, :defaults
> end
>
> >