将输入参数传递给自定义验证函数 ruby

问题描述 投票:0回答:1

我有两个类属性的两个自定义验证方法。两者共享相同的代码,但属性不同。你能帮我减少这里的代码重复吗?

validates validation_fcn_for_attr_1
validates validation_fcn_for_attr_2


def validation_fcn_for_attr1:
.
<same body with attr1>
.
end

def validation_fcn_for_attr2:
.
<same body with attr2>
.
end

这是我的用例:

validate :verify_valid_locations
validate :verify_loactions_for_vacation
validate :another_validation_fcn

validates :travel_dist, number: {greater_than: 0}

    def verify_valid_locations
        acceptable_locations = ["C", "T", "G"]
        unless locations.in? acceptable_locations
          errors.add(:base, 'Acceptable towns for move are "C", "T", "G"')
        end
    end

    def verify_loactions_for_vacation
        acceptable_locations = ["C", "T", "G"]
        unless vacation_locations.in? acceptable_locations
          errors.add(:base, 'Acceptable towns for paid vacation are "C", "T", "G"')
        end
    end
 
ruby-on-rails rails-activerecord
1个回答
2
投票

编辑:现在您已经提供了真实的代码,我发现您实际上是在进行包含验证,您可以使用内置的 Rails 验证技术来完成此操作。方法如下:

validates :locations,
          :vacation_locations,
          inclusion: { in: ['C', 'T', 'G'],
                       message: 'Acceptable towns are "C", "T", "G"' }

请注意,错误不会添加到

base
属性中,它们将添加到实际属性中。这几乎总是更可取的。
(您可能会考虑将消息扔到区域设置文件中,或者修改那里的现有消息,但这是另一天的讨论。)


有几种方法可以实现这一点。如果您提供有关实际示例的更多详细信息,我可以提供更多帮助。但现在您可以为共享代码设置一个辅助方法并从两种验证方法中调用它:

# app/models/model_name.rb
validate :validation_fcn_for_attr_1
validate :validation_fcn_for_attr_2

def validation_fcn_for_attr1
  helper(attr1)
end

def validation_fcn_for_attr2
  helper(attr2)
end

def helper(attr)
  .
  <shared body>
  .
end
private :helper

或者如果验证足够简单,您可能更喜欢:

# app/models/model_name.rb
validate :validation_fcn

def validation_fcn
  [attr_1, attr_2].each do |attr|
    .
    <shared body>
    .
  end
end
private :validation_fcn

或者您可以使用

validates_each
块:

validates_each :attr_1, :attr_2 do |record, attr, value|
  .
  <shared body>
  .
end

或者您可以创建一个完整的正确自定义验证器并在两个属性上调用它。如果您想走那条路,请告诉我,我可以提供帮助。 (如果您发布更接近您的实际验证技术和/或属性名称的内容可能会更容易。) 最终看起来像这样:

# app/models/model_name.rb
validates :attr_1,
          :attr_2,
          custom_validator_name: true
# app/validators/custom_validator_name.rb
class CustomValidatorName < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    .
    <validation code>
    .
  end
end
最新问题
© www.soinside.com 2019 - 2025. All rights reserved.