Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shoulda-matcher How to validate uniqueness of enum attribute?

I use rspec-rails with shoulda-matcher to test my model. Here is the code:

user_ticket.rb

class UserTicket < ActiveRecord::Base
  belongs_to :user
  belongs_to :ticket

  enum relation_type: %w( creator supporter )

  validates_uniqueness_of :relation_type, scope: [:user_id, :ticket_id]
end

user_ticket_spec.rb

RSpec.describe UserTicket, type: :model do
  subject { FactoryGirl.build(:user_ticket) }

  describe 'Relations' do
    it { should belong_to(:user) }
    it { should belong_to(:ticket) }
  end

  describe 'Validations' do
    it { should define_enum_for(:relation_type).with(%w( creator supporter )) }
    # PROBLEM HERE
    it { should validate_uniqueness_of(:relation_type).case_insensitive.scoped_to([:user_id, :ticket_id]) }
  end
end

When I run the test case the result is always:

Failure/Error: it { should validate_uniqueness_of(:relation_type).case_insensitive.scoped_to([:user_id, :ticket_id]) }

     ArgumentError:
       'CREATOR' is not a valid relation_type

I just think shoulda matcher wants to validate the uniqueness with some kinds of relation_type values: uppercase, lowercase,..etc. My question is in this situation, how to make the test pass with such of defined model validations?

like image 885
Hieu Pham Avatar asked Dec 14 '22 03:12

Hieu Pham


1 Answers

It's failing because you're asking it to test validation case insensitively. Typically this would be used to test a range of values with different cases cause validation to fail. However, you're not even allowed to set the value because of the enum; it doesn't even get to the validation check.

It is testing the validation with "creator" and "CREATOR" (at least). enums are case sensitive so these would be two different values in the enum and you've only declared "creator". When it tries to assign "CREATOR" to test the validation your enum gets upset and refuses to allow it.

You may want to validate the uniqueness without case sensitivity in which case you want:

validate_uniqueness_of(:relation_type).ignoring_case_sensitivity

From the validates_uniqueness_of docs:

By default, validate_uniqueness_of will check that the validation is case sensitive: it asserts that uniquable attributes pass validation when their values are in a different case than corresponding attributes in the pre-existing record.

Use ignoring_case_sensitivity to skip this check.

Or you might want to skip the uniqueness checks in your test altogether and trust that rails only allows unique values in an enum.

like image 163
Shadwell Avatar answered Dec 30 '22 07:12

Shadwell