I have 2 models with a one-to-one relationship (example is simplified and not the real models).
class Person < ActiveRecord::Base
belongs_to :student, :foreig开发者_如何学Gon_key => 'name', :primary_key => 'full_name'
end
class Student < ActiveRecord::Base
belongs_to :person, :foreign_key => 'full_name', :primary_key => 'name'
end
The link between them is a weak link, since one can change the full_name field in the Student object and then the person object couldn't be reached from the student object.
So far so good (this is by design).
The problem arises when a person's name is the same as an equivalent student's full_name, but different in the letters' case.
The query for the MySQL DB returns a result (since MySQL is case-insensitive), but when Rails runs over the result it doesn't find it (since Rails is case-sensitive), which results in an Error when eagerly loading the association. Example of the error's stacktrace:
NoMethodError (You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.each):
vendor/rails/activerecord/lib/active_record/association_preload.rb:155:in `set_association_single_records'
...
I'm guessing this is a Rails 2.3.8 bug. Is there an easy solution for this problem?
Thanks!
No, this is not a Rails bug or a Ruby bug - Ruby strings are case-sensitive, so you should not expect this to work as is.
This is bad database design, but if you want to keep going down this road of madness, add a separate column lower_name
to each table that has the name forced to lowercase and use that as your AR association link. (The cleanest solution is to put a before_save
filter on each model to update lower_name
when the name changes.)
精彩评论