During my Flatiron School final project I came into an issue with serializers. Moreover, the Rails serializer didn't want to access information that was more than 1 level deep. Because I was chaining information and this caused an issue and made it difficult to work with without keeping all of my information in the same table (something I didn't want to do).
With a lot of help from two coaches and a days worth of research and breaking it all at least 3 times, I was able to get it to work but when I asked about any documentation that might explain the Rails serializer better "nope, it's no longer maintained as everyone is moving to Fast JSON." was all I got ... Great. Just my luck. I use something that is no longer maintained.
But this got me wondering... what is a serializer in general/ why am I using it/ what is this 'Fast JSON'?
"Serialization refers to a process of converting an object into a format which can be persisted to disk (for example saved to a file or a datastore), sent through streams (for example stdout), or sent over a network. The format in which an object is serialized into, can either be binary or structured text (for example XML, JSON YAML…). JSON and XML are two of the most commonly used serialization formats within web applications." (5)
Ruby on Rails uses and "ActiveModel::Serializers" that "encapsulates the JSON serialization of objects... In short, serializers replace hash-driven development with object-oriented development." (1)
My Nested Mess Fix
WOW! What an interesting way to nest associated data without building out one big table of information. With serialization I was able to have each model separated out in different tables and use a Serializer for each model to associate them. All of my models had references to things that they belonged to but with the rails serializer it couldn't seem to see more than 1 level deep.
My original fix a "teacher" had set up was this junky hash of my data:
It did the trick to show my data but it was all in the wrong order. I would have to have had so many levels of enumeration to see what was included with what and whose data was whoms that it was not usable. It was gross and killed my project for about 30 minutes before I gave up and reset to a working state. I only lost about two hours total on it luckily.
Then, my coach found out that the issue here was that I was trying to serialize a collection (active relation) of data as if it were a single resource. For collections, you need to specify "each_serializer:" instead of just "serializer:". This took a lot of searching for by both me and them and though it's confusing... serializer: refers to the "collection serializer" and I needed access to each_searalizer: in the collection. Eh... it makes sense and it allowed me to associate my data in a pretty nested hash.
So what is this Fast JSON and how does it make serialization easier?
Fast JSON is a "a lightning fast JSON:API serializer for Ruby Objects." (4) It's faster because it has support for belongs_to, has_many and has_one, support for compound documents, is optimized serialization of compound documents, and has caching. By supporting the belongs_to and has_many it is able to see the collection better and use a "is_collection" tag to specify that a collection exists and next them accordingly with their associated relations.
How do you set up a serializer then?
Make sure that you have a gem for the serializer of choice. Because at the time I was going to the Flatiron Schools program I did their walk through and used the 'gem "active_model_serializers", "~> 0.10.7"'.
Don't forget to generate a serializer file for each table you want associated with something. I did this for all 4 of my tables. You need to do separate generations for each serializer with "rails g serializer ". Mine were users, accounts, logins, password because there are many users, each user can have many account groups, each group can have many login credentials, but each log in credential can only have 1 password associated with it.
Go into each serializer file and associate them. Start at the top and work your way down. For me this means that User where I had to set up the attributes :username, :email and the "has_many :accounts, serializer: AccountsSerializer"
Now make sure that each Controller that needs to view data has the serializer it needs to use.
Each one of these represent one of the controllers that I had and where I needed to use a serializer to see its associated data.
Tricky Points
Because for my project each user had a list of Account Groups and each Account Grouping could have multiple credentials associated with it, I needed to word things just right to get them to see that each account has a serializer for each credential. Woof. Not Easy and this is where it took so long. But, once it was done my data showed through perfectly and made it very easy to see what data was associated to each user and which account group it had associations with.
NOTE:: NONE of my tables had ANY has_many associations. Every table belongs_to another so it is a one way relationship. I am not sure how serializers might change if there is a has_many relationship.
References
- https://github.com/rails-api/active_model_serializers/tree/v0.9.3
- https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/serialization/
- https://github.com/rails-api/active_model_serializers/issues/1788
- https://github.com/Netflix/fast_jsonapi#serializer-definition
- https://www.acunetix.com/blog/articles/what-is-insecure-deserialization/
Top comments (0)