【发布时间】:2015-11-12 16:23:59
【问题描述】:
我知道这样做是一种轻微的反模式,但有时它只是一个比实现不同的逻辑类或全功能的装饰器/表单对象更容易的解决方案,只是一点点差异。
假设我有一个用户类 (ActiveModel),并且我想在多个不同的上下文中使用它,比如注册和登录。 对于注册,我希望能够有与登录不同的翻译,例如能够为无效的电子邮件格式提供不同的消息。
有没有简单的方法来完成这个?同时能够在同一类对象上工作。因此,SignUp 和 Login 都应该在 FULL User 类上运行,允许使用其中提供的逻辑。
理想情况下,只需获取实例并在实例上设置变量以更改 i18n-tree 的“model_name”部分。
我尝试了几种方法:
代表团
class Login < DelegateClass(User)
end
非常适合在实例级别简单地覆盖/添加逻辑。不幸的是,所有 Rails i18n 的东西都在类级别上运行,没有办法进入,因为 self 反映的是用户而不是登录,也没有真正的登录类来附加逻辑。
装饰
这将是完美世界中的理想解决方案,例如使用表单对象(改革等),但它不可能使用用户逻辑(例如验证)而不费力,复制甚至重新实现它们复杂的案例(例如检查电子邮件的唯一性等)。只是简单的翻译文本更改的开销太大。 另外,这通常带有全套自己的翻译等,除非真的需要,否则我不想复制所有这些 - 也许只需更改一些默认的。
继承
仅对于初始情况(允许更改翻译以进行验证)完美:
class LoginController < ApplicationController
...
class User < ::User
end
end
这个小魔法在 I18n 回退的前面增加了另一层,所以突然在树中的“用户”之前查找了一个“登录控制器/用户”。 不幸的是,您对具有不同类的对象进行了任何其他操作,因此在执行此操作时必须非常小心,这会产生一些意想不到的副作用。
有没有更好的解决方案?正如我所说,我知道最完美的做法是甚至不直接对 ActiveModel 对象进行操作,但有时引入业务逻辑对象来处理所有事情是完全矫枉过正的 - 并一次又一次地重复大量逻辑。
【问题讨论】:
标签: ruby-on-rails ruby rails-i18n