0

如何Ruby代码此位被重构,以使其不太难看:如何干掉其他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号线可以在某种程度上DRYed起来。谢谢你的帮助!

这是我的模型:

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

对于重构问题,您应该使用http://codereview.stackexchange.com。 – 2013-02-28 19:08:25

回答

4

我认为你需要重新考虑你的设计了一下。你至少有四个不同的课程每小时费率,这有点乱。我知道你试图根据可以被更多本地化的关联覆盖的关联来分配默认值,但是你在做任何类的重写(几乎肯定不是应该对它负责的类)。

person:如果某人具有特定的小时费率,则获得该小时费率,否则获取该小组的小时费率。该逻辑属于Person类,在公共接口中提供了一种方法,允许您在一个步骤中查询该内容,如person.real_hourly_rate。你可以用project做同样的事情。

最后,如果你的类有很好的,定义良好的API,你应该能够确定这种方法是这样的:

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

这里,意图很明显,在繁重的工作中的分布它需要的类,并且该方法对于任何获取代码的人都是可读的和可理解的。

有一个称为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方法(也许这并不是它最好的名字),如果存在的话会给你每小时收费如果没有,它会询问相关人员的小时费率。

+0

谢谢扎克!你说的话对我来说是完全合理的,我一直在努力实现它。但是,由于某种原因,我无法让它工作。我上面更新了我的模式,所以你可以看到我的'default_item_price'方法应该去哪儿。我仍然不明白为什么当我的模型中已经有一个'delegate'语句时需要'real_hourly_rate'方法。 – Tintin81 2013-02-28 18:47:20

+0

废料,我真的得到它的工作。我上面发布了我的代码。我只是感到困惑,因为我没有使用你建议的'delegate'方法。 – Tintin81 2013-02-28 19:10:22

+0

太棒了,看起来好多了。 – 2013-02-28 19:17:52

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 
+0

感谢您的帮助! – Tintin81 2013-02-28 20:24:48

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 
+0

感谢您的帮助! – Tintin81 2013-02-28 20:24:24