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.
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?
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.
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...)
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.
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...
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.
DHH himself provides a nice, succinct example gist here:
https://gist.github.com/1014971
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.
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.
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.
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
More information can be found here: http://m.onkey.org/2008/9/15/active-record-tips-and-tricks