重构小型服务

时间:2016-01-12 21:30:14

标签: ruby-on-rails ruby ruby-on-rails-4 refactoring

我有这个小代码

class ReadReportService
  def self.get_oldest_reports(count, filter={})
    reports = Report.unread.order('created_at DESC').limit(count)

    reports = reports.where(category: filter[:category]) if filter[:category].present?
    reports = reports.where(cost: filter[:cost]) if filter[:cost].present?
    reports = reports.where(email: filter[:email]) if filter[:email].present?

    reports.update_all(status: Report.statuses[:read])

    reports.to_a
  end
end

我能做得更好更好吗?如何改进检查哈希参数?

2 个答案:

答案 0 :(得分:0)

它应该在Report型号中:

class Report < ActiveRecord::Base
  STATUSES = {read: 'read', pending: 'pending'}

  scope :ordered_limit, ->(limit) { order('created_at DESC').limit(limit) }
  scope :filter_category, ->(category) { where(category: category) if category }
  scope :filter_cost, ->(cost) { where(cost: cost) if cost }
  scope :filter_email, ->(email) { where(email: email) if email }

  def self.get_oldest_reports(count, filter={})
    reports = unread.ordered_limit(count)
      .filter_category(filter[:category])
      .filter_cost(cost)
      .filter_email(email)
    reports.update_all(status: STATUSES[:read])

    reports.to_a # not sure you need it
  end
end

答案 1 :(得分:0)

如果您想简化适用于过滤器的代码,您可以执行以下操作:

reports = Report.unread.order('created_at DESC').limit(count)
[:category, :cost, :email].each do |key|
  reports = reports.where(key => filter[key]) if filter[key].present?
end
reports.update_all(status: Report.statuses[:read])
reports.to_a

顺便说一句,在名为update_all的方法中调用get_xxx并不是一个好主意。如果我得到了某些东西,我就不会期望某些东西会被改变。

P.S。如果你喜欢oneliners,你甚至可以做这样的事情:

reports.where(filter.slice(:category, :cost, :email).select { |k, v| v.present? })