Search code examples
ruby-on-railsrails-activerecordmodel-associationsactive-relation

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


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


Solution

  • 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