2010-03-24 1 views
3
class Followup < ActiveRecord::Base 
    belongs_to :post 
    belongs_to :comment 
end 

이 모델에는 게시물이나 댓글 만 있으면되지만 둘 중 하나만 있어야합니다.Rails를 사용하여 두 속성 중 하나만 존재하는 것을 확인하는 가장 우아한 방법은 무엇입니까?

여기에 내가 뭘하려는거야 대한 RSpec에있다 : 나는이 작업을 수행하는 솔루션의 무리를 볼 수 있습니다

it "should be impossible to have both a comment and a post" do 
    followup = Followup.make 
    followup.comment = Comment.make 
    followup.should be_valid 
    followup.post = Post.make 
    followup.should_not be_valid 
    end 

,하지만이 일의 가장 우아한 방법이 될 것이다?

답변

7

정말 원하는 것은 다형성 연관입니다.

Ryan은 Railscast #154에 대해 설명합니다.

class Followup < ActiveRecord::Base 
    belongs_to :followupable, :polymorphic => true 
end 

class Post < ActiveRecord::Base 
    has_many :followups, :as => :followupable 
end 

class Comment < ActiveRecord::Base 
    has_many :followups, :as => :followupable 
end 
+0

답변 해 주셔서 감사합니다. 나는 단지 2 개의 연관성을 가지고 있었기 때문에 다형성을 사용하는 것을 망설였습니다. 아직도 망설이지 만 그게 멋지다는 것을 알았습니다. ^^ – marcgg

1

우아함의 문제는 주관적 물론이지만 다음 예는 제공된 두 값없이 값이 제공 즉 2 개 무효 조건에 대해 별도의 오류 메시지를 포함하여, 정확하게 당신이 원하는 것을 할 것입니다. 더 솔루션의

class Foo < ActiveRecord::Base 
    validate :one_and_only_one 

    def one_and_only_one() 
    errors.add_to_base("You must provide either a foo or a bar") 
     if self.foo.blank? && self.bar.blank? 
    errors.add_to_base("You cannot provide both a foo and a bar") 
     if !self.foo.blank? && !self.bar.blank? 
    end 
end 

편집

생각 다음이이 공간이 채워 필드에 실패했지만

errors.add_to_base("You must provide either a foo or a bar") 
    unless [f.foo, f.bar].compact.length == 1 

우아함 테스트가 잘 통과 할 수 있습니다.

+0

답변을 주셔서 감사 드리며 편집을 위해 +1 해 주셨습니다.하지만 여전히 칙칙한 해결책이 여전히 좋다고 생각합니다. – marcgg

+0

나는 당신과 동의 할 것입니다. 나는 다형성에 대한 대안을 생각하고 있었지만 그렇게 해냈습니다. –

관련 문제