airblade/paper_trail — pull request #439 by bli (2014-11-03 04:04:58+00:00)
Title: supporting has_many reification based on @lyfeyaj and @NullVoxPopuli 's works

This is based on @lyfeyaj and @NullVoxPopuli 's works.
What I changed are mainly:
1. Reification for has_many through
2. Add tests and make sure all of them pass
3. Add option mark_for_destruction to mark the has_one/has_many associations that did not exist in the
reified version for destruction, instead of remove them.
4. Disable recursive reification of has_one/has_many associations. See the scenario below for more.
5. Some small tunings like using a hash to reduce the number of loop from n*m to n

### Some notes:

There is a limitation that the Reification will not work properly if the parent of a child can be changed.
Consider this scenario:
1. Create a customer A.
2. Create a customer B
3. Create an order for B.
3. Update A.
4. Change the customer of the order to A
5. Now reify the last version of A. Ideally we would expect no orders in the reified A.

Recursive reification is not supported. Take the customer, order, and line item model for example, when a customer is reified, the line item is not reified.
Consider this scenario:
1. Create a customer
2. Create an order for the customer with a line item
3. Update the customer
4. Update the line item
5. Now reify the last version of the customer. If we support recursive reification, we would expect to see the line item before the updates in step 4.

There is an assumption in the code that the version_id is always incremental. In reality, it could possibly reach the upper limit of Integer and become 1 again. Thus there is a very rare edge case wherein the reification would not work properly. This is due to selecting 'MIN(version_id)' in the SQL.