Big hole in my understanding of RoR

Hi,

After skim reading your post, is your question "How do I set default values for ActiveRecord?". Which I find a bit more concise.

If so, a quick Google search indicates that you have merely used the wrong way to access the attributes, you should use their accessor as I don't believe they are stored in "@" variables.

See here:

Ignore me if I've missed the point of your post.

Regards, Andrew

  def initialize (params = nil)     super     self.text="default text from init" unless self.text     self.color="#999999" unless self.color   end

and the "new" form now provides a default for color, but not for text. This just makes me more confused...! And, I still haven't got this working with the Uri relationship!

I'm not sure if this has any bearing on your particular problem, but "text" may no be a very "safe" column name to use. I have had issues in the past with MySQL when using keywords as column names. It's best to use column names that are not database specific keywords.

I've put some thought into this and have done some experimenting and thought I would bring up a few points of discussion:

It seems to me there are multiple definitions of a "default value."

1. Database/Model level defaults: In relation to a model object it would be values that would define the "natural state" of an attribute. Take for example an attribute access_level on a User object. A natural default state may be a value representing a "regular" user (say 1 = "Regular user").

This type of default value can be provided right in your database migration like:

class CreateUsers < ActiveRecord::Migration   def self.up     create_table :users do |t|       t.column :created_at, :datetime #<< Notice that Rails will automatically take care of the default value       t.column :first_name, :string       t.column :last_name, :string       t.column :access_level, :integer, :default => 1 #<< 1 = Regular user     end   end

  def self.down     drop_table :users   end end

It is also possible (although it seems unnecessary given the above) to set these types of defaults in the model class like:

class User < ActiveRecord::Base   def initialize(params = nil)     super     self.access_level ||= 1   end end

In other cases the "default value" may actually be related more to a particular view.

I recently ran into an example like this: I had a event scheduler that I wanted a default value for the current time to be set on the datatime selection control. In my opinion this is not a model level default value. To create an event, expecting people to subscribe to the event later, it is not the "natural state" of the Event object to have a start_time = Time.now. However, it is convenient to initialize the form's control to default to the current date and time to make the user's selection process easier.

It just happens that the built-in time widgets do this (I think so anyway). But in any case the initial state of the model object's start_time attribute to be nil and not Time.now.

So assuming that this behavior is not built into the form's control object Rails provides a convenient way to construct a new object with some attributes initialized that can be set from with the controller like:

  # GET /people/new   def new     @person = User.new(access_level => 1)   end

Maybe some purist MVC guys would say that is breaking the MVC design pattern, and maybe it is, but sometimes the convenience is so great that it's worth bending the rules a bit. However, this is similar to many "factory constructor" design patterns that I often see in use.

It would be more "pure" if the form's control were extended to provide a default option.

Something like:   <p>     <b>Access Level</b><br />     <%= f.text_field :access_level, :options => {:default => 1 }%> # DON'T do this it's just made up to illustrate a point   </p>

I recently ran across the problem of needing to initialize a model's
relation on creation and used the 'faux accessor' solution because
you really shouldn't be overriding an AR initialize method.

Josh outlines the technique here:

http://blog.hasmanythrough.com/2007/1/22/using-faux-accessors-to- initialize-values

-Michael http://javathehutt.blogspot.com

  def text     self[:text] or "default text"   end don't appear to be called by the form builders? If @text isn't used by ActiveRecord, I'd have thought the first one would at least return the default text, and if ActiveRecord does use a hash, then I'd have thought the second one does work...

I think the form builders use the "attribute_before_type_cast" accessor methods. Actually I tried submitting a patch for it: http:// dev.rubyonrails.org/ticket/5427

    self.text="default text from init" unless self.text     self.color="#999999" unless self.color   end

Just a guess, maybe self.text.empty?

Best regards, Andrew