Rails association not working. "Undefined method" error in trying to access child object from parent object

For some reason (most likely in my view due to naming conventions) rails association is not working. Trying to access child object from parent object gives undefined method.

Routes.rb:

Sns::Application.routes.draw do

root :to => "questions#index"

resources :questions do

resources :question_responses

end

**question.rb:**

class Question < ActiveRecord::Base

validates :title, :presence => true

validates :description, :presence => true

has_many :question_responses, :dependent => :destroy, :class_name => “QuestionResponse”

accepts_nested_attributes_for :question_responses, :allow_destroy => true

end

question_response.rb:

class QuestionResponse < ActiveRecord::Base

validates :body, :presence => true

belongs_to :question, :foreign_key => "question_id"

end

**questions_controller.rb:**

class QuestionsController < ApplicationController

before_filter :find_question

before_filter :find_question_response, :only => [:show, :edit, :update, :destroy]

def index

@question = Question.new

@questions = Question.all

end

def new

@question = Question.new

@question_response = @question.question_responses.build

end

def create

@question = Question.new(params[:question])

if @question.save

flash[:notice] = “Question has been created.”

redirect_to @question

else

flash[:alert] = “Question has not been created.”

render :action => ‘new’

end

@question_response = @question.question_responses.build(params[:question_response])

if @question_response.save

flash[:notice] = “Reply has been created.”

redirect_to [@question, @question_response]

else

flash[:alert] = “Reply has not been created.”

render “question_responses/new”

end

end

def show

@question = Question.find(params[:id])

end

def edit

@question = Question.find(params[:id])

end

def update

@question = Question.find(params[:id])

if @question.update_attributes(params[:question])

flash[:notice] = “Question has been updated.”

redirect_to @question

else

flash[:alert] = “Question has not been updated.”

render :action => ‘edit’

end

end

def destroy

@question = Question.find(params[:id])

@question.destroy

flash[:notice] = “Question has been deleted.”

redirect_to questions_path

end

def find_question_response

@question_response = @question.question_responses.find(params[:id])

end

private

def find_question

if (params[:question_response] && params[:question_response][:question_id])

@question = Question.find(params[:question_response][:question_id])

elsif params[:question_id]

@question = Question.find(params[:question_id])

end

end

end

Error with trace:

undefined method `question_responses' for nil:NilClass

app/controllers/questions_controller.rb:55:in `find_question_response'

activesupport (3.2.1) lib/active_support/callbacks.rb:429:in `_run__35842215__process_action__9839693__callbacks'

activesupport (3.2.1) lib/active_support/callbacks.rb:405:in `__run_callback'

activesupport (3.2.1) lib/active_support/callbacks.rb:385:in `_run_process_action_callbacks'

activesupport (3.2.1) lib/active_support/callbacks.rb:81:in `run_callbacks'

actionpack (3.2.1) lib/abstract_controller/callbacks.rb:17:in `process_action'

actionpack (3.2.1) lib/action_controller/metal/rescue.rb:29:in `process_action'

actionpack (3.2.1) lib/action_controller/metal/instrumentation.rb:30:in `block in process_action'

activesupport (3.2.1) lib/active_support/notifications.rb:123:in `block in instrument'

activesupport (3.2.1) lib/active_support/notifications/instrumenter.rb:20:in `instrument'

activesupport (3.2.1) lib/active_support/notifications.rb:123:in `instrument'

actionpack (3.2.1) lib/action_controller/metal/instrumentation.rb:29:in `process_action'

actionpack (3.2.1) lib/action_controller/metal/params_wrapper.rb:205:in `process_action'

activerecord (3.2.1) lib/active_record/railties/controller_runtime.rb:18:in `process_action'

actionpack (3.2.1) lib/abstract_controller/base.rb:121:in `process'

actionpack (3.2.1) lib/abstract_controller/rendering.rb:45:in `process'

actionpack (3.2.1) lib/action_controller/metal.rb:203:in `dispatch'

actionpack (3.2.1) lib/action_controller/metal/rack_delegation.rb:14:in `dispatch'

actionpack (3.2.1) lib/action_controller/metal.rb:246:in `block in action'

actionpack (3.2.1) lib/action_dispatch/routing/route_set.rb:66:in `call'

actionpack (3.2.1) lib/action_dispatch/routing/route_set.rb:66:in `dispatch'

actionpack (3.2.1) lib/action_dispatch/routing/route_set.rb:30:in `call'

journey (1.0.3) lib/journey/router.rb:68:in `block in call'

journey (1.0.3) lib/journey/router.rb:56:in `each'

journey (1.0.3) lib/journey/router.rb:56:in `call'

actionpack (3.2.1) lib/action_dispatch/routing/route_set.rb:589:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/best_standards_support.rb:17:in `call'

rack (1.4.1) lib/rack/etag.rb:23:in `call'

