我试图让我的胖User
模型不那么笨重。我使用值对象来表示自定义值和对它们的操作,并且我坚持使用ActiveSupport::Concern
和模块。我将this作为灵感来阅读。
我把这样的辅助方法:
def is_a_wizard?
power_level >= WIZARD_POWER
end
def just_became_a_wizard?
power_level == WIZARD_POWER
end
进入模块,并将它们作为一种扩展包含在内。但是,它很难阅读和维护,我在视图和控制器中都需要它们中的一些(例如用于向导身份验证)。我应该把它们放在哪里?为他们使用的时间创建服务对象?
答案 0 :(得分:2)
您可以创建其他课程并在任何地方使用它:
# lib/wizard_detector.rb
class WizardDetector
def initialize(power_level)
@power_level = power_level
end
def is_a_wizard?
@power_level >= WIZARD_POWER
end
def just_became_a_wizard?
@power_level == WIZARD_POWER
end
end
# app/models/user.rb
class User
delegate :is_a_wizard?, :just_became_a_wizard?, to: :wizard_detector
def wizard_detector
@wizard_detector ||= WizardDetector.new(power_level)
end
end
# anywhere else
WizardDetector.new(power_level_to_check).is_a_wizard?
请注意,wizard_detector对象在模型中缓存,如果在请求流程中功率级别发生变化,则可能有害。可以替换缓存。
答案 1 :(得分:0)
正如我在评论中写的那样,模型中的业务逻辑方法是可以的。
但如果你觉得它太多了,你可以考虑像
这样的东西class User < AR::Base
def predicates
@predicates ||= ::User::Predicates.new(self)
end
end
并在/models/user/predicates.rb
class User
class Predicates < SimpleDelegator
def just_became_a_wizard?
power_level == User::WIZARD_POWER
end
end
end
然后你可以这样做:
user.predicates.just_became_a_wizard?
巨大的好处是您的用户模型不再使用大量方法。
缺点是每次都需要调用代理对象。
答案 2 :(得分:0)
我会重命名示例中的方法:
#is_a_wizard?会是#wizard吗? (这个将是红宝石的方式)
just_became_a_wizard? =&GT; new_wizard? (inexperienced_wizard?......这个不太明显)
计算机科学只有两件事:缓存失效和命名事物。
- Phil Karlton
答案 3 :(得分:0)
我最近开始越来越多地使用Concerns来保持模型清洁。我将为“Wizard”创建一个模块,在该命名空间下使用Concern模块为模型和控制器。虽然如果你有那么多与巫师有关的控制器方法,我个人会有点怀疑。对于观点,为什么不写标准助手呢?
当然,如果您有多个需要这些方法的模型,这更有意义,但它仍然可以帮助清理单个模型。我个人觉得很难维护,因为我几乎没有触及过这些小方法。您可能还会发现,除了方法定义之外,您还可以将其移动到关注点。
此外,您应该确保您的疑虑实际上是关注点,而不仅仅是您厌倦在模型中查看的方法的通用倾销场。