rails: undefined method insert_record for Array

I have a Model A which has many objects of Model B using a :has_many association. When I create a new object of model A, set its attributes, build associated objects and inspect the non-persisted objects, it works fine. However, as soon as I try to persist the objects using save or save!, I am getting the following back-trace.

NoMethodError: undefined method insert_record’ for #Array:0x000000052541f8 from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:154:in send' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:306:in block in save_collection_association’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/associations/association_collection.rb:431:in block in method_missing' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in block in method_missing’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in each' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/associations/association_proxy.rb:216:in method_missing’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/associations/association_collection.rb:431:in method_missing' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:297:in save_collection_association’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/autosave_association.rb:163:in block in add_autosave_association_callbacks' from /usr/lib/ruby/gems/2.0.0/gems/activesupport-3.0.5/lib/active_support/callbacks.rb:415:in _run_create_callbacks’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:281:in create' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/persistence.rb:246:in create_or_update’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:277:in block in create_or_update' from /usr/lib/ruby/gems/2.0.0/gems/activesupport-3.0.5/lib/active_support/callbacks.rb:418:in _run_save_callbacks’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/callbacks.rb:277:in create_or_update' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/persistence.rb:39:in save’ … 2 levels… from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:240:in block (2 levels) in save' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:292:in block in with_transaction_returning_status’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/connection_adapters/abstract/database_statements.rb:139:in transaction' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:207:in transaction’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:290:in with_transaction_returning_status' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:240:in block in save’ from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:251:in rollback_active_record_state!' from /usr/lib/ruby/gems/2.0.0/gems/activerecord-3.0.5/lib/active_record/transactions.rb:239:in save’ from (irb):104 from /usr/lib/ruby/gems/2.0.0/gems/railties-3.0.5/lib/rails/commands/console.rb:44:in start' from /usr/lib/ruby/gems/2.0.0/gems/railties-3.0.5/lib/rails/commands/console.rb:8:in start’ from /usr/lib/ruby/gems/2.0.0/gems/railties-3.0.5/lib/rails/commands.rb:23:in <top (required)>' from /home/amitav/WMS/trunk/script/rails:6:in require’ from /home/amitav/WMS/trunk/script/rails:6:in <top (required)>' from -e:1:in load’ from -e:1:in <main>'

I am using ruby 2.0.0p195 with rails 3.0.5.

About this issue

  • Original URL
  • State: closed
  • Created 11 years ago
  • Comments: 19 (6 by maintainers)

Commits related to this issue

Most upvoted comments

Ruby 2.0 is no longer returns true from respond_to? for protected methods. That’s why it’s failing in for rails 3.0 on ruby 2.0. AssociationProxy redefines send method.

def send(method, *args)
  if proxy_respond_to?(method)
    super
  else
    load_target
    @target.send(method, *args)
   end
end

insert_record is a protected method, so in ruby 2.0 this method will go to @target which is an array.

Here’s small monkey patch that one can use to fix this issue. It’s been tested only for rails 3.0.x, but i guess that it should work for earlier versions as well.

if Rails::VERSION::MAJOR == 3 && Rails::VERSION::MINOR == 0 && RUBY_VERSION >= "2.0.0"
  module ActiveRecord
    module Associations
      class AssociationProxy
        def send(method, *args)
          if proxy_respond_to?(method, true)
            super
          else
            load_target
            @target.send(method, *args)
          end
        end
      end
    end
  end
end

/cc @tisba, @saneshark

I also had to add:

def respond_to?(symbol, include_private=false)
  super(symbol, true)
end

Because autosave_association.rb:334 was not triggered:

association.send(:construct_sql) if association.respond_to?(:construct_sql)

We are using a different implementation of respond_to? since we were having issues with some associations:

    def respond_to?(*args)                                                   
      args << true unless args.size > 1                                      
      proxy_respond_to?(*args) || (load_target && @target.respond_to?(*args))
    end