bsky
bsky

Reputation: 20222

Rails - can not verify that at least one field is null

I have a class Prediction which belongs_to either a currency or a market.

  belongs_to :market
  belongs_to :currency

  validate :market_xor_currency?, on: [:new, :create, :edit, :update]

  def market_xor_currency?
    if(self.market != nil && self.currency != nil)
      false
    end
    true
  end

I am testing with Rspec in this manner:

p1 = FactoryGirl.create(:prediction)
p1.currency = FactoryGirl.create(:currency)
expect{ p1.market = FactoryGirl.create(:market) }.to raise_error

However, the test fails. How can I make Prediction belong to either a currency or a market?

Upvotes: 1

Views: 182

Answers (3)

MravAtomski
MravAtomski

Reputation: 26

I believe something like this should work in your case:

class MyValidator < ActiveModel::Validator
  def validate(record)
    if(record.market != nil && record.currency != nil)
      record.errors[:name] << 'market xor currency'
    end
  end
end

class SomeModel < ActiveRecord::Base
  include ActiveModel::Validations
  validates_with MyValidator
end

Upvotes: 0

Mohammad AbuShady
Mohammad AbuShady

Reputation: 42799

I think a polymorphic relation is more suitable for a such relation

class Market < ActiveRecord::Base
  has_many :predictions, as: :predictable
end

class Currency < ActiveRecord::Base
  has_many :predictions, as: :predictable
end

class Prediction < ActiveRecord::Base
  belongs_to :predictable, polymorphic: true
end

This way you won't need to validate any thing, because by definition the prediction can only belong to either one of them

More about polymorphic relations

if you still want to do it your way, then I think this validation method should work

def market_xor_currency?
  unless market.nil? ^ currency.nil?
    errors.add(:base, 'whatever error you want')
  end
end

Upvotes: 2

Shalev Shalit
Shalev Shalit

Reputation: 1963

In order to make custom method validation, you need to add error if not valid:

http://guides.rubyonrails.org/active_record_validations.html#custom-methods

Upvotes: 0

Related Questions