Search code examples
ruby-on-railsruby-on-rails-4activerecordrails-activerecordreserved-words

Is :apps / 'apps' reserved in Rails v4?


I ran into an odd error trying to do batch updates:

rake db:caching:stats:calculate
rake aborted!
NoMethodError: undefined method `each' for 2548:Fixnum
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/associations/collection_association.rb:365:in `replace'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/associations/collection_association.rb:47:in `writer'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/associations/builder/association.rb:123:in `apps='
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:54:in `public_send'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:54:in `_assign_attribute'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:41:in `block in assign_attributes'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:35:in `each'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/attribute_assignment.rb:35:in `assign_attributes'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/persistence.rb:251:in `block in update'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/transactions.rb:351:in `block in with_transaction_returning_status'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `block in transaction'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/transaction.rb:184:in `within_new_transaction'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/connection_adapters/abstract/database_statements.rb:213:in `transaction'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/transactions.rb:220:in `transaction'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/transactions.rb:348:in `with_transaction_returning_status'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/persistence.rb:250:in `update'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/relation.rb:369:in `update'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/relation.rb:366:in `block in update'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/relation.rb:366:in `map'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/relation.rb:366:in `with_index'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/relation.rb:366:in `update'
/usr/local/rvm/gems/ruby-2.2.1/gems/activerecord-4.2.4/lib/active_record/querying.rb:8:in `update'
/home/ubuntu/workspace/pf_middleware/lib/tasks/caching/calculate_stats.rake:42:in `block (4 levels) in <top (required)>'
Tasks: TOP => db:caching:stats:calculate

I was generating a rather large set of updates, so I used the following to ensure I was passing in what I expected and produced the same error.

School.update([1,2,3], [{apps: 11111},{apps: 22222},{apps: 33333}])
==> NoMethodError: undefined method `each' for 11111:Fixnum

I checked and rechecked the documentation, tried 'apps' instead of :apps. Double-checked that apps was a field in School, etc., but could not understand why I kept getting this error.

I decided to try a different field... and it worked!

hash = { 1 => { offers: 123 }, 2 => { offers: 321 } }
School.update(hash.keys, hash.values)

This leads me to believe that :apps / 'apps' is something special, but I cannot find proof of that. Does anyone have any thoughts?

Thanks!


Solution

  • OK, since you have totally changed your question since my first answer, here's another.

    When you do this

    School.update([1,2,3], [{apps: 11111},{apps: 22222},{apps: 33333}])
    

    It's like saying

    School.find(1).update_attributes({apps: 11111})
    School.find(1).update_attributes({apps: 22222})
    School.find(1).update_attributes({apps: 33333})
    

    And when you say

    School.find(1).update_attributes({apps: 11111})
    

    you are effectively saying

    school = School.find(1)
    school.apps = 11111
    school.save
    

    If your school class doesn't have an instance method called "apps=", or it does but that method doesn't expect an integer, it will raise an exception (or in the latter case, perhaps produce unpredictable results).

    In this case, if school has_many :apps then the "School#apps=" method is the one set up by the has_many association, and will expect an array of App objects.