Andy,
Some thoughts to keep this conversation going...
1) Migrations:
A couple of thoughts. First, you could just figure that if someone is
using your plugin and has set the "Archived" tables in their initial
migrations, then they are aware of what deleting columns would mean.
So you could go that route.
Another thought would be to offer some sort of warning... i.e. running
a migration that removes columns would give a warning... which could
be overridden by a flag or even some environment setting.
Another option, although very complex, would be to monkeypatch AR so
that deleting columns doesn't actually delete them but "hides" them.
But the more I think about that, the less I like it.
Ultimately, I'd just go with the first option. If you think about it,
the value here is storing record data beyond the "delete" point (I
like "archive" better). So if the "structure" of the data is changed,
that change should be allowed (in this case, removing columns as part
of a migration). It's the rows of data, if you will, that you want to
maintain. I think if the programmer knows enough to use your plugin
and define the extra tables, then they should be aware and willing to
accept that removing columns means removing them from the
"Deleted" (or "Archived") tables.
2) Archived vs. Deleted
Totally up to you. I like the idea "archived" more because it
syntactically describes what's happening better, IMO. I know, I
know... there is the idea of "undelete", but really... Deleting, to
me, means GONE. Archiving, though, means, "effectively gone... but
still _somewhere_ if I need it".
3) Archival Finds
I think it shouldn't be too hard to do this. I haven't done any
method_missing coding (yet), but the code I have seen looks fairly
straightforward. You might even do some plugin research and find some
others that do some custom Find calls and use that as a starting
point.
Another thought... maybe don't override the method name, but rather
add in a hash parameter... like:
Post.find_all_by_author("John Doe", :order =>
updated_at, :include_archive => true)
Or something like that. That might be easier as you don't need to do
any method_missing hacking... but just intercept that parameter and do
some table-joining.
4) File-based Archival
I could even imagine adding some hook whereby the archival takes
records from the DB and dumps them to some flat-file, or XML, or CSV
or some such format. This may not be necessary... but I can imagine
some possible use. I.e. where you "archive" (to the archive tables)
posts older than 3 months, but you "flat-file-archive" posts older
than 1 year. Just an idea, though... maybe it's not that useful.
As for me, I'll definitely be using this in at least one of my apps.
I've got one that's a very simple contact management and job posting
app. The jobs can be flagged as "filled". I'm thinking that it's the
perfect case to try this out... since I can make the "filled" jobs
just be the "archived" jobs. Then, the normal Job AR stuff only works
on active jobs unless the deleted (er... "filled") jobs are requested.
The biggest win of your approach over acts_as_paranoid is the speedup
in normal queries because the "deleted" data simply isn't in those
tables anymore. And most normal usage won't need the deleted data
anyway. So two big thumbs up on this work!
-Danimal