Home > other >  normalize email when doing find_by(email: ...)
normalize email when doing find_by(email: ...)

Time:11-22

I normalize the email addresses in a before_validation, e.g.:

class User
  before_validation do
    self.email = normalized_email
  end

  def normalized_email
    User.normalize_email(email)
  end
end

But then I have to do User.find_by(email: User.normalize_email(params[:email])) everywhere for instance, and it bit me today when trying to find an user I forgot to normalize the email address, so I would like to have it done automatically.

Ideally I would not overwrite find_by and it would work for all the methods, like where for instance.

How can I do it?

CodePudding user response:

I would just define a special method for this use-case:

class User
  def self.by_email(email)
    find_by(email: User.normalize_email(email))
  end

  before_validation do
    self.email = normalized_email
  end

  def normalized_email
    User.normalize_email(email)
  end
end

Which can then be used like this:

User.by_email(params[:email])

Please note that I explicitly didn't suggest using a scope for this, because by convention scopes should be chainable and therefore should return ActiveRecord::Relations what doesn't work well when you only want to return a single record.

CodePudding user response:

You can override find_by in User to ensure this happens consistently.

  class << self
    def find_by(*args)
      # find_by can be called without a Hash, make sure.
      attrs = args.first
      super unless attrs.is_a?(Hash)

      # Cover both calling styles, find_by(email: ...) and find_by("email": ...)
      [:email, "email"].each do |key|
        # Be careful to not add email: nil to the query.
        attrs[key] = normalized_email(attrs[key]) if attrs.key?(key)
      end

      super
    end
  end

This also covers find_by!, find_or_*, and create_or_find_by* methods. It doesn't cover where nor raw SQL.

You could override where, but there's some odd caching happening which makes that troublesome.

  • Related