我在自定义属性验证程序中遇到了一个奇怪的错误。我有以下设置,一切都按预期工作(每个类都包含模块API和V1):
# app/models/api/v1/business_account.rb
class BusinessAccount
has_many :transactions, class_name: BusinessAccountThings::Transaction
end
# app/models/api/v1/business_account_things/transaction.rb
module BusinessAccountThings
class Transaction
belongs_to :business_account
validates :amount, money: true
end
end
# app/validators/api/v1/money_validator.rb
class MoneyValidator < ActiveModel::EachValidator
def validate_each(record, attribute, value)
unless /^\d+\.*\d{0,2}$/ =~ value.to_s
record.errors[attribute] << 'Only two digits are allowed.'
end
end
end
我现在想在BusinessAccount
中使用自定义验证器,如下所示:
class BusinessAccount
has_many :transactions
validates :current_balance, money: true
end
我在运行BusinessAccount
的规范时遇到以下错误(尝试从Rails控制台加载类时出现类似错误):
/home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activemodel-4.2.4/lib/active_model/validations/validates.rb:120:in `rescue in block in validates': Unknown validator: 'MoneyValidator' (ArgumentError)
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activemodel-4.2.4/lib/active_model/validations/validates.rb:117:in `block in validates'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activemodel-4.2.4/lib/active_model/validations/validates.rb:113:in `each'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activemodel-4.2.4/lib/active_model/validations/validates.rb:113:in `validates'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account_things/transaction.rb:22:in `<class:Transaction>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account_things/transaction.rb:5:in `<module:BusinessAccountThings>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account_things/transaction.rb:3:in `<module:V1>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account_things/transaction.rb:2:in `<module:API>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account_things/transaction.rb:1:in `<top (required)>'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in `require'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in `block in require'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:240:in `load_dependency'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in `require'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:360:in `require_or_load'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:494:in `load_missing_constant'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:184:in `const_missing'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account.rb:16:in `<class:BusinessAccount>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account.rb:4:in `<module:V1>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account.rb:2:in `<module:API>'
from /home/hannes/workspaces/rails-app/app/models/api/v1/business_account.rb:1:in `<top (required)>'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in `require'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in `block in require'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:240:in `load_dependency'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:274:in `require'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:360:in `require_or_load'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:494:in `load_missing_constant'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/activesupport-4.2.4/lib/active_support/dependencies.rb:184:in `const_missing'
from /home/hannes/workspaces/rails-app/spec/models/api/v1/business_account_spec.rb:5:in `<top (required)>'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1361:in `load'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1361:in `block in load_spec_files'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1359:in `each'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/configuration.rb:1359:in `load_spec_files'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:106:in `setup'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:92:in `run'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:78:in `run'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/lib/rspec/core/runner.rb:45:in `invoke'
from /home/hannes/.rbenv/versions/2.2.5/lib/ruby/gems/2.2.0/gems/rspec-core-3.4.4/exe/rspec:4:in `<top (required)>'
from /home/hannes/.rbenv/versions/2.2.5/bin/rspec:23:in `load'
from /home/hannes/.rbenv/versions/2.2.5/bin/rspec:23:in `<main>'
BusinessAccount
中的第16行是has_many :transactions, class_name: BusinessAccountThings::Transaction, dependent: :destroy
Transaction
中的第22行是validates :amount, money: true
。
如果我从Transaction
删除第22行,问题就会消失。
如果我运行Transaction
的规范,我会收到此错误:
1) API::V1::BusinessAccountThings::Transaction
Failure/Error:
validates :current_balance,
numericality: { greater_than_or_equal_to: 0 },
money: true
ArgumentError:
Unknown validator: 'MoneyValidator'
# ./app/models/api/v1/business_account.rb:9:in `<class:BusinessAccount>'
# ./app/models/api/v1/business_account.rb:4:in `<module:V1>'
# ./app/models/api/v1/business_account.rb:2:in `<module:API>'
# ./app/models/api/v1/business_account.rb:1:in `<top (required)>'
# ./spec/models/api/v1/business_account_things/transaction_spec.rb:5:in `block (2 levels) in <top (required)>'
# ./spec/models/api/v1/business_account_things/transaction_spec.rb:7:in `block (2 levels) in <top (required)>'
# ------------------
# --- Caused by: ---
# NameError:
# uninitialized constant API::V1::BusinessAccount::MoneyValidator
# ./app/models/api/v1/business_account.rb:9:in `<class:BusinessAccount>'
所以看起来两个类似乎无法同时加载MoneyValidator
...我该如何解决这个问题?
答案 0 :(得分:1)
自动加载API::V1::MoneyValidator
因设置失败。
business_account.rb
正在尝试将其加载为API::V1::BusinessAccount::MoneyValidator
。这会失败,因为它在API::V1
下命名,而不是API::V1::BusinessAccount
。
自动加载还会尝试查找MoneyValidator
(没有命名空间;如源代码中所写)。因此,如果您将验证器类移出API::V1
命名空间并使其成为顶级常量,那么它应该可以工作。