【问题标题】:RSpec with website format validation fails具有网站格式验证的 RSpec 失败
【发布时间】:2016-04-12 07:11:20
【问题描述】:

我正在使用 rails4、factory_girl、rspec 和 shoulda 匹配器。如果我使用下面的代码运行 rspec,我会收到此错误:

Product should validate that :website cannot be empty/falsy, producing a custom validation error on failure
 Failure/Error: self.website = "http://#{self.website}" unless self.website[/^https?/]

 NoMethodError:
   undefined method `[]' for nil:NilClass

如果我从format_website 方法中删除unless self.website[/^https?/],我会收到此错误:

Product did not properly validate that :website cannot be empty/falsy,
   producing a custom validation error on failure.
     After setting :website to ‹nil› -- which was read back as ‹"http://"›
     -- the matcher expected the Product to be invalid and to produce a
     validation error matching ‹/can't be blank/› on :website. The record
     was indeed invalid, but it produced these validation errors instead:

     * user: ["can't be blank"]
     * name: ["can't be blank"]
     * company: ["can't be blank"]

我应该怎么做才能完成这项工作?

产品型号

belongs_to :user

validates :name, presence: { message: "can't be blank" }, length: { maximum: 140, message: "can't be longer than 140 characters" }, uniqueness: { message: "already exists" }
validates :company, presence: { message: "can't be blank" }, length: { maximum: 140, message: "can't be longer than 140 characters" }
validates :website, presence: { message: "can't be blank" }, length: { maximum: 140, message: "can't be longer than 140 characters" }

before_validation :format_website
validate :website_validator


def format_website
  self.website = "http://#{self.website}" unless self.website[/^https?/]
end

def website_validator
  self.errors.add :website, "format is invalid!" unless website_valid?
end

def website_valid?
  !!website.match(/^(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-=\?]*)*\/?$/)
end

工厂

FactoryGirl.define do
  factory :product do
    name { Faker::Commerce.product_name }
    company { Faker::Company.name }
    website { 'https://example.com' }
    user
  end
end

it { is_expected.to callback(:format_website).before(:validation) } #this one is not important, if I take out it still gives the same error
it { is_expected.to validate_presence_of(:name).with_message(/can't be blank/) }
it { is_expected.to validate_presence_of(:company).with_message(/can't be blank/) }
it { is_expected.to validate_presence_of(:website).with_message(/can't be blank/) }
it { is_expected.to belong_to(:user) }

【问题讨论】:

    标签: ruby-on-rails validation rspec factory-bot shoulda


    【解决方案1】:

    您应该确保website 不是nil

    def format_website
      return if website.blank?
    
      self.website = "http://#{self.website}" unless self.website[/^https?/]
    end
    

    在这种情况下,如果是 self.website == nil,您将尝试在 nil 对象上调用方法 [],因此会出现第一个错误。

    对于第二种情况,答案就在您从 rspec 获得的回报中:

    将 :website 设置为‹nil›后——读回为‹"http://"›

    你的方法format_website返回"http://",这是因为网站是nil。

    【讨论】:

    • born4new,我没有正确地问这个问题。我想知道如何解决此问题以使验证器正常工作。我应该使用其他类型的验证吗?
    • 再一次,很难说没有看到导致问题的规格,但我很确定当您使用 FactoryGirl 创建模型时,您不会实例化 website 属性。所以这样做,它应该可以解决它。
    • 能否请您也添加失败规范的代码?
    • 由于某些原因在您的规范中,当您在 format_website 方法中调用 self.website 时,它是 nil。在启动您的规范时,我会尝试在format_website 中添加一个binding.pry(撬宝石),看看为什么会发生这种事情。
    • born4new,请问您使用什么进行网站验证?我问这个问题是为了弄清楚最好的方法是什么。我只是用这个 rspec 例子来证明这个验证器不是最好的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-06-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多