如何组织太胖的Rails模型?

时间:2022-07-22 20:37:26

It is good practice to shift logic from the controller into the model. But in any complex system, this invariably leads to a very large file even if a majority of the methods are one liners as per the Rails Way.

将逻辑从控制器转移到模型中是一种很好的做法。但是在任何复杂的系统中,即使大多数方法按照Rails方式是一个衬里,这也总是导致一个非常大的文件。

I've resorted to splitting up models into other modules and including them in the original model, for example, model_flags, model_validation, etc. Anyone has a better way?

我已经将模型拆分成其他模块并将它们包含在原始模型中,例如,model_flags,model_validation等。任何人都有更好的方法吗?

Edit: I've selected a new answer that suggested using ActiveConcern. Also, to anyone that is interested about organizing code, this article, Making ActiveRecord Models Thin, should help greatly.

编辑:我选择了一个建议使用ActiveConcern的新答案。此外,对于任何对组织代码感兴趣的人,本文“使ActiveRecord模型变薄”应该会有很大帮助。

6 个解决方案

#1


28  

I realize this is a fairly old question and it's been marked as answered, but it still has good Google juice, so I figured it was worth adding to...

我意识到这是一个相当古老的问题,并且已被标记为已回答,但它仍然具有良好的Google汁液,因此我认为值得添加...

Rails 3 introduced ActiveSupport::Concern, which can be used to modularize behavior that's shared across models. Or, for that matter, to slim down models that have become too fat.

Rails 3引入了ActiveSupport :: Concern,它可用于模块化模型之间共享的行为。或者,就此而言,减少变得太胖的模型。

DHH himself provides a nice, succinct example gist here:

DHH本人在这里提供了一个很好的,简洁的例子:

https://gist.github.com/1014971

https://gist.github.com/1014971

#2


6  

I wouldn't do this for a few reasons.

我不会出于某些原因这样做。

First you violate the assumption that things will be where they should be which is probably the biggest bonus to rails in the first place. A new person can walk onto your project and navigate it quite easily if you stick model stuff in your model. If you pull it out you just add a delay and some confusion particularly if the only logic for removing something to a module is to reduce the model size.

首先,你违背了这样的假设:事情应该是他们应该在哪里,这可能是最初对铁路的最大奖励。如果您在模型中粘贴模型,新人可以轻松地进入您的项目并轻松导航。如果你把它拔出来,你只需添加一个延迟和一些混乱,特别是如果删除某个模块的东西的唯一逻辑是减少模型大小。

Second you gain almost nothing from it and you lose something. File size doesn't matter these days when almost all editors and IDEs ease the navigation pain of large files. Moving stuff to a module actually takes some of this modern ease away and will require you and your colleagues or future maintainers to jump around several more files while working on one model.

其次,你几乎从中获得任何东西而你却失去了一些东西如今几乎所有编辑器和IDE都能减轻大文件的导航难度,文件大小并不重要。将内容移动到模块实际上需要一些现代的易用性,并且需要您和您的同事或未来的维护者在处理一个模型时跳过几个文件。

That said I suspect what the hardcore rails best practice posse will tell you is that if your model is that large and complex then your design is flawed and your model is probably representing several things that could be made into separate models rather than modules.

这就是说我怀疑拥有的最佳实践团队会告诉你的是,如果你的模型那么庞大而复杂,那么你的设计就会有缺陷,你的模型可能代表了几个可以分成模型而不是模块的东西。

#3


4  

Well, I wouldn't say that any of you are wrong to put everything in one model, but I think it is also quite valid to be able to separate various concerns. It is a trade off in the very least.

好吧,我不会说你把任何东西放在一个模型中是错的,但我认为能够分开各种各样的问题也是非常有效的。这至少是一种折衷。

And I'm posting an answer to my own question, as I have found the Rails Way to do just that: http://github.com/jakehow/concerned_with

而且我正在发布我自己的问题的答案,因为我已经找到了Rails方法来做到这一点:http://github.com/jakehow/concerned_with

More information can be found here: http://m.onkey.org/2008/9/15/active-record-tips-and-tricks

更多信息可以在这里找到:http://m.onkey.org/2008/9/15/active-record-tips-and-tricks

