如何重构这些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
答案 0 :(得分:4)
我认为你需要重新考虑一下你的设计。你有至少四个不同班级的小时费率,这有点乱。我知道你试图根据可以被更多本地化的类重写的关联来分配默认值,但是你正在做任何类的所有重写(几乎肯定不是应该负责它的类)。
取person
:如果一个人有特定的小时费率,那么,取得该费用,否则,获得该组织的每小时费率。此逻辑属于Person
类,在公共接口中有一个方法,允许您在一个步骤中查询,例如person.real_hourly_rate
。您可以使用project
执行相同的操作。
最后,如果您的类具有良好的,定义良好的api,您应该能够将此方法定义为:
def default_item_price(user)
project_hourly_rate || user.preference_hourly_rate
end
在这里,目的很清楚,这项工作是在需要的类中分配的,并且任何拿起代码的人都可以理解和理解该方法。
有一个名为delegate
的方便的rails方法可能会帮助你解决一些问题:
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
方法(也许这不是它的最佳名称)将为您提供小时费率(如果存在),如果不存在,则会询问相关人员的小时费率。
答案 1 :(得分: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
答案 2 :(得分: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