rails: instance.destroy leads to undefined method `to_sym' for nil:NilClass
Sample model structure:
class Base::Role < ActiveRecord::Base
self.table_name = 'roles'
self.abstract_class = true
end
class Base::Power < ActiveRecord::Base
self.abstract_class = true
end
class Base::Organization < ActiveRecord::Base
self.abstract_class = true
end
class Power < Base::Power
self.primary_key = 'id'
has_and_belongs_to_many :roles, class_name: 'Role'
end
class Role < Base::Role
has_and_belongs_to_many :powers, class_name: 'Power'
belongs_to :organization, class_name: 'Organization'
end
class Organization < Base::Organization
self.primary_key = 'id'
has_many :roles, class_name: 'Role'
end
class Mod::Power < Power; end
class Mod::Organization < Organization; end
class Mod::Role < Role; end
Doing Mod::Role(id).destroy
works like a charm. However, this does not work:
Mod::Role.includes(:powers).where(organization_id: 'ORG_00001').find(id).destroy
Causes this NoMethodError
:
NoMethodError: undefined method `to_sym' for nil:NilClass
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/sanitization.rb:58:in `block in expand_hash_conditions_for_aggregates'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/sanitization.rb:57:in `each'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/sanitization.rb:57:in `expand_hash_conditions_for_aggregates'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/relation/query_methods.rb:923:in `build_where'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/relation/query_methods.rb:555:in `where!'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/relation/query_methods.rb:545:in `where'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/has_many_association.rb:117:in `delete_records'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:472:in `remove_records'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:465:in `block in delete_or_destroy'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:148:in `block in transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/connection_adapters/abstract/database_statements.rb:198:in `transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/transactions.rb:211:in `transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:147:in `transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:465:in `delete_or_destroy'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:233:in `delete'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/associations/collection_association.rb:178:in `delete_all'
... 11 levels.user
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/transactions.rb:267:in `block in destroy'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/transactions.rb:329:in `block in with_transaction_returning_status'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `block in transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/connection_adapters/abstract/database_statements.rb:208:in `within_new_transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/connection_adapters/abstract/database_statements.rb:200:in `transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/transactions.rb:211:in `transaction'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/transactions.rb:326:in `with_transaction_returning_status'
from /Users/user/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/transactions.rb:267:in `destroy'
I tried debugging the problem and got into AR internals. This is the problem:
From: /Users/davidhorsak/.rvm/gems/ruby-2.1.0@mpx-um-app/gems/activerecord-4.1.0.beta1/lib/active_record/sanitization.rb @ line 58 ActiveRecord::Sanitization::ClassMethods#expand_hash_conditions_for_aggregates:
55: def expand_hash_conditions_for_aggregates(attrs)
56: expanded_attrs = {}
57: attrs.each do |attr, value|
=> 58: if aggregation = reflect_on_aggregation(attr.to_sym)
59: mapping = aggregation.mapping
60: mapping.each do |field_attr, aggregate_attr|
61: if mapping.size == 1 && !value.respond_to?(aggregate_attr)
62: expanded_attrs[field_attr] = value
63: else
64: expanded_attrs[field_attr] = value.send(aggregate_attr)
65: end
66: end
67: else
68: expanded_attrs[attr] = value
69: end
70: end
71: expanded_attrs
72: end
[61] pry(HABTM_Powers)> attrs
=> {nil=>[#<#<Class:0x00000108b03110> power_id: "af_index_groups", role_id: 8>]}
As seen form the backtrace, we are running Ruby 2.1 and Rails 4.1.0.beta. This problem is not present on Rails 4.0.2.
I tried making a small program where I would replicate the problem on the mentioned sample structure but failed. Let me know if I can provide more info on this topic.
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Comments: 18 (6 by maintainers)
@sgrif sorry for the confusion here!
I wasn’t trying to make anything happen or request any changes - was merely posting our solution in the event of someone searching Google and coming along this issue (like I had).
I’ll adjust my comment to be more specific.
Thanks for your hard work on Rails!
It seems that Active Record expects a
primary_key: true
on a column if you doid: false
.Commenting on old closed issues will not make anything happen. If you are experiencing something you believe to be a bug, please open a new issue with steps to reproduce using our standard bug report template.
I stumbled across this today - I’m using Rails 5, but it seems like the same exact issue still happens. In my case the issue was that the join table had no primary key column. Removing
id: false
from the table migration and re-running it fixed the issue with instance.destroy.This might also help people who land here from Google (as I did). Also this.
@bengotow I ran into this issue as well - it looks like the reason was because our project was using a join table, but also using
has_many through:
.Posting details about it in case someone else runs into the same problem:
The Problem:
We were incorrectly wiring up a
has_and_belongs_to_many
relationship.We also had a
UserRole
class (not exactly sure why).Because of this, we were experiencing the same issue as above:
The Fix
If using
has_and_belongs_to_many
instead ofhas_many through:
with a generatedjoin_table
, Rails will automatically do what’s necessary.Not sure it is relevant. But i created relational table for has many relation without primary key(id: false in migration). I had to remove it to make the delete work. It may save some poor souls.