Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

Calling #method on new AR objects

#5262

(brought up by PointMan in #rubyonrails)

With Ruby, we can use #method to do something like this:

class Foo
  def hello
    put "hello"
  end
end

foo = Foo.new
foo.method(:hello).call
# => hello

Doing that with an AR object doesn't fire exactly the same way

class User < ActiveRecord::Base
  # has an attr :email from a migration
end

u = User.new
u.method(:email).call

NameError: undefined method `email' for class `User'
    from (irb):2:in `method'
    from (irb):2
    from /Users/franklakatos/.rvm/gems/ruby-1.9.2-head/gems/railties-3.0.0.rc/lib/rails/commands/console.rb:44:in `start'
    from /Users/franklakatos/.rvm/gems/ruby-1.9.2-head/gems/railties-3.0.0.rc/lib/rails/commands/console.rb:8:in `start'
    from /Users/franklakatos/.rvm/gems/ruby-1.9.2-head/gems/railties-3.0.0.rc/lib/rails/commands.rb:23:in `<top (required)>'
    from script/rails:10:in `require'
    from script/rails:10:in `<main>'

This however, will work:

u = User.new
u.email
# => nil
u.method(:email).call
# => nil

I'm doing a little digging now, but I'm assuming Rails doesn't eager load the attributes onto the class until it needs to (because it'd have to hit the DB to set up all the attr values). Not sure if it's a bug, but some may find it breaks a flow of Ruby programming they are used to.

Ruby 1.9.2-head, Rails 3.0.0.rc

Holla atcha boy and let me know

Reported by fakingfantastic · July 31st, 2010 @ 03:22 PM

State: resolved
Milestone: none
Assigned to: nobody
Importance: Low

Activity

  1. fakingfantastic
    fakingfantastic
    • No changes were found…

    July 31st, 2010 @ 03:22 PM

  2. Brian Jensen
    Brian Jensen

    Hi

    The same problem exists in rails 2.3.8. You can even take it a step further and write User.first.method(:email) and it will give you above error.

    Best regards
    Brian Jensen
    @PointMan_

    July 31st, 2010 @ 04:23 PM

  3. Rohit Arondekar
    Rohit Arondekar
    • Importance changed from to Low

    Out of curiosity, why would you want to do

      u = User.new
      u.method(:email).call
    

    instead of

      u = User.new
      u.email
    

    August 1st, 2010 @ 03:41 AM

  4. Rainer Blessing
    Rainer Blessing

    I tried it with 2.3.8 and 2-3-stable and didn't get the error.
    If either u.method(:email).call or u.email is called the execution path runs through method_missing and the correct value is returned.
    I got the error only in Rails 3 with Ruby 1.8.7 and 1.9.2-head where method_missing is not called by u.method(:email).

    Rohit I think u.method can be used if the method is determined at runtime. It's prettier than using eval.

    August 5th, 2010 @ 06:52 PM

  5. fakingfantastic
    fakingfantastic

    "Rohit I think u.method can be used if the method is determined at runtime. It's prettier than using eval."

    Yeah, I'm pretty sure that was the reason it was stumbled upon.

    August 5th, 2010 @ 07:06 PM

  6. Repository
    Repository
    • State changed from new to resolved

    (from [066518295032a8e3f3468737337b8c8299442867]) Preserving :include options for hmt association with an order but without conditions [#5262 Calling #method on new AR objects state:resolved] http://github.com/rails/rails/commit/066518295032a8e3f3468737337b8c...

    September 28th, 2010 @ 06:05 PM