【问题标题】:How to DRY duplicated Model Methods in Ruby on Rails, by Modules or Classes?如何按模块或类在 Ruby on Rails 中干燥重复的模型方法?
【发布时间】:2015-02-03 17:27:03
【问题描述】:

喂。我是 Ruby on Rails 和 OOP 的新手。

我在一个小调度器上工作,并且想干掉我的模型方法。
我对 Rails 中 Module 和 Class 的使用做了一些说明,但找不到最好的方法。
difference-between-a-class-and-a-module
ruby-class-module-mixins

例子:

假设我有 2 个模型(基准和人)。
每个模型都有一个存储日期的属性,但具有不同的属性名称。

我在两个模块中编写了相同的日期验证方法。

我的模特:

class Datum < ActiveRecord::Base
 attr :start_date

 def validate_date
  # same validation stuff with self.start_at
 end
end


class Person < ActiveRecord::Base
 attr :birth_date

 def validate_date
  # same validation stuff with self.birth_date
 end
end


这是我对 lib/ModelHelper 和基准模型的尝试:

class Datum < ActiveRecord::Base
 include ModelHelper

 attr_accessible :start_at

 # Validations
 before_validation :validate_date, :start_at

end


module ModelHelper

 private

 def validate_date *var
  # validation stuff with birth_date and start_at 
 end
end


问题:
就我而言,我认为我需要分配一个参数(对于每个模型属性, :start_at 和 :bith_date )。
但我不知道怎么做。

使用 Module 或 Class 干燥我的模型的最佳方法是什么?
为什么以及如何?

【问题讨论】:

  • 我强烈建议您查看 codereview.stackexchange.com
  • 顺便说一下,我最近在 CodeReview.SE 上发布了一个关于自定义 Rails 4 验证器的答案:codereview.stackexchange.com/questions/71435/…
  • @Anthony 我的问题不仅仅针对代码审查。它更多地是关于通过给定的示例来理解 Ruby on Rails 中的模块和类。
  • @D-side 感谢您的评论,您的回答很有帮助。但这并不能解释我的问题。 使用 Module 或 Class 干燥我的模型的最佳方法是什么? 为什么和...?我很高兴获得更多答案。
  • @stephanfriedrich 在这个特定的上下文中,validate_date 可以分解为验证器类。然后,您将只有属性和验证规则的声明。足够干燥。

标签: ruby-on-rails model module dry


【解决方案1】:

正如@D-side 在 cmets 中所说,您最好的选择是创建一个Custom Validator

创建一个 app/validators 目录并添加一个名称类似于 my_date_validator.rb 的文件,内容如下:

# EachValidator is a validator which iterates through the attributes given in the
# options hash invoking the validate_each method passing in the record, attribute
# and value.
#
# All Active Model validations are built on top of this validator.
#
class MyDateValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    unless value_is_valid? # <- validate in here.
      record.errors[attribute] << (options[:message] || "is not a valid date")
    end
  end
end

并在您的模型中添加:

class Datum < ActiveRecord::Base
  validates :start_date, my_date: true
end

class Person < ActiveRecord::Base
  validates :birth_date, my_date: true
end

my_date 代表MyDateValidator 类名的第一部分。

如果你命名你的验证器:

  • FooValidator 然后你在你的模型验证中使用它作为 foo。
  • FooBarValidator 然后在模型验证中将其用作 foo_bar。
  • MyDateValidator 然后您在模型验证中将其用作 my_date。

另外,根据您想要验证的内容,您可能需要查看此 Gem:

https://github.com/johncarney/validates_timeliness

【讨论】:

  • 在此处添加一些引用:特定于应用的验证器的首选位置是app/validatorsgithub.com/bbatsov/rails-style-guide/blob/master/…
  • 感谢您的回复。但是你为什么不使用模型呢?
  • 或在您的示例/Rails 指南中。如果我尝试使用更多自定义验证器怎么办(我应该为每个验证器 c 类编写)
  • 我也不明白,my_date: true 代表什么?如果我按照我提到的方式运行验证( before_validation :validate_date )会怎样?
  • 谢谢@D-side 我根据您的评论更新了答案。
猜你喜欢
  • 1970-01-01
  • 2010-10-17
  • 1970-01-01
  • 1970-01-01
  • 2014-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多