Where to define callbacks? Model vs model_oberver

Hi guys,

I am wondering where I should define my callbacks. I have a user model
and a few callbacks: before_save, after_save, etc.

I can define each callback in the model, but it is getting a bit messy
and overcrowded especially as I am using restful_auth. The other option
is to move the callbacks definitions in a user_observer. However
restful_auth which is supposed to be an example for good coding practice
defines before_save :encrypt_password inside the model.

So what to do?

1) Stuff callbacks inside the model, but the model can become a mess
2) Separate callbacks from model, this is a step beyond mvc, cleaner,
but it requires having to move back and forth between files and
remembering to register the callbacks.

How do you do that? What is today's commonly accepted best practice?

What about validations? For instance before_validation, shouldn't I also
move it to an observer?

Hi --

Hi guys,

I am wondering where I should define my callbacks. I have a user model
and a few callbacks: before_save, after_save, etc.

I can define each callback in the model, but it is getting a bit messy
and overcrowded especially as I am using restful_auth. The other option
is to move the callbacks definitions in a user_observer. However
restful_auth which is supposed to be an example for good coding practice
defines before_save :encrypt_password inside the model.

So what to do?

1) Stuff callbacks inside the model, but the model can become a mess
2) Separate callbacks from model, this is a step beyond mvc, cleaner,
but it requires having to move back and forth between files and
remembering to register the callbacks.

How do you do that? What is today's commonly accepted best practice?

What about validations? For instance before_validation, shouldn't I also
move it to an observer?

I've always felt that one of the nice things about AR model files is
that you can put a lot in them and they *don't* turn into a mess.
Long, maybe, but not messy. One thing you could do if you want to trim
the files is put some of the methods themselves in separate modules
and separate files, and then just have the callback declarations in
the model file itself.

David

Hi David,

I liked your book very much. Organizing code in modules is a better idea
than having to handle the observer file. I consider that callbacks calls
have to belong to the model, but their actual code could actually be in
another file, in order to be a bit more readable.

I'll follow your advice and use modules.

Best regards,

When I had this concern some months ago, the advice that I found was this: if the callback directly affects the model (e.g., hashing the user’s password), declare it in the model; if the callback uses the model to do something else (e.g., log the fact that the user was changed from active to inactive), declare it in an observer. This rule of thumb has worked very well for me.

I would rather see modules used to give a home to commonly used code instead of to house code for a model that seemed like it was becoming to large. If you have that sense about your model, consider the possibility that it simply does carry that much responsibility in its domain, or it’s carrying too much responsibility and the design of the domain should be reconsidered. Using modules to just move code around feels like the wrong approach to good domain design.

Regards,
Craig

I see what you mean Craig. I'll think about it, and figure out what I am
the most comfortable for me.

Hi --

When I had this concern some months ago, the advice that I found was this:
if the callback directly affects the model (e.g., hashing the user's
password), declare it in the model; if the callback uses the model to do
something else (e.g., log the fact that the user was changed from active to
inactive), declare it in an observer. This rule of thumb has worked very
well for me.

I would rather see modules used to give a home to commonly used code instead
of to house code for a model that seemed like it was becoming to large. If
you have that sense about your model, consider the possibility that it
simply does carry that much responsibility in its domain, or it's carrying
too much responsibility and the design of the domain should be reconsidered.
Using modules to just move code around feels like the wrong approach to good
domain design.

My preference is to leave stuff in the model file; as I said, I think
model files can usually handle growth very gracefully. I like your
observer rule of thumb. But I don't entirely agree with what you're
saying about modules. Modules are of course great for reusable code,
but if there's a bunch of functionality that seems like a good
candidate for a module, but only one class is going to use it, I don't
like to penalize that class for being the only user of the module by
refusing to create the module. I'd say the same thing about a partial
template, and most other modularizing tools.

Similarly, while I definitely don't advocate using modules just to
shorten a file (e.g., throw the last 50 lines in a module called
"ClutterFree"), I don't think modules are a danger sign, in terms of
design, if there's a rationale for what goes into the module. The
questions of whether the model aligns correctly with the domain and
whether the domain needs reworking can arise even in the case of very
short model files (like, two lines long :slight_smile: and on the other side I
can imagine a model loading modules that make perfect sense for what
it's doing. So I'd tend to decouple the well-designed-domain question
from the does-a-model-load-modules? question.

David