模型中的重构:出了什么问题?

时间:2009-02-14 23:29:37

标签: ruby-on-rails refactoring models

我正在尝试干掉这个初始详细的代码:

def planting_dates_not_nil?
    !plant_out_week_min.blank? || !plant_out_week_max.blank? || !sow_out_week_min.blank? || !sow_out_week_max.blank?
  end

  def needs_planting?(week)
    if !plant_out_week_min.blank? && !plant_out_week_max.blank?
      (plant_out_week_min..plant_out_week_max).include? (week) 
    end
  end

  def needs_sowing?(week)
    if !sow_out_week_min.blank? && !sow_out_week_max.blank?
      (sow_out_week_min..sow_out_week_max).include? (week)
    end 
  end

  def needs_harvesting?(week)
    if !harvest_week_min.blank? && !harvest_week_max.blank?
      (harvest_week_min..harvest_week_max).include? (week) 
    end
  end

这是我的初步尝试:

  def tasks_for_week(week,*task_names)
    task_names.each do |task_name|
      to_do_this_week = []
        unless read_attribute(task_name).nil?
          if (read_attribute("#{task_name}_week_min")..read_attribute("#{task_name}_week_max")).include? (week)
            to_do_this_week << task_name
          end
        end
      end
  end

但是,当我在控制台中运行此代码时,如下所示:

p.tasks_for_week(Date.today.cweek, :plant_out, :sow_out])

我得到了意想不到的结果......即使工厂不需要种植,我仍然得到一个返回两个任务名称的数组([:plant_out,:sow_out]

任何人都可以告诉我如何清理它并让tasksforweek方法返回预期的结果吗?

TIA

3 个答案:

答案 0 :(得分:1)

您的方法返回task_names.each的结果。 each始终返回它的开头。所以你需要实际返回你的结果。

此外,您将在循环的每次迭代中重新创建to_do_this_week数组,这将清除它。

def tasks_for_week(week, *task_names)
  to_do_this_week = []
  task_names.each do |task_name|
    if some_condition
      to_do_this_week << task_name 
    end
  end
  to_do_this_week
end

或者这个:

def tasks_for_week(week, *task_names)
  returning [] do |to_do_this_week|
    task_names.each do |task_name|
      if some_condition
        to_do_this_week << task_name 
      end
    end
  end
end

但我认为这可能是你最好的:

def tasks_for_week(week, *task_names)
  task_names.find_all do |task_name|
    some_condition
  end
end

最后一个使用find_all迭代一个数组并返回一个新数组,该数组填充了该块返回true值的任何对象。

最后,您的条件逻辑也有点疯狂。您可以以动态方式将[]访问者用于活动记录字段。使用正面案例而不是unless something.nil?的双重否定通常更清晰。如果这是创建范围的常用方法,最好将其归结为方法:

def week_range_for_task(task)
  self["#{task_name}_week_min"]..self["#{task_name}_week_max"]
end

...

self[task_name] && week_range_for_task(task_name).include?(week)

制作整个方法:

def tasks_for_week(week, *task_names)
  task_names.find_all do |task_name|
    self[task_name] && week_range_for_task(task_name).include?(week)
  end
end

答案 1 :(得分:1)

有一点需要注意的是,self[task_name]似乎从数据库中获取原始数据,忽略了您可能编写的任何自定义getter方法。

如果您想使用自定义getter,或者您希望将任何方法视为属性,则可以使用self.send(task_name)代替self[task_name]

答案 2 :(得分:0)

这是稍微修改过的代码,其中包含一个新的条件方法。

  def whole_range_exists?(method_name)
        self["#{method_name}_week_min"] && self["#{method_name}_week_max"]
      end

      def week_range_for_task(task_name)
        self["#{task_name}_week_min"]..self["#{task_name}_week_max"]
      end

      def tasks_for_week(week, *task_names)
        task_names.find_all do |task_name|
          whole_range_exists?(task_name) && week_range_for_task(task_name).include?(week)
        end
      end