2011-09-30 3 views
0

프로필 모델Rails 3.0.9 : 업데이트 할 때마다 ActiveRecord 고유성 제약 조건이 실패하고 고유 한 열을 건 드리면 문제가되지 않습니다.

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'에 대한 고유성 제약 조건을 업데이트하고 모델을 업데이트 할 수 없으며 그 이유를 파악할 수 없습니다. 내가 레일스 3 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 > 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을 검색하는 것뿐만 아니라 시간을 많이 들여서 이런 일이 발생하는 이유에 대한 답을 찾을 수 없습니다.

+2

Profile.find_all_by_referral_code (profile.referral_code)에서 얻는 혜택은 무엇입니까? – klochner

+1

이 제약은 데이터베이스 수준에서도 구현됩니까? 해당 테이블에 대한 DDL을 덤프하고 거기에 키/제약 조건이 있는지 확인하십시오. 또한 log/development.log를 확인하여 업데이트가 실행중인 실제 SQL 쿼리를 가져옵니다. –

답변

0

레일즈는 더티 컬럼을 "추적"하고 필요한 최소 업데이트 구문을 생성합니다. log/development.log 파일을 보면 생성되는 실제 SQL을 볼 수 있으며, 업데이트 된 문장은 편집 한 컬럼 만 건드린다는 것을 알 수있다. 적어도 당신의 코드가 그렇게까지 나아 간다면

모델을 저장하기 전에 Rails는 모든 유효성 검사를 실행하며 참조 코드가 고유한지 여부를 확인합니다. 이렇게하기 위해 검사 할 데이터베이스에 대해 선택 SQL 문을 실행합니다. development.log 파일을 보면 분명히이 쿼리를 볼 수 있습니다.

레일스가 올바르게 작동합니다.

추천 코드가 고유해야한다고 생각되는 이유는 무엇입니까? 제 추측은 당신이 무 (Nil) 또는 빈 코드 (Blank Code)로 모델을 저장하려고한다는 것입니다. 이 경우 :allow_nil => true 또는 :allow_blank => true을 : 고유성 해시에 추가하십시오.

관련 문제