refactoring thick models? what approach do you use?

Hi,

What practice does Rails suggest for refactoring thick models? If
you split out methods from a model class where would you typically put
them? Which rails technique would you use to access them, such as (a)
mix-in's, (b) call them in their own separate class, e.g.
modelname_tools.method, or perhaps one of the (c) rails
meta-programming means of loading up extra methods (class methods or
instance methods) into a class.

For example I have a bank "transaction" model for which there are now
a few Class methods such as "self.auto_categorise", so I would assume
splitting these out into a separate file. So this case which file to
put them into, which directory to house it, and if the methods "added"
back into the model which approach to do this?

thanks in advance

A thick model is okay, depending on why its thick... there may be
another model(s) hiding in that code which could be factored out into a
new class or classes.

For common model methods, I started with a simple module that was
included by the classes making use of those methods.

As the number of those methods grew and became more pervasive in their
use, I introduced a "GenericModel" to sit between my model classes and
ActiveRecord::Base, the GenericModel class is where all the really
common functionality resides now (and specific classes can override if
necessary).

I did the same thing with my controllers as well, using the magic of
constantize which lets my GenericController class contain code like:

params[:controller].singularize.camelcase.constantize.paginate blah blah
blah

and

params[:controller].singularize.camelcase.constantize.new

to handle requests for almost all the actions of all my controllers,
giving me one place to put all my rescues and standard "where do I go
from here?" logic.

rough outline:

a lot of methods will most likely go into the helpers related to the
controller
(most of the things related to the views)
some go into the model (most things related to database activity)
application.rb for small things needed in several controllers

everything that doesn't fit in those wold get it's own lib in lib
folder

splitting the controller would be another way to thin it out,
rethink your RESTfull and CRUD design

DHH's keynote at railsconf europe outlined one possible way. Split out related bits of functionality into modules, eg your structure could be

person.rb
person/notifications.rb
person/something_else.rb.

and then Person includes those modules

Fred

Rick Olsen has a neat way of doing this: http://pastie.org/pastes/200292.

RSL

thanks

Russell/Fred - Your suggested way (or Rick Olsen's specifically) looks
good. I was wondering if there is any reason it could be more dynamic
however, like automatically include (or "require_dependency") for
every file it (the model) sees under it's own directly? i.e. then you
could place such discovery & include code inside ActiveRecord::Base
including some mechanism (not sure what it would be offhand) that
ensures that whenever a new active record class is loaded, the
equivalent of a "require_dependency" is in place for each file under
the model's directly.

BTW - Anyone know why I can't see "require_dependency" in the Rails
API or Ruby API?

I’m gonna have to say that as alluring and leet and fun as automagically loading things without being called can be, it’s a hell of a lot easier on fellow programmers when you explicitly call/load code. When some method loaded/created in a non-standard location starts breaking it can be a pain figuring out where. This isn’t the worst example of doing this but it’s a habit I’m reluctant to endorse. YMMV.

RSL

yeah, you're probably right - I'm just thinking of the pain trying to
read through rails plugins code where with all the metaprogramming
concepts you kind of have to be a brain surgeon to see how everything
really fits together..