У меня есть модель профиля
class Profile < ActiveRecord::Base
attr_accessible :user_id, :race_id, :nickname, :first_name, :last_name, :gender, :birth_date, :eighteen,
:time_zone, :metric_scale, :referral_code, :referrer_id, :tag_line
# Relationships
belongs_to :user
belongs_to :race
belongs_to :referred_by, :class_name => "Profile", :foreign_key => "referral_code"
has_many :referrals, :class_name => "Profile", :foreign_key => "referrer_id"
# Validations
validates :user_id, :race_id, :nickname, :first_name, :last_name, :time_zone, :gender, :presence => true
validates :referral_code, :nickname, :uniqueness => { :case_sensitive => false }
# Instance Methods
def full_name
first_name + " " + last_name
end
# Class Methods
def self.search(search)
search_condition = "%" + search + "%"
find(:all, :conditions => ['nickname LIKE ?', search_condition])
end
def self.find_by_referral_code(referrer_code)
find(:one, :conditions => ['referral_code LIKE ?', referrer_code])
end
end
Независимо от того, в каком столбце я обновляю ограничение уникальности для «referral_code» false, я не могу обновить модель и не могу понять, почему. Из того, что я читал в сети по состоянию на Rails 3, ActiveRecord должен был отслеживать грязные объекты и генерировать только запросы на обновление, содержащие измененные столбцы, оставляя все остальные в покое. Поскольку он должен выполнять запросы на обновление только для столбцов, отличных от уникальных, проверка не должна завершаться сбоем. К сожалению это так. Вот сеанс Rails Console, отображающий это:
Loading development environment (Rails 3.0.9)
ruby-1.9.2-p180 :001 > profile = Profile.find(3)
=> #<Profile id: 3, user_id: 3, race_id: 2, nickname: "Premium-User", first_name: "Premium", last_name: "User", gender: "M", birth_date: "1977-01-01", eighteen: true, complete: true, time_zone: "Kuala Lumpur", metric_scale: false, referral_code: "bo", referrer_id: nil, tag_line: "This is what its like.", created_at: "2011-09-21 04:08:00", updated_at: "2011-09-21 04:08:00">
ruby-1.9.2-p180 :002 > update = {"tag_line"=>"Changed to this"}
=> {"tag_line"=>"Changed to this"}
ruby-1.9.2-p180 :003 > profile.update_attributes(update)
=> false
ruby-1.9.2-p180 :004 > profile.errors
=> {:referral_code=>["has already been taken"]}
Даже выполнение обновления непосредственно для одного столбца, который не является уникальным, приводит к сбою ограничения уникальности, и запись не будет обновлена, вот сеанс консоли:
Loading development environment (Rails 3.0.9)
ruby-1.9.2-p180 :001 > profile = Profile.find(3)
=> #<Profile id: 3, user_id: 3, race_id: 2, nickname: "Premium-User", first_name: "Premium", last_name: "User", gender: "M", birth_date: "1977-01-01", eighteen: true, complete: true, time_zone: "Kuala Lumpur", metric_scale: false, referral_code: "bo", referrer_id: nil, tag_line: "This is what its like.", created_at: "2011-09-21 04:08:00", updated_at: "2011-09-21 04:08:00">
ruby-1.9.2-p180 :002 > profile.tag_line = "changed to this"
=> "changed to this"
ruby-1.9.2-p180 :003 > profile.save
=> false
ruby-1.9.2-p180 :004 > profile.errors
=> {:referral_code=>["has already been taken"]}
Я также запустил проверку, чтобы увидеть, действительно ли ActiveRecord отслеживал грязный объект, и это, похоже, вот сеанс консоли:
Loading development environment (Rails 3.0.9)
ruby-1.9.2-p180 :001 > profile = Profile.find(3)
=> #<Profile id: 3, user_id: 3, race_id: 2, nickname: "Premium-User", first_name: "Premium", last_name: "User", gender: "M", birth_date: "1977-01-01", eighteen: true, complete: true, time_zone: "Kuala Lumpur", metric_scale: false, referral_code: "bo", referrer_id: nil, tag_line: "This is what its like.", created_at: "2011-09-21 04:08:00", updated_at: "2011-09-21 04:08:00">
ruby-1.9.2-p180 :002 > profile.tag_line = "change to this"
=> "change to this"
ruby-1.9.2-p180 :003 > profile.changes
=> {"tag_line"=>["This is what its like.", "change to this"]}
ruby-1.9.2-p180 :004 > profile.save
=> false
ruby-1.9.2-p180 :005 > profile.errors
=> {:referral_code=>["has already been taken"]}
Честно говоря, я в растерянности, я потратил немало времени, копаясь в нем, а также в поиске в Google, и я не могу найти ответ, почему это происходит.