What is the most elegant way to check for ONLY one of two attributes using Rails?

class Followup < ActiveRecord::Base
  belongs_to :post
  belongs_to :comment
end

This model should have only a message or comment, but only one of two.

Here's rspec for what I'm trying to do:

  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

I can see a bunch of solutions to do this, but what would be the most elegant way to do this?

+3
source share
2 answers

I think you really need a polymorphic association.

Ryan does a great job explaining in 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
+7
source

, , , , , 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

, .

+1

Source: https://habr.com/ru/post/1738335/


All Articles