在Rails中inheritance用户模型真的很糟糕吗?

我从Rails得到了很多回击,因为我将User子类化为许多不同的子类。 在我的应用程序中,并非所有用户都是平等的 实际上有很多模型对象,并不是每个用户类型都可以访问它们。

我还需要一种方法来做多态行为。 例如,根据类型,许多方法的行为会有所不同。 这不是多态性的意思吗?

但事实是,我总是从Rails中退出。 默认值 – 特别是表单提交给参数哈希的方式 – 似乎像非子类模型一样工作。 链接和参数哈希只是默认设置真正咬你的两种方式。

在Rails中为不同类型的用户处理复杂逻辑的“正确”方法是什么? 在Java中,子类化模型可以工作 – 您不必通过箍来使其按照您希望的方式工作。 但是在Rails中,很难让子类使用REST约定,当你忘记包含:as => :user时它会惩罚你,或者当你在链接中放入子类对象时会惩罚你,例如edit_user_path(@user) < – 坏主意!

还有一个区域也很难处理。 假设我有一个Company模型,它有很多Users 。 这些用户可以是导演,教师,学员等 – 所有不同的子类。

当我们创建帐户时,我们可能希望使用accepts_nested_attributes_for :users 。 但是,如果我们使用它,我们就不能指定它创建的类。 血淋淋的地狱!

似乎Rails中的所有内容都不希望您将模型子类化。 如果你没有子类,一切都“正常”。 但如果你是子类,那你就是为了地狱。

解决办法是什么?

一般来说,Ruby中不鼓励inheritance,而是支持mixin行为和委托。 Ruby和Rails可以做到这一点,但它往往导致你提到的推回

您的特定示例听起来像是委托的情况:拥有属于员工的User类(反之亦然)。 该员工的类型特定行为(例如,董事,讲师等)都在该特定员工类中。 然后,用户将委派如何处理与其加入的员工的特定方案

这是我弄明白的一个技巧。 不要假设它是预期的行为:

 class UserSubclass < User def self.model_name User.model_name end end 

基本上所有模型(派生自ActiveModel)默认情况下都基于具体的类名来标识自己。 这是通过类方法#model_name (它返回一个ActiveModel::Name的实例,其中self作为参数。覆盖它以返回一个特定的类将Rails放在正确的轨道上。这样你就可以将这个逻辑保留在你的模型中了你的模板。

它基本上是“说出你的意思”,

如果您指的是通用用户表单或专门的员工用户表单,那么框架无法知道何时说redirect_to @user

这会导致很多redirect_to @user.becomes(User)你可以自由地redirect_to @user.becomes(User)

 def to_base_class becomes User end alias_method :to_b, :to_base_class 

如果您打算重定向到User而不是Employee资源,请写入redirect_to @user.to_b

基本上,像redirect_to @user这样优雅的语法表示模型和视图/控制器之间非常深的耦合,当你制作模型和视图/控制器逻辑时,由于这种耦合而产生的更复杂的裂缝将开始显示,并且域分离中的一些额外工作将需要制作或需要编写更多代码。

Rails并没有因为使用OOP而惩罚你,你正在经历模型< - > view < - >控制器关系的复杂性增加:

曾几何时你的模型是你的视图,反之亦然,现在你有两个模型类映射到两个视图类,如果你想为另一个模型使用一个视图,你将不得不说它