rack (1.4.1) lib/rack/conditionalget.rb:25:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/head.rb:14:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/params_parser.rb:21:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/flash.rb:242:in `call'

rack (1.4.1) lib/rack/session/abstract/id.rb:205:in `context'

rack (1.4.1) lib/rack/session/abstract/id.rb:200:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/cookies.rb:338:in `call'

activerecord (3.2.1) lib/active_record/query_cache.rb:64:in `call'

activerecord (3.2.1) lib/active_record/connection_adapters/abstract/connection_pool.rb:443:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/callbacks.rb:28:in `block in call'

activesupport (3.2.1) lib/active_support/callbacks.rb:405:in `_run__609157476__call__595802435__callbacks'

activesupport (3.2.1) lib/active_support/callbacks.rb:405:in `__run_callback'

activesupport (3.2.1) lib/active_support/callbacks.rb:385:in `_run_call_callbacks'

activesupport (3.2.1) lib/active_support/callbacks.rb:81:in `run_callbacks'

actionpack (3.2.1) lib/action_dispatch/middleware/callbacks.rb:27:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/reloader.rb:65:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/remote_ip.rb:31:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/debug_exceptions.rb:16:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/show_exceptions.rb:56:in `call'

railties (3.2.1) lib/rails/rack/logger.rb:26:in `call_app'

railties (3.2.1) lib/rails/rack/logger.rb:16:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/request_id.rb:22:in `call'

rack (1.4.1) lib/rack/methodoverride.rb:21:in `call'

rack (1.4.1) lib/rack/runtime.rb:17:in `call'

activesupport (3.2.1) lib/active_support/cache/strategy/local_cache.rb:72:in `call'

rack (1.4.1) lib/rack/lock.rb:15:in `call'

actionpack (3.2.1) lib/action_dispatch/middleware/static.rb:53:in `call'

railties (3.2.1) lib/rails/engine.rb:479:in `call'

railties (3.2.1) lib/rails/application.rb:220:in `call'

rack (1.4.1) lib/rack/content_length.rb:14:in `call'

railties (3.2.1) lib/rails/rack/log_tailer.rb:14:in `call'

rack (1.4.1) lib/rack/handler/webrick.rb:59:in `service'

/home/administrator/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/webrick/httpserver.rb:138:in `service'

/home/administrator/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/webrick/httpserver.rb:94:in `run'

/home/administrator/.rvm/rubies/ruby-1.9.3-p125/lib/ruby/1.9.1/webrick/server.rb:191:in `block in start_thread'

Read the error carefully, it says that nil has not got a method question_responses, so the object you are trying to call the method on is nil. So apparently @question is nil, assuming that line 55 is     @question_response = @question.question_responses.find(params[:id])

The reason is that this is being called in a before_filter and you have not got any code there to setup @question.

Colin

Hi Colin,

The error here is not the issue, I have rectified it. My point is having declared the associations properly with belongs_to, has_many...when in the console I don't get any association methods. I should be able to access child object from parent object based on these declarations, but continues to show 'undefined method'.

Thanks!

You have not quoted the previous message so I have not idea what this message is about. Remember this is a mailing list not a forum. Please post the exact error you are seeing (copy/paste it here from the console if you are seeing it in the console) and post the relevant sections of code also (the association definitions if it seems to be a problem with them).

Colin

Hi,

Try to get the Question object first. from that move to Question Response.

Colin Law wrote in post #1055588:

Hi Colin,

The error here is not the issue, I have rectified it. My point is having declared the associations properly with belongs_to, has_many...when in the console I don't get any association methods. I should be able to access child object from parent object based on these declarations, but continues to show 'undefined method'.

You have not quoted the previous message so I have not idea what this message is about. Remember this is a mailing list not a forum. Please post the exact error you are seeing (copy/paste it here from the console if you are seeing it in the console) and post the relevant sections of code also (the association definitions if it seems to be a problem with them).

Colin

Hi Colin,

I am sorry for not quoting the previous message. I posted this question on Ruby on Rails Talk Google Group, not sure how it ended up here. Anyhow, my previous message was in response to this post of yours:

For some reason (most likely in my view due to naming conventions) rails association is not working. Trying to access child object from parent object gives undefined method.

...

validates :title, :presence => true class QuestionResponse < ActiveRecord::Base :destroy]

@question = Question.find(params[:id]) def find_question Error with trace:

undefined method `question_responses' for nil:NilClass

