ruby-on-railsrubyvalidationclearance

How do disable email validation in Clearance


I'm trying to get Clearance to work with AWS Dynamo as the back-end store. The problem I'm having is that I can't get Clearance to not do the email-uniqueness validation, which it can't do because it's not able to do standard ActiveRecord uniqueness validations via a SQL query.

According to the comments in the code, I should be able to have my User object return email_optional? true, and that should disable the uniqueness validation on emails. So I have:

class User < ApplicationRecord
  include Dynamoid::Document
  include Clearance::User

  field :name
  field :email

  def email_optional?
    puts 'yes, email is optional'
    true
  end
end

But, when I try to create a user I get an error, and, more to the point, the puts is not executed:

$ rails c
Running via Spring preloader in process 18665
Loading development environment (Rails 5.1.3)
irb(main):001:0> u = User.new(name: 'ijd', email: 'ian@fu.bar', password: 'test')
ActiveRecord::StatementInvalid: Could not find table 'editor_development_users'
    from (irb):1

Update: the reply from @spickermann reminded me that I should have noted that I also tried without subclassing ActiveRecord::Base (via ApplicationRecord). It gives a different error:

class User
  include Dynamoid::Document
  ....
irb(main):002:0> reload!
Reloading...
=> true
irb(main):003:0> u = User.new(name: 'ijd', email: 'ian@fu.bar', password: 'test')
ArgumentError: Unknown validator: 'UniquenessValidator'
  from app/models/user.rb:4:in `include'
  from app/models/user.rb:4:in `<class:User>'
  from app/models/user.rb:2:in `<top (required)>'
  from (irb):3

Solution

  • User.new does not trigger validations. Therefore the error cannot be connected to the validations itself.

    At the moment your User model is kind of both: A subclass of ActiveRecord::Base and it behaves like a Dynamoid::Document.

    class User < ApplicationRecord 
      include Dynamoid::Document
    
      # ...
    end
    

    ActiveRecord::Base reads the table definition from the database when an instance is initialized. This leads to your exception, because the table does not exist. Just remove the inheritance from ApplicationRecord.

    class User
      include Dynamoid::Document
    
      # ...
    end
    

    The second issue when you remove the inheritance is more complex. Usually, I would suggest to just include ActiveModel::Validations when you want to validate models that do not inherit from ActiveRecord::Base. But the UniquenessValidator isn't defined in ActiveModel::Validations but in ActiveRecord::Validations (what makes kind of sense). This makes Clearance incompatible with models that do not inherit from ActiveRecord::Base.

    I would probably define a dummy implementation of a UniquenessValidator as a work-around:

    class User
      include Dynamoid::Document
    
      class UniquenessValidator
        def initialize(_options); end
        def def validate_each(_record, _attribute, _value); end
      end
    
      # ...
    end