How to DRY using metaprogramming?

半城伤御伤魂 提交于 2019-12-11 02:18:51

问题


Seems like there should be a good way via MP to DRY this up:

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

回答1:


I would just have the length of time passed in as an argument:

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

See, it's still very readable:

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

For fun, here is the metaprogramming way:

{ :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



回答2:


If you are set on using those functions names I would do this:


class Dashboard

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

  [['three_days', 3], ['seven_days', 7], ['month', 30]].each do |name, days|
    class_eval <<-EVAL
      def self.num_registrations_past_#{name}
        User.recent_registrations(#{days}.days.ago).count
      end

      def self.avg_registrations_past_#{name}
        self.num_registrations_past_#{name} / #{days}.to_f
      end
    EVAL
  end

  def self.total_registered_users
    return User.count
  end

  def self.total_activated_users
    return User.total_activated
  end

end


来源:https://stackoverflow.com/questions/4858668/how-to-dry-using-metaprogramming

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!