在使用'undefined method downcase'验证方法破坏规范之前

时间:2017-12-21 00:39:35

标签: ruby-on-rails validation rspec

在我的用户模型中,我有一个名为normalize_params的before_validation方法,它使用downcase。

class User < ApplicationRecord
  before_validation :normalize_params, on: [:create, :update]

  validates :email, :presence => true
  validates :email, :uniqueness => true

  validates :username, :presence => true
  validates :username, :uniqueness => true

  validates_confirmation_of :password

  scope :all_users_except, -> (current_user) {
    where.not(id: current_user)
  }

  has_attached_file :avatar, styles: { medium: "300x300>", thumb: 
  "100x100>" }, default_url: "/images/missing.png"
  validates_attachment_content_type :avatar, content_type: 
  /\Aimage\/.*\z/
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
     :recoverable, :rememberable, :trackable, :validatable

  private

  def normalize_params
    self.name = name.downcase.titleize
    self.email = email.downcase
    self.home = home.downcase.titleize
  end
end

所有这一切都在我的应用程序中完美运行,但是当我们的测试因为这个错误而打到小写时我的测试会中断...

NoMethodError:
  undefined method `downcase' for nil:NilClass

以下是我的测试......

require 'rails_helper'

describe User, 'validation' do
  it { should validate_presence_of :email }
  it { should validate_presence_of :username }
  it { should validate_presence_of :password }
end

如果我将before_validation和normalize_params取出,那么我的测试就会通过。

2 个答案:

答案 0 :(得分:3)

根据documentation示例,您可以在{}之前使用attribute_present?

class User < ApplicationRecord
  before_validation :normalize_params, on: %i[create update]

  validates :email,    presence: true, uniqueness: true
  validates :username, presence: true, uniqueness: true

  private

  def normalize_params
    titleize_name
    downcase_email
    # You can any other here.
  end

  def titleize_name
    self.name = name.downcase.titleize if attribute_present? 'name'
  end

  def downcase_email
    self.email = email.downcase if attribute_present? 'email'
  end
end

请注意:

  • 使用%i[]创建符号数组。
  • 通过用逗号分隔它们来验证状态和唯一性。
  • 首选is_expected.to而不是should语法(it { is_expected.to validate_presence_of :attribute }
  • 将每个属性修改分开以便轻松工作并包含它们。
  • 在不需要时避免使用哈希火箭。见ruby-style-guide#hash-literals

答案 1 :(得分:2)

nameemailhome中的任何一个可能是nil。我建议使用safe navigation operator

def normalize_params
  self.name = name&.downcase&.titleize
  self.email = email&.downcase
  self.home = home&.downcase&.titleize
end