感谢您回答我之前提出的问题,但我遇到了一个新问题。
我正在创建一个自定义验证程序,用于验证用户是否输入了干净的单词。这个 在我的UsersController上用作验证方法。
我使用的是Obscenity gem,但我创建了一些自己的方法来确保质量数据。
错误消息
NoMethodError: Undefined method include? for Nil:NilClass
问题在于,如果记录已经存在,我的方法可以工作,但是在创建记录期间它们不起作用。我尝试使用
来解决这个问题:on => [:create, :update]
但我仍然收到同样的错误。
验证方法
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
User.rb(型号)
class User < ActiveRecord::Base
include ActiveModel::Validations
validates_with MyValidator
has_many :favorites, foreign_key: "user_id", dependent: :destroy
has_many :pictures, through: :favorites
has_secure_password
before_create :create_remember_token
VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
validates_presence_of :name, :password, :email
validates_uniqueness_of :name, :email
validates :name, length: { in: 3..20 }
validates :password, length: { minimum: 6 }
validates :email, format: { with: VALID_EMAIL_REGEX }, length: { in: 8..50 }
validates_confirmation_of :password, if: lambda { |m| m.password.present? }
def User.new_remember_token
SecureRandom.urlsafe_base64
end
def User.digest(token)
Digest::SHA1.hexdigest(token.to_s)
end
private
def create_remember_token
self.remember_token = User.digest(User.new_remember_token)
end
end
我也尝试过使用except语句
def validate (user)
mystery_setup
unless User.all.include?(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
end
我尝试使用unless语句测试是否有用户,但是也没有。
根据类似问题的建议,我更改了我的迁移文件以对抗此区域。
class CreateUsers < ActiveRecord::Migration
def change
create_table :users do |t|
t.string :name, default: 'new'
t.string :password, default: 'new'
t.string :email, default: 'new'
t.timestamps
end
end
end
问题链接
undefined method `include?' for nil:NilClass with partial validation of wizard gem
参考代码
http://guides.rubyonrails.org/active_record_validations.html#performing-custom-validations
通过更改默认值来更改迁移文件并没有解决这个问题所以我决定在这里提出一个新问题。
此方法适用于更新记录,但不适用于创建新记录。
帮助表示赞赏。先谢谢你。
修改
刚刚收到了一个很好的建议,即以括号格式传递属性。我的代码现在看起来像这样
def validate (user)
mystery_setup
unless User.all.include?(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
目前,它只有电子邮件和密码属性的错误。如果我删除最后两个||@new_mysteries.any?我的方法用于过滤名称。
我想保持这种专业性,所以我想让它与其他两种方法一起使用。可能与我使用括号或||有关符号
坚定的进步人员,坚持下去。
修改
另外,如果我想在其他类上调用这些验证方法,将它放在帮助文件中会更好吗?
新更新
这是我的用户控制器代码
class UsersController < ApplicationController
before_action :signed_in_user, only: [:edit, :update, :destroy]
before_action :correct_user, only: [:edit, :update]
def index
@users = User.all
end
def show
@user = User.find(params[:id])
end
def new
@user = User.new
end
def create
@user = User.new(user_params)
if @user.save
flash[:success] = "Congratulations #{@user.name}! You have successfully created an account"
redirect_to games_path
else
render 'new'
end
end
def edit
end
def update
@user = User.find(params[:id])
end
def favorites
@user = User.find(current_user)
end
def destroy
end
private
def user_params
params.require(:user).permit(:name, :email, :password, :password_confirmation)
end
def signed_in_user
unless signed_in?
store_location
redirect_to signin_url notice: "Please sign in."
end
end
def correct_user
@user = User.find(params[:id])
redirect_to(root_url) unless current_user?(@user)
end
end
答案 0 :(得分:4)
|| @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.name && user.name.include?(mystery)
然而强烈推荐andand
gem,这将允许您将上述内容写成:
user.name.andand.include?(mystery)
答案 1 :(得分:4)
你可以这样写:
def validate (user)
mystery_setup
user.errors[:name] << 'Tsk! Tsk! Please select a different username' if
Obscenity.profane?(user[:name]) ||
[:name, :email, :password].product(@new_mysteries).any? { |sym, mystery|
(str = user.public_send sym) && str.include?(mystery) }
end
感谢@Arup的修复。
如果您希望减少实例变量的数量,可以将第一行更改为:
new_mysteries = mystery_setup
并将@new_mysteries
更改为new_mysteries
。
答案 2 :(得分:2)
试试这个:
def validate (user)
mystery_setup
unless User.all.include?(user)
if user.name && user.email && user.password
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
end
end
答案 3 :(得分:2)
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
mysteries.map{ |mystery| mystery.tr("A-Za-z", "N-ZA-Mn-za-m")}
end
def validate (user)
# No need to pollute the class with instance variables, just pass it back in a return
new_mysteries = mystery_setup
if Obscenity.profane?(user.name.to_s) ||
@new_mysteries.any?{ |mystery| user.name.to_s.include?(mystery) ||
user.email.to_s.include?(mystery) ||
user.password.to_s.include?(mystery)}
user.errors[:name] << 'Error: Please select a different username'
end
end
end
答案 4 :(得分:2)
我已经重构了一下代码,请告诉我这是否有效:
def validate (user)
mystery_setup
if Obscenity.profane?(user.name)
user.errors[:name] << 'Error: Please select a different username'
end
%w(name email password).each do |attr|
value = user.send(attr)
if value.present? and @new_mysteries.grep(/#{value}/).present?
user.errors[attr] << "Error: Please select a different user#{attr}"
end
end
end
答案 5 :(得分:2)
这部分是第一行的错误。
@mystery_words = # This is a mystery, I can't tell you.
@mystery_c = mystery_words.map(&:capitalize)
这应该是
@mystery_words = [] # This is a mystery, I can't tell you.
@mystery_c = mystery_words.map(&:capitalize)
答案 6 :(得分:0)
由于nil
是Ruby中原子虚无的表示,因此它从不包含任何内容。 include?
方法可以简单地定义为:
def nil.include? arg
false
end