【问题标题】:unable to refactor code rails 4 query无法重构代码 rails 4 查询
【发布时间】:2016-07-24 14:46:36
【问题描述】:

场景是,我想获取 2 个案例的所有时间段。

  1. 如果门卫为真,则查询将相同

  2. 如果 doorman 为 false 则需要在查询中添加参数

因此,几乎相同的查询几乎可以在两种情况下都适用,只需稍作修改。

这是查询和代码:

def self.latest_pickup_date current_zone,doorman
    if doorman
      latest_timeslot = Timeslot.where(dropoff_slots: '-1', zone_id: current_zone).order(:slot_date).last
    else
      latest_timeslot = Timeslot.where(dropoff_slots: '-1', zone_id: current_zone, doorman_type: "none").order(:slot_date).last
    end
    latest_timeslot.nil? ? Date.current : latest_timeslot.slot_date
  end

我想以使用 DRY 方法的方式重构我的代码和查询。

我不想在这两种情况下都写两次这些查询。我需要使用代码实践的更好解决方案。或者,如果我这样做是正确的,您也可以提出建议。

如果有人可以提供帮助,还需要良好的专业代码实践和代码重构。

【问题讨论】:

  • 您的问题标题是无法重构,为什么无法重构?你知道codereview.stackexchange.com吗?
  • @Зелёный 我没有那么多好的知识,而且我的专业知识有限,所以我发帖以获得专家的答案。我的目的不仅仅是得到答案。我自己也可以。好吧,我不知道 codereview.stackexchange.com
  • 你应该把这个问题发到codereview.stackexchange.com

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


【解决方案1】:

您可以对现有查询执行 where 以添加附加条件,并使用 try 以防查询为空

def self.latest_pickup_date current_zone,doormam
  latest_timeslot = Timeslot.where(dropoff_slots: '-1', zone_id: current_zone).order(:slot_date)
  latest_timeslot = latest_timeslot.where(doorman_type: 'none') unless doorman
  latest_timeslot.last.try(:slot_date) || Date.current
end

【讨论】:

  • 采用这种方法。这是最干净的解决方案
  • 那是代码进行两次查询,虽然它只能进行一次查询,但try 这是一个不好的做法。
  • 我也是这么想的。看起来它进行了 2 个查询。无论如何,它确实运作良好。为什么try 是不好的做法?
  • 它不会进行两次查询。仅在请求结果时才进行查询。这就是 ActiveRecord 关系的工作方式,它可以轻松地以增量方式构建查询,而不会影响您的数据库。至于try 是一种“代码气味”,另一种选择是一些非常笨拙的latest_timeslot.last ? lastest_timeslot.last.slot_date : Date.current ...对我来说try 更优雅和可读。
【解决方案2】:

您能否检查以下重构代码,如果您喜欢这种方法,请告诉我。

def self.latest_pickup_date current_zone,doorman
  filters = {dropoff_slots: '-1', zone_id: current_zone}
  filters[:doorman_type] = "none" unless doorman

  latest_timeslot = Timeslot.where(filters).order(:slot_date).last

  latest_timeslot.nil? ? Date.current : latest_timeslot.slot_date
end

【讨论】:

  • 能否在代码中也添加 cmets ?谢谢顺便说一句。看起来不错。
  • 基本上 where 子句接受字典。因此,您可以单独传递过滤器列和值,也可以传递字典。在字典中,键应该是列名,值应该是您要用于过滤的值。这就是我这里所做的,filters = {dropoff_slots: '-1', zone_id: current_zone} #前两个字段filters[:doorman_type] = "none" unless doorman #可选字段latest_timeslot = Timeslot.where(filters) .order(:slot_date).last # 过滤器当doorman不为null时,将doorman_type添加到字典中。
  • 好的,您可以添加链接以阅读有关过滤器的更多信息吗?加一件事:filters[:doorman_type] 此代码在过滤器中添加另一个键?我对吗?我的意思是我们在字典中添加了其他 2 个关键字 filters[:doorman_type]
  • 您可以省略nil?Timeslot 常量。这不是很清楚,也不是很好的解决方案。
  • 你能不能试着让它变得更好?它甚至对我也不是很清楚。 @Зелёный
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多