Ruby on Rails error in active relation, NoMethodError: undefined method 'methodname' for #<ActiveRecord::Relation:0x00000002ab5908>

user2603796 picture user2603796 · Oct 23, 2013 · Viewed 7.3k times · Source

Here is code of two models which have 1 to 1 association

class User < ActiveRecord::Base
  has_one :e_user
  validates_presence_of :first_name
  validates_presence_of :last_name
  validates :password, presence: true, :length => { :minimum => 6}
  validates_uniqueness_of :email, :message => ": This email is already registered!"
  validates_presence_of :email  
end

Below is second model:

class EUser < ActiveRecord::Base
  belongs_to : user
end

When i go to rails console and get a User from db, by doing

a = User.where(:id => 1)

I get a user in a. Now I want to get the e_user associated with a(if any it should return it or return null), but i get error message when i type a.EUser in console, error is

NoMethodError: undefined method `EUser' for  #<ActiveRecord::Relation:0x00000002ab5908>from /home/faraz/.rvm/gems/ruby-1.9.3-p448/gems/activerecord-3.1.1/lib/active_record/relation.rb:459:in `method_missing'
from (irb):3
from /home/faraz/.rvm/gems/ruby-1.9.3-p448/gems/railties-3.1.1/lib/rails/commands/console.rb:45:in `start'
from /home/faraz/.rvm/gems/ruby-1.9.3-p448/gems/railties-3.1.1/lib/rails/commands/console.rb:8:in `start'
from /home/faraz/.rvm/gems/ruby-1.9.3-p448/gems/railties-3.1.1/lib/rails/commands.rb:40:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'

Regards

Answer

zeantsoi picture zeantsoi · Oct 23, 2013

First, you have declared that User has_one :e_user. Thus, the correct relationship lookup is:

first_user = User.first
first_user.e_user

Second, the where ActiveRecord method returns an ActiveRecord::Relation object type. What you need is User object itself. Instead, use find:

a = User.find(1)
a.e_user

An explanation: the where method returns an ActiveRecord::Relation object which contains all class objects which meet the conditions in an array-like structure. However, even if where returns just a single record, that record will still be contained within that array-like structure; any instance methods on the retrieved class won't be accessible until you access the object within the ActiveRecord::Relation.

find, on the other hand, returns the first object itself that meets the specified condition (by default, ActiveRecord matches against the object id). Thus, any object returned by the find method has full utility and use over the instance methods and attributes defined for those class objects:

find_user = User.find(1)
where_user = User.where(:id => 1)

find_user.class
#=> User
where_user.class
#=> ActiveRecord::Relation

find_user == where_user
#=> false

find_user == where_user.first
#=> true