Why am I getting this "undefined method `#<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Survey" error?

16,930

Variable

As a general rule, you'd receive a undefined method error by trying to call a method on an object which either doesn't exist, or is incorrectly defined:

@question.update_attributes(params[:question])

Looks like something to do with this is causing the error


Error

We've had problems like this before, and it's down to this:

ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Survey”

As per the Rails documentation:

Association proxies in Active Record are middlemen between the object that holds the association, known as the @owner, and the actual associated object, known as the @target. The kind of association any proxy is about is available in @reflection. That's an instance of the class ActiveRecord::Reflection::AssociationReflection.

What this means is whatever is happening is calling the proxy object (which basically associates the real objects) in to your methods. Basically you're trying to call methods on an array (collection), rather than the object itself

You'd need to do something like this to fix it:

@question.surveys.first

Fix

I've not used pry before, but I'd try this:

@question.update(question_params)

private

def question_params
    params.require(:question).permit(:description, :element_id, :standard_id, :about, :additive, :iterations, picture_ids: [], footnote_ids: [], :active, :manual)
end
Share:
16,930
steven_noble
Author by

steven_noble

Updated on August 17, 2022

Comments

  • steven_noble
    steven_noble over 1 year

    I have the following associations:

    class Question < ActiveRecord::Base
      has_and_belongs_to_many :footnotes
      has_and_belongs_to_many :pictures
      has_many :fields, :dependent => :destroy
      has_many :surveys, :dependent => :delete_all
      belongs_to :input
      belongs_to :element
      has_many :screenshots
      belongs_to :standard, :touch => true
      belongs_to :product, :touch => true
      belongs_to :condition, :class_name => "Field", :touch => true
    end
    
    class Product < ActiveRecord::Base
      has_many :questions, :dependent => :destroy
      has_many :reviews
      has_and_belongs_to_many :orders
      has_many :competitors
      has_many :elements, :dependent => :destroy
      has_many :fields
    end
    
    class Element < ActiveRecord::Base
      has_many :questions
      has_many :standards
      belongs_to :product, :touch => true
    end
    
    class Standard < ActiveRecord::Base
      has_many :questions
      has_many :standards
      belongs_to :review
    end
    
    class Footnote < ActiveRecord::Base
      belongs_to :reference, :touch => true
      has_and_belongs_to_many :questions
    end
    

    Why, then, do I get the following?

    From: /Users/steven/Dropbox/Testivate/app/controllers/questions_controller.rb @ line 80 QuestionsController#update:
    
        79: def update
     => 80:   binding.pry_remote
        81:   @question = Question.find(params[:id])
        82:   @question.update_attributes(params[:question])
        83:   @question.update_columns :product_id => @question.element.product.id
        84:   flash[:notice] = "Question was successfully updated. (#{undo_link(@question)}.)" if @question.save
        85:   respond_with @question
        86: end
    
    [1] pry(#<QuestionsController>)> @question = Question.find(params[:id])
    +----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | id | sta | des | ele | con | cre | upda | add | ins | act | ite | pro | inp | man | abo | res | lev | com | met |
    +----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    | 1  | 1   | Is  | 1   |     | 201 | 2014 | tru | On  | fal | 1   | 1   |     | fal |     |     | 0   | fal | fal |
    +----+-----+-----+-----+-----+-----+------+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+-----+
    1 row in set
    [2] pry(#<QuestionsController>)> params
    => {"utf8"=>"✓",
     "_method"=>"patch",
     "question"=>
      {"description"=>"Is it readable?",
       "element_id"=>"1",
       "standard_id"=>"1",
       "about"=>"",
       "additive"=>"true",
       "iterations"=>"1",
       "instructions"=>"On the homepage, there is:",
       "picture_ids"=>[""],
       "footnote_ids"=>[""],
       "active"=>"0",
       "manual"=>"0"},
     "commit"=>"Update Question",
     "action"=>"update",
     "controller"=>"questions",
     "id"=>"1"}
    [3] pry(#<QuestionsController>)> @question.save
    => true
    [4] pry(#<QuestionsController>)> @question.update_attributes(params[:question])
    NoMethodError: undefined method `#<ActiveRecord::Associations::CollectionProxy::ActiveRecord_Associations_CollectionProxy_Survey:0x0000010b21ce90>' for #<Question:0x0000010c0dda38>
    from /Users/steven/.rvm/gems/ruby-2.1.0/gems/activemodel-4.0.2/lib/active_model/attribute_methods.rb:439:in `method_missing'
    
  • steven_noble
    steven_noble about 10 years
    Thanks. While I did not end up implementing your solution, that fact that you mentioned @question.surveys.first made me realise that 'Proxy_Survey' was a reference to my 'has_many :surveys` relation. This led me to investigate callbacks on @question that involved that relation. And that's where I found the bug. Thanks.