【问题标题】:How to DRY using metaprogramming?如何使用元编程进行干燥?
【发布时间】:2011-02-01 03:44:43
【问题描述】:

似乎应该有一个通过 MP 的好方法来干燥这个:

class Dashboard

  def self.num_registrations_past_day
    return User.recent_registrations(24.hours.ago).count
  end

  def self.num_registrations_past_three_days
    return User.recent_registrations(3.days.ago).count
  end

  def self.num_registrations_past_seven_days
    return User.recent_registrations(7.days.ago).count
  end

  def self.num_registrations_past_month
    return User.recent_registrations(30.days.ago).count
  end

  def self.avg_registrations_past_three_days
    return (self.num_registrations_past_three_days / 3.to_f)
  end

  def self.avg_registrations_past_seven_days
    return (self.num_registrations_past_seven_days / 7.to_f)
  end

  def self.avg_registrations_past_month
    return (self.num_registrations_past_month / 30.to_f)
  end

  def self.total_registered_users
    return User.count
  end

  def self.total_activated_users
    return User.total_activated
  end

end

【问题讨论】:

    标签: ruby-on-rails metaprogramming dry


    【解决方案1】:

    我只想将时间长度作为参数传入:

    def self.num_registrations_since(time)
      User.recent_registrations(time).count
    end
    
    def self.avg_registrations_since(time)
      self.num_registrations_since(time) / ((Time.now - time) / 1.day)
    end
    

    你看,它还是很可读的:

    Dashboard.num_registrations_since(3.days.ago)
    Dashboard.avg_registrations_since(7.days.ago)
    

    为了好玩,这里是元编程方式:

    { :day => 24.hours.ago,
      :three_days => 3.days.ago,
      :seven_days => 7.days.ago,
      :month => 30.days.ago }.each do |method_suffix, time|
      define_singleton_method "num_registrations_past_#{method_suffix}" do
        User.recent_registrations(time).count
      end
      define_singleton_method "avg_registrations_past_#{method_suffix}" do
        self.send("num_registrations_past_#{method_suffix}") / ((Time.now - time) / 1.day)
      end
    end
    

    【讨论】:

    • 您将如何使用 MP 方法处理平均值?
    • 我更新了我的示例以展示如何处理两种方式的平均值。我仍然建议使用第一种方式,将时间传递给方法,而不是每次都定义一个新方法。用元编程来做这件事真的很麻烦。
    【解决方案2】:

    如果您打算使用这些函数名称,我会这样做:

    班级仪表板 def self.num_registrations_past_day 返回 User.recent_registrations(24.hours.ago).count 结尾 [['three_days', 3], ['seven_days', 7], ['month', 30]].each do |name, days| class_eval

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-06-05
      • 2018-08-29
      • 2014-12-13
      • 1970-01-01
      • 2011-06-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多