app/controllers/questions_controller.rb:55:in `find_question_response'

Read the error carefully, it says that nil has not got a method question_responses, so the object you are trying to call the method on is nil. So apparently @question is nil, assuming that line 55 is    @question_response = @question.question_responses.find(params[:id])

The reason is that this is being called in a before_filter and you have not got any code there to setup @question.

Colin

Now I know from the book "Beginning Rails 3" that having belongs_to and has_many declarations provide the associated association methods. I have these declarations in place as well as the foreign_key in the question_responses table that maps to the primary key of questions table, and yet when I declare a Question object and a QuestionResponse object and try to access the QuestionResponse object from the Question object (which is very well demonstrated in the book), I get this error message:

NoMethodError: undefined method `qr' for #<Question:0xa89bdcc>         from /home/administrator/.rvm/gems/ruby-1.9.3-p125/gems/activemodel-3.2.1/lib/active_model/attribute_methods.rb:407:in `method_missing'         from /home/administrator/.rvm/gems/ruby-1.9.3-p125/gems/activerecord-3.2.1/lib/active_record/attribute_methods.rb:126: in `method_missing'         from (irb):3         from /home/administrator/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.1/lib/rails/commands/console.rb:47:in `start'         from /home/administrator/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in `start'         from /home/administrator/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.1/lib/rails/commands.rb:41:in `<top (required)>'         from script/rails:6:in `require'         from script/rails:6:in `<main>'

I can successfully declare q = Question.first and qr = QuestionResponse.first, but doing q.qr (as demonstrated in the book) gives the error mentioned above.

Thanks!

P.S. This is my original question: http://www.ruby-forum.com/topic/4025611?reply_to=1055588#1055501.

You have wrong entry in database…apply condition if !@question.blank?

then @question.question_responses

end

... Now I know from the book "Beginning Rails 3" that having belongs_to and has_many declarations provide the associated association methods. I have these declarations in place as well as the foreign_key in the question_responses table that maps to the primary key of questions table, and yet when I declare a Question object and a QuestionResponse object and try to access the QuestionResponse object from the Question object (which is very well demonstrated in the book), I get this error message:

NoMethodError: undefined method `qr' for #<Question:0xa89bdcc> from

I did ask you to post the code showing the model relationships and the section of code or console activity that is failing, rather than a textual description of what you have done. What is this 'qr' method that you seem to be trying to use? If you have question has_many question responses and you have a question object (my_question for example) then to get the responses you should use my_question.question_responses Note that it is plural and will be effectively an array of responses

Colin

Colin Law wrote in post #1055607:

NoMethodError: undefined method `qr' for #<Question:0xa89bdcc>    from

I did ask you to post the code showing the model relationships and the section of code or console activity that is failing, rather than a textual description of what you have done. What is this 'qr' method that you seem to be trying to use? If you have question has_many question responses and you have a question object (my_question for example) then to get the responses you should use my_question.question_responses Note that it is plural and will be effectively an array of responses

Colin

/home/administrator/.rvm/gems/ruby-1.9.3-p125/gems/railties-3.2.1/lib/rails/commands/console.rb:8:in

To post to this group, send email to rubyonrails-talk@googlegroups.com. To unsubscribe from this group, send email to

rubyonrails-talk+unsubscribe@googlegroups.com.

For more options, visit this group at

http://groups.google.com/group/rubyonrails-talk?hl=en.

-- gplus.to/clanlaw

Thanks Colin, your suggestion worked. I did mention that qr is QuestionResponse object. According to the book (Beginning Rails 3) that I have, having say q as Question object and qr as QuestionResponse, I should be able to do q.qr as you suggested my_question.question_responses. Not sure why that is not working in my case. However, this tells me that association is working. Many thanks again.

Read the book more carefully and I am sure you will find that it is the name of the association after "q." not the actual object name (they could be the same so this may be the confusion).

Colin

Colin Law wrote in post #1055618:

Murali Tirupati wrote in post #1055602:

Hi,

Try to get the Question object first. from that move to Question Response.

Thanks & Regards, MuraliDharaRao.T +91-9642234646

Thanks, surely that is the idea :slight_smile:

vishal singh wrote in post #1055605:

You have wrong entry in database...apply condition if !@question.blank?     then @question.question_responses end

I tried nil, blank, empty, but to no avail. Now stuck with this error message:

Couldn't find QuestionResponse with id=2 [WHERE "question_responses"."question_id" = 2]

Not sure why would it continues to look for question_responses, even after putting the condition. Works fine, as expected, otherwise.

you have two model question.rb and question_response.rb

in question model write has_many :question_responses and in question_response model write belongs_to :question

in question_responses table add attribute question_id

now for fetch record

@a = Question.find(1) (1 is id )

@a.question_responses (if question_id =1 in question_responses table)

it will work for u.

vishal singh wrote in post #1055650:

you have two model question.rb and question_response.rb

in question model write has_many :question_responses and in question_response model write belongs_to :question

in question_responses table add attribute question_id

now for fetch record

@a = Question.find(1) (1 is id ) @a.question_responses (if question_id =1 in question_responses table)

it will work for u.

Yes, the models are set appropriately for association, as you explained, including foreign key. I have posted the models and other relevant codes in my first post, if you want to take a look: http://www.ruby-forum.com/topic/4025611?reply_to=1055650#1055501

The app works if @question_responses.question_id match @question.id, not otherwise. Hence the need for condition I guess, which did not work.