0

如何重构这段 Ruby 代码以使其不那么难看:

def default_item_price(user)
  if project.present?
    if project.hourly_rate?
      project.hourly_rate
    elsif project.person.hourly_rate?
      project.person.hourly_rate
    elsif project.person.organisation && project.person.organisation.hourly_rate?
      project.person.organisation.hourly_rate
    else
      user.preference.hourly_rate     
    end
  else
    user.preference.hourly_rate
  end
end

我没有做过很多 Ruby 编程,我想知道最后 6 行是否可以以某种方式干掉。谢谢你的帮助!

这些是我的模型:

class User
  has_many :people
end

class Person
  belongs_to :user
  has_many :projects

  def real_hourly_rate
    hourly_rate || organisation.real_hourly_rate
  end    
end

class Project
  belongs_to :person
  has_many :invoices

  def real_hourly_rate
    hourly_rate || person.real_hourly_rate
  end
end

class Invoice
  belongs_to :project

  def default_item_price(user)
    project.real_hourly_rate || user.preference.hourly_rate    
  end
end
4

3 回答 3

4

我认为你需要重新考虑你的设计。你有至少四个不同课程的小时费率,这有点混乱。我了解您正在尝试根据可以被更本地化的关联覆盖的关联分配默认值,但是您正在执行所有覆盖的任何类(几乎肯定不是应该负责的类)。

采取person:如果一个人有特定的小时费率,则获取该值,否则,获取该人所在组织的小时费率。这个逻辑属于Person类,在公共接口中有一个方法,可以让你一步来查询这个,比如说person.real_hourly_rate。你可以用project.

最终,如果你的类有很好的、定义明确的 api,你应该能够将这个方法定义为:

def default_item_price(user)
  project_hourly_rate || user.preference_hourly_rate
end

在这里,意图很明确,繁重的工作分布在它需要的类中,并且任何拿起你的代码的人都可以阅读和理解该方法。

有一个方便的 rails 方法delegate可以帮助您解决其中的一些问题:

class Project
  delegate :hourly_rate, to: :person, prefix: true, allow_nil: true

  def real_hourly_rate
    hourly_rate || person_hourly_rate
  end

real_hourly_rate方法(也许这不是它的最佳名称)如果存在,将给您每小时费率,如果不存在,它将询问相关人员的每小时费率。

于 2013-02-28T17:56:31.667 回答
1

我同意扎克的观点。无论如何,这是一个烘干机重写!

def hourly_rate_from anything
  anything.hourly_rate? ? anything.hourly_rate : nil
end

def default_item_price user
  if project.present?
    rate = hourly_rate_from project
    rate ||= hourly_rate_from project.person
    if project.person.organisation
      rate ||= hourly_rate_from( project.person.organisation ) 
    end
    return rate if rate
  end
  hourly_rate_from user.preference
end
于 2013-02-28T17:59:45.367 回答
0

与 Java 等人不同,在 Ruby 中&&||返回他们的一个或另一个参数。这可用于使具有一系列空值检查的代码非常简洁:

def default_item_price(user)
  if project.present?
    project.hourly_rate ||
    project.person.hourly_rate ||
    (project.person.organisation && project.person.organisation.hourly_rate) ||
    user.preference.hourly_rate
  else
    user.preference.hourly_rate
  end
end
于 2013-02-28T18:46:44.520 回答