未定义的方法'any?'为零:NilClass

时间:2014-08-04 20:18:26

标签: ruby-on-rails ruby instance-variables

我试图创建一个验证器来验证用户是否输入了一个干净的单词。我使用了Obscenity gem,但创建了一些自己的方法来确保质量数据。

class MyValidator < ActiveModel::Validator

  @mystery_words = # This is a mystery, I can't tell you.
  @mystery_c = @mystery_words.map(&:capitalize)
  @mystery_u = @mystery_words.map(&:upcase)
  @mysteries = @mystery_words + @mystery_c + @mystery_u
  @new_mysteries = @mysteries.map{|mystery|mystery.tr("A-Za-z", "N-ZA-Mn-za-m")}

  def validate (user)
    if Obscenity.profane?(user.name) \ 
    || @new_mysteries.any?{|mystery|user.name.include?(mystery)} \
    || @new_mysteries.any?{|mystery|user.email.include?(mystery)} \
    || @new_mysteries.any?{|mystery|user.password.include?(mystery)}
      user.errors[:name] << 'Error: Please select a different username'
    end
  end
end

class User < ActiveRecord::Base

  include ActiveModel::Validations
  validates_with MyValidator

错误消息

NoMethodError: undefined method any? for nil:NilClass

我不明白为什么收到这条消息。

2 个答案:

答案 0 :(得分:1)

代码中存在可变范围的问题。请尝试以下方法:

class MyValidator < ActiveModel::Validator

  def mystery_setup
    @mystery_words = # This is a mystery, I can't tell you.
    @mystery_c = @mystery_words.map(&:capitalize)
    @mystery_u = @mystery_words.map(&:upcase)
    @mysteries = @mystery_words + @mystery_c + @mystery_u
    @new_mysteries = @mysteries.map { |mystery| mystery.tr("A-Za-z", "N-ZA-Mn-za-m") }
  end

  def validate(user)
    mystery_setup

    if Obscenity.profane?(user.name) || @new_mysteries.any?{|mystery|user.name.include?(mystery)} || @new_mysteries.any?{|mystery|user.email.include?(mystery)} \
    || @new_mysteries.any?{|mystery|user.password.include?(mystery)}
      user.errors[:name] << 'Error: Please select a different username'
    end
  end
end

答案 1 :(得分:1)

您已在类上定义@new_mysteries,而不是在实例上定义。

考虑:

class MyValidator

  @new_mysteries = ['a','b','c']

  def validate
    p @new_mysteries
  end
end

MyValidator.new.validate
# => nil

validate方法中,@变量引用实例上的变量(由new创建的实例)。在方法定义之外,@变量引用类本身的实例。因此断开了。

我可能会在构造函数中声明@new_mysteries

class MyValidator

  def initialize
    @new_mysteries = ['a','b','c']
  end

  def validate
    p @new_mysteries
  end
end

MyValidator.new.validate
# => ["a", "b", "c"]

进一步阅读:http://www.railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/