ActiveRecord 4.2's Type Casting
Last month Rails 4.2 was released and if you have been keeping up with my posts, I even covered how you can upgrade from 3.2 to 4.2 in one step! This speaks volumes to how easy it is to adopt to outward facing API changes within our beloved framework. But often times, version changes bring implementation changes that we never see. For example, all of Aaron Patterson's work for AdequateRecord Pro™ are performance optimizations that affect no outward API interface at all. Unless you read the source, many of these awesome changes go unnoticed and that's a damn shame because some of them can make our lives easier.
Today I want to share some of the new hotness I found while working on the latest ActiveRecord SQL Server Adapter. Specifically, how ActiveRecord type casts values. Up until Rails 4.2, all type casting was done in class methods like implemented on the object. Sean Griffin does a great job explaining this convoluted process. Warning, it's kind of boring and a chore to read.
This process has been around for as long as I can remember. It made it really hard to write good abstract OO code that casts values going into and out of the database. All that has changed with the new namespace. All objects within this namespace are simple POROs with very obvious and well documented interfaces. The base class is and below is a slightly trimmed down version of that object, sans comments. Take a quick read.
Do you see what I see? This is amazing. I see an object that finally handles all of the following.
- Casting raw DB values.
- Casting user input to prepare for DB quoting.
- Casting for default values in schema dumpers.
- Avoid code bloat.
- So much more!
Case in point, a lot of database connection gems still return raw strings for every value. Sub classes of can define their own implementation to deal with this. For example, here is the object's default behavior. Super easy!
One thing that Rails core team did to make this even better allows us to type check our Ruby values ahead of time during attribute assignment vs. when we save to the database. This is now done in the class using the attribute parsed from the SQL type. Here are the salient points of that class.
Any type aliased to use the value object will now type check that the value is within the accepted database range. As far as I can tell, only Integer objects in Rails core do this, but I plan on implementing these checks for Decimal and other values too. Here is how SQL Server's SQL type attribute behaves.
There is so much more that we can do with these objects. The PostgreSQL adapter already casts the JSON data type. I can even see SQL Server returning a Nokogiri object for an XML data type. The sky is the limit. The core object allows the SQL Server Adapter to implement guards for different connection modes. Our connection returns all DB values mapped to their proper Ruby primitive. To avoid wasting precious time, we bypass all Rails type casting in one single place now.
These objects are a great step forward and they should open up all sorts of possibilities for gems to extend our DB objects. Thanks so much to Sean Griffin and anyone else working on ActiveRecord to make it better, faster, and easier to use!
Нет, больше. В этот момент кровать громко заскрипела: клиент Росио попытался переменить позу. Беккер повернулся к нему и заговорил на беглом немецком: - Noch etwas.