Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Ruby on Rails ActiveRecord model Accessors

My Model, "DataFile", has a bunch of fields which I'd like to set from outside the Model, e.g.

file = DataFile.new
file.owner = 123

Now, as far as I know, I'd have to place an "attr_accessor :field" in my model, for every field that I'd like to modify from outside. However, the above code runs fine without having any attr_accessors defined, setting the owner field to 123. Why is that?

I'd expected to get a "method not defined" error or something like that.

like image 475
fresskoma Avatar asked Sep 10 '26 10:09

fresskoma


2 Answers

Because Rails' ORM uses the ActiveRecord pattern, two methods are created automatically for each column in the database associated with that table: columnname, and columnname=. This happens "automatically" as a result of your model inheriting from ActiveRecord::Base. These methods are defined using ruby's metaprogramming facilities and are created dynamically at the time of class creation.

For more info as to exactly what's going on, I would take a look at the Rails source. However, the above is probably enough to give you a working understanding of what is happening.

like image 124
Drew Olson Avatar answered Sep 12 '26 23:09

Drew Olson


Drew and Zepplock got it right, but I'll just add one more thing. The accessors that Rails (actually, ActiveRecord) creates for database fields are NOT Ruby accessors, and if you use script/console you'll see that owner isn't an instance variable of the object file.

It's likely you'd never notice this until you venture away from the standard accessors and try to manipulate @owner inside a method on file. If you're learning Ruby at the same time you're learning Rails (which is what I did), it's likely you'll bump into this at some point. This is the reason that you need to write:

class MyClass < ActiveRecord::Base
  def invalidate_owner
    self.owner = owner << " no longer owns this"
    save
  end
end

instead of

class MyClass < ActiveRecord::Base
  def invalidate_owner
    self.owner << " no longer owns this"
    save
  end
end
like image 39
Mark Westling Avatar answered Sep 12 '26 23:09

Mark Westling



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!