#4


2  

Having no knowledge of your object model, it's a bit harder to advise, but I'd say that if you're absolutely convinced that all of the validations/associations/callbacks need to be in that place, there are still ways of factoring out common behaviors. So while I wouldn't just move a big chunk of code out of one file and into another, where it just re-opens the class, I would say that using modules/plugins to describe common types of behaviors is a good idea.

不了解你的对象模型,建议有点困难,但我会说,如果你绝对相信所有的验证/关联/回调都需要在那个地方,那么仍有一些因素可以解决共同的行为。因此,虽然我不会只将一大块代码从一个文件移到另一个文件中,而只是重新打开类,我会说使用模块/插件来描述常见的行为类型是一个好主意。

For example, if you're building a Facebook-esque activity feed, and everything needs to generate "events", then maybe you'd want to move that "Eventable" behavior into a module, which when included, defines the associations/validations/etc. I'd say that approach would actually enhance the clarity of your code, since manually specifying those associations everywhere isn't nearly as expressive as declaring something as Eventable, nor is it as safe (you'd be duplicating logic in a bunch of places, and when the logic changes, you know the rest...)

例如,如果您正在构建一个Facebook-esque活动源,并且所有内容都需要生成“事件”,那么您可能希望将该“可事件”行为移动到一个模块中,该模块在包含时定义了关联/验证/等等。我会说这种方法实际上会增强代码的清晰度,因为在任何地方手动指定这些关联并不像宣布像Eventable那样具有表现力,也不是那么安全(你在一堆地方复制逻辑) ,当逻辑改变时,你知道其余的......)

All in all though, I'd say take a big look at your object model. In your test suite, if you notice that all of your tests require a lot of setup, that can be a good indicator that you're missing something in your object model. Again though, some sample code would be great.

总而言之,我会说看看你的对象模型。在您的测试套件中,如果您注意到所有测试都需要进行大量设置,那么这可能是您在对象模型中遗漏某些内容的良好指标。尽管如此,一些示例代码会很棒。

#5


2  

#6


0  

Modules sounds sensible. I wouldn't extract the method calls (validations, callbacks, plugins etc) into modules, though, I'd limit the extraction to my own methods.

模块听起来很合理。我不会将方法调用(验证,回调,插件等)提取到模块中,但是,我将提取限制为我自己的方法。

And as always, it would help if you posted some sample code. I find it hard to imagine a generic strategy to clean up models, it depends on the nature of the code.

和往常一样,如果你发布一些示例代码会有所帮助。我发现很难想象清理模型的通用策略,这取决于代码的性质。

#1


28  

I realize this is a fairly old question and it's been marked as answered, but it still has good Google juice, so I figured it was worth adding to...

我意识到这是一个相当古老的问题,并且已被标记为已回答,但它仍然具有良好的Google汁液,因此我认为值得添加...

Rails 3 introduced ActiveSupport::Concern, which can be used to modularize behavior that's shared across models. Or, for that matter, to slim down models that have become too fat.

Rails 3引入了ActiveSupport :: Concern,它可用于模块化模型之间共享的行为。或者,就此而言,减少变得太胖的模型。

DHH himself provides a nice, succinct example gist here:

DHH本人在这里提供了一个很好的,简洁的例子:

https://gist.github.com/1014971

https://gist.github.com/1014971

#2


6  

I wouldn't do this for a few reasons.

我不会出于某些原因这样做。

First you violate the assumption that things will be where they should be which is probably the biggest bonus to rails in the first place. A new person can walk onto your project and navigate it quite easily if you stick model stuff in your model. If you pull it out you just add a delay and some confusion particularly if the only logic for removing something to a module is to reduce the model size.

首先,你违背了这样的假设:事情应该是他们应该在哪里,这可能是最初对铁路的最大奖励。如果您在模型中粘贴模型,新人可以轻松地进入您的项目并轻松导航。如果你把它拔出来,你只需添加一个延迟和一些混乱,特别是如果删除某个模块的东西的唯一逻辑是减少模型大小。

