A Fresh Cup is Mike Gunderloy's software development weblog, covering Ruby on Rails and whatever else I find interesting in the universe of software. I'm a full-time software developer: most of my time in recent years has been spent writing Rails, though I've dabbled in many other things and like most people who have been writing code for decades I can learn new stuff as needed.

As of July 2016, I'm looking for my next job. I'm not able to relocate, so unless you're in the Evansville area, I'd need a completely remote gig. I have lots of experience working remote. Prefer full-time but I wouldn't be averse to an interesting contact gig. Drop me a comment if you've got something or email MikeG1 [at] larkfarm.com.

Navigation
« Rails 2.1.2 and 2.2RC1: Update Your RubyGems | Main | Double Shot #319 »
Friday
Oct242008

Rails 2.2 Change: Private Methods on Association Proxies are Private

There's a small change in Active Record behavior that's going to bite some existing applications under Rails 2.2: private methods on an association proxy are actually private. To illustrate, this code would work in Rails 2.1:

user.rb:

[sourcecode language='ruby']
class User < ActiveRecord::Base
has_one :account
end
[/sourcecode]

account.rb:

[sourcecode language='ruby']
class Account < ActiveRecord::Base
belongs_to :user
private
def secret_code
"ABCDE"
end
end
[/sourcecode]

Controller code:

[sourcecode language='ruby']
@u = User.first
@code = u.account.secret_code
[/sourcecode]

With Rails 2.1, you'll actually get the secret code in @code, even though it comes from a private method of the account object. Rails 2.2 is stricter about this: that same code will fail with a NoMethodError. If you want to access a private method across an association proxy now, you'll need to use @code = u.account.send("secret_code").

Directly accessing private methods on an Active Record instance itself was already blocked in Rails 2.1, but Rails 2.2 updates that failure to give back a NoMethodError as well.

Reader Comments (2)

I'm glad this functionality is getting some attention, since I think it significantly improves the correctness of method calling via associations. However, I'm not sure I agree with your final paragraph.

Calling private methods defined on classes derived from ActiveRecord fail (I believe) with a NoMethodError in every version of Rails that I have ever worked with; this is standard Ruby functionality. However, if you try to restrict access to a method added to an ActiveRecord by Rails from a database column, you will be disappointed. Rails 2.1, and earlier, dispatches to those methods via method missing without checking for privacy. Rails 2.2 corrects this error.

For instance, if your users table has an email_address column, this code will succeed in 2.1, but fail with a NoMethodError in 2.2:

class User < ActiveRecord::Base
private
def email_address
read_attribute(:email_address)
end
end

...

puts User.new.email_address

October 28, 2008 | Unregistered CommenterAdam Milligan

Is this changable... [sourcecode language='ruby']
@u = User.first
@code = u.account.secret_code
[/sourcecode]

then, how it possible..

Email Database

April 10, 2010 | Unregistered CommenterRK

PostPost a New Comment

Enter your information below to add a new comment.
Author Email (optional):
Author URL (optional):
Post:
 
Some HTML allowed: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <code> <em> <i> <strike> <strong>