After having worked with MongoDB for a while, I really miss its dynamic features when dealing with “legacy” systems (MySQL, in this instance). How cool it would be to just start inserting data into random collection and it will magically appear in the DB? Good news is: it can be done.
There are some tradeoffs to be made, however. If we want completely flexible row-per-row structure, we have to serialize our data into JSON blobs (or whatever). This way we lose ability to efficiently query the data. Fortunately, in many cases there is a structure in data, so it can be represented as a MySQL schema.
In this concrete example we are storing event stream. For the ease of management we decided
to split the stream by source app id and date (in this app we don’t have to query across
several apps or days at the same time). So, our table names should follow this pattern,
where datestr
is a date formatted as yyyymmdd
1
|
|
So, how do we do it? We utilize API for schema manipulations, which is conveniently provided to us by ActiveRecord. We are interested in the create_table method.
1 2 3 4 5 6 7 8 |
|
Here’s how our method definition might look like:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
|
Note the clear_cache!
call. We need to invalidate ActiveRecord’s internal caches, or
otherwise it won’t know about our newly created table until app is restarted. Writing a
reverse method is pretty straightforward:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
And this is how you use the code:
1 2 3 4 5 |
|
That is, prefix every create
call with a use_table_for_app
call, so that current
table is properly set and created (if needed). I admit, this is still far from being
completely transparent, but this works for me at the moment. Feedback is welcome!
Happy coding!