Second you gain almost nothing from it and you lose something. File size doesn't matter these days when almost all editors and IDEs ease the navigation pain of large files. Moving stuff to a module actually takes some of this modern ease away and will require you and your colleagues or future maintainers to jump around several more files while working on one model.

其次,你几乎从中获得任何东西而你却失去了一些东西如今几乎所有编辑器和IDE都能减轻大文件的导航难度,文件大小并不重要。将内容移动到模块实际上需要一些现代的易用性,并且需要您和您的同事或未来的维护者在处理一个模型时跳过几个文件。

That said I suspect what the hardcore rails best practice posse will tell you is that if your model is that large and complex then your design is flawed and your model is probably representing several things that could be made into separate models rather than modules.

这就是说我怀疑拥有的最佳实践团队会告诉你的是,如果你的模型那么庞大而复杂,那么你的设计就会有缺陷,你的模型可能代表了几个可以分成模型而不是模块的东西。

#3


4  

Well, I wouldn't say that any of you are wrong to put everything in one model, but I think it is also quite valid to be able to separate various concerns. It is a trade off in the very least.

好吧,我不会说你把任何东西放在一个模型中是错的,但我认为能够分开各种各样的问题也是非常有效的。这至少是一种折衷。

And I'm posting an answer to my own question, as I have found the Rails Way to do just that: http://github.com/jakehow/concerned_with

而且我正在发布我自己的问题的答案,因为我已经找到了Rails方法来做到这一点:http://github.com/jakehow/concerned_with

More information can be found here: http://m.onkey.org/2008/9/15/active-record-tips-and-tricks

更多信息可以在这里找到:http://m.onkey.org/2008/9/15/active-record-tips-and-tricks

#4


2  

Having no knowledge of your object model, it's a bit harder to advise, but I'd say that if you're absolutely convinced that all of the validations/associations/callbacks need to be in that place, there are still ways of factoring out common behaviors. So while I wouldn't just move a big chunk of code out of one file and into another, where it just re-opens the class, I would say that using modules/plugins to describe common types of behaviors is a good idea.

不了解你的对象模型,建议有点困难,但我会说,如果你绝对相信所有的验证/关联/回调都需要在那个地方,那么仍有一些因素可以解决共同的行为。因此,虽然我不会只将一大块代码从一个文件移到另一个文件中,而只是重新打开类,我会说使用模块/插件来描述常见的行为类型是一个好主意。

For example, if you're building a Facebook-esque activity feed, and everything needs to generate "events", then maybe you'd want to move that "Eventable" behavior into a module, which when included, defines the associations/validations/etc. I'd say that approach would actually enhance the clarity of your code, since manually specifying those associations everywhere isn't nearly as expressive as declaring something as Eventable, nor is it as safe (you'd be duplicating logic in a bunch of places, and when the logic changes, you know the rest...)

例如,如果您正在构建一个Facebook-esque活动源,并且所有内容都需要生成“事件”,那么您可能希望将该“可事件”行为移动到一个模块中,该模块在包含时定义了关联/验证/等等。我会说这种方法实际上会增强代码的清晰度,因为在任何地方手动指定这些关联并不像宣布像Eventable那样具有表现力,也不是那么安全(你在一堆地方复制逻辑) ,当逻辑改变时,你知道其余的......)

All in all though, I'd say take a big look at your object model. In your test suite, if you notice that all of your tests require a lot of setup, that can be a good indicator that you're missing something in your object model. Again though, some sample code would be great.

总而言之,我会说看看你的对象模型。在您的测试套件中,如果您注意到所有测试都需要进行大量设置,那么这可能是您在对象模型中遗漏某些内容的良好指标。尽管如此,一些示例代码会很棒。

#5


2  

#6


0  

Modules sounds sensible. I wouldn't extract the method calls (validations, callbacks, plugins etc) into modules, though, I'd limit the extraction to my own methods.

模块听起来很合理。我不会将方法调用(验证,回调,插件等)提取到模块中,但是,我将提取限制为我自己的方法。

And as always, it would help if you posted some sample code. I find it hard to imagine a generic strategy to clean up models, it depends on the nature of the code.

和往常一样,如果你发布一些示例代码会有所帮助。我发现很难想象清理模型的通用策略,这取决于代码的性质。