【问题标题】:global methods in ruby on rails modelsruby on rails 模型中的全局方法
【发布时间】:2009-05-14 14:20:47
【问题描述】:

我的所有模型中都有如下所示的方法:

def formatted_start_date
  start_date ? start_date.to_s(:date) : nil
end

我想要为每个模型中的每个日期时间字段自动编写这样的方法,最好的方法是什么?

-C

【问题讨论】:

    标签: ruby-on-rails activerecord model


    【解决方案1】:

    我只需要回答这个问题,因为这是一个有趣的 Ruby 练习。

    向类中添加方法可以通过多种方式完成,但最巧妙的方式之一是使用 Ruby 的一些反射和求值特性。

    在您的 lib 文件夹中将此文件创建为 lib/date_methods.rb

    module DateMethods
    
      def self.included(klass)
    
        # get all dates
        # Loop through the class's column names
        # then determine if each column is of the :date type.
        fields = klass.column_names.select do |k| 
                      klass.columns_hash[k].type == :date
                    end
    
    
        # for each of the fields we'll use class_eval to
        # define the methods.
        fields.each do |field|
          klass.class_eval <<-EOF
            def formatted_#{field}
              #{field} ? #{field}.to_s(:date) : nil
            end
    
          EOF
        end
      end
    end
    

    现在只需将它包含到任何需要它的模型中

     class CourseSection < ActiveRecord::Base
       include DateMethods
     end
    

    包含后,该模块将查看任何日期列并为您生成 formatted_ 方法。

    了解这些 Ruby 的工作原理。其乐无穷。

    也就是说,你必须问问自己这是否有必要。我不认为这是出于个人原因,但同样,写起来很有趣。

    -b-

    【讨论】:

    • 为什么在数组上使用 collect 和 compact 而不是 select?
    • 你是对的。 .select 在这里更合适。我发现 .collect.compact 更快的时候,即使它看起来不应该,但在这种情况下 .select 是一个更好的选择。谢谢你抓住那个。我专注于做困难的事情而错过了简单的事情。
    • +1 有趣的东西。如果您更正答案(此处为 SO)以包括 Chris 的 cmets 会更好。
    【解决方案2】:

    它看起来更像是我的帮手。在您的应用程序帮助中尝试此操作:

    def formatted_date(date)
       date ? date.to_s(:date) : nil
    end
    

    格式化并不是真正属于模型的东西(正是因为您发现的原因......在每个模型中都放置这样的通用代码很烦人)

    如果你真的想按照你说的去做,那么你可以做的是对 ActiveRecord 超类进行猴子补丁并将你想要的函数添加到那里。然后它将可用于您的所有模型。请注意,monkeypatching 可能导致不可预测和未定义的行为,使用风险自负!它也很hacky :)

    class ActiveRecord::Base
       def formatted_start_date
          start_date ? start_date.to_s(:date) : nil
       end
    end
    

    只需在应用中其他任何内容之前运行的某个位置粘贴它,它就会动态地将方法添加到模型的基类中,使其可供使用。

    或者您可以为所有模型创建一个 mixin,但这对于单个方法来说似乎有点矫枉过正。

    【讨论】:

    • 好的,让我们假设将格式放入模型中是合适的,或者除了对应用程序中的每个日期字段进行格式化之外,我还想做其他事情,我该怎么做?
    • 是的,但是“start_date”部分在这里是硬编码的,我需要对应用程序中的所有日期字段执行此操作,它们可以称为 start_date、end_date、term_date、finish_date、date 等..我如何检查所有日期列的子类,然后为每个列编写一个动态方法?
    • 我不知道……这听起来是个坏主意:P
    【解决方案3】:

    对您的评论的回答: 您可以将通用代码/功能提取到包含在类中的模块中(我相信这称为 mixin?),或者您可以使用子类。我不认为子类只是您想要进入对象的常用功能,而不是真正的继承情况。

    看看this for more info on modules and Ruby

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2010-10-17
      • 2014-11-14
      • 1970-01-01
      • 2011-03-05
      • 2015-06-14
      • 2020-04-23
      • 2016-11-04
      • 2014-01-31
      相关资源
      最近更新 更多