serialization and attribute assignment share commonality, so full decoupling is not DRY?

In Rails 4, strong_parameters allows the controller to filter out what is accessible so that you have to make a conscious choice about what parameters to allow to be updated.

And serialization options were too hash-y, then projects like RABL came about to try to avoid having to define as_json or having specific JSON, etc. view that was a little nasty looking and not very easy, so then ActiveModel::Serializer was written to let you define what equates an abstract view by defining something that looks a lot like a model class.

However, as things get more Javascript-framework-based on the UI side, JSON APIs (at least) seem like something that should just work with a minimal amount of code on the Rails side, so why not define serialization and attribute (and association) assignment in the same place?

In other words, for one or more uses of a model or collection of models you’d have some way of defining what attributes and associations are both serialized and accepted for writes, which were serialize-only, and which were writable.

The goal also would be to hopefully not have to define yet another class or template to designate this definition if not desired (but I guess you could if you wanted), but at the least to be able to have a single place to define both of these if you want, so you aren’t having to enter the same attribute name in both strong_parameters and in the serializer.

Locally, we are starting to use AngularJS for client-side development served by Rails 3.2.x because we didn’t want something that was purely just for services, even if for Angular most of what is required other than auth, etc. is just a number of JSON services. (Nothing against Ember- we also think it looks great, as do a number of other existing and up-and-coming solutions for client-side.) So, we have a project that was kind of born out of a spike (hence it having been previously unstable, non-working, and the only test file in it is beyond irrelevant at this point) to just attempt to provide something that helps us more quickly integrate with the models I originally generated using a script I wrote from a legacy DB that has a moderately complex schema. The project is here:

Anyway, the point of sharing that is to show that even though it is pretty nasty right now, with something that allows you to use a combination of mass assignment security and serialization in a short amount of code can get the job done, and I feel like the direction things are headed in will end up with everyone writing even more code, when they will likely rather be spending that time writing Javascript. At least I hear that’s what is the cool kids are doing these days… :slight_smile:

Thanks in advance for any advice and thoughts on this.

Hi Gary,

thanks for that post, I agree that accessible and (de-)serialization configuration should be done in one place. Have a look at Roar[1], here, representer modules define the document’s structure. When deserializing, only those defined properties are considered, making it pointless to define writeable attributes/mass-assignment and the like.



Thanks, Nick!

Roar is really nice! Having a representer, something that is like a serializer but also defines what can be updated/assigned, is really nice. Since the model still defines what is writeable via mass assignment security (attr_accessible, etc.), even if you have different representers for different services or views, some stuff still must be defined in the model- although maybe you’d turn whitelisting off (in A.R./Rails 3.2.4+) and just attr_protected :id, :created_by, :updated_by and have the representer manage what is read and written outside of the timestamp, maybe userstamp (created_by, updated_by), any custom timestamps/passwords, etc.? Is there a way in Roar to define some things as read and write and other things as write only and read-only? Roar-rails looked cool, too!

The way I handled keeping accessible and deserialization in the same place in restful_json was to reuse mass assignment security (attr_accessible and the like) for what is readable and writeable about a model and then use a new as_json_includes/as_json_excludes as an additional way to show/limit the JSON that is returned to the client, then use subclasses/module includes, etc. (normal Ruby-ish stuff helped by Rails’ class_attribute’s) to handle different views. That way at the very least you could say that just by changing the class_name option on the association (belongs_to, has_one, has_many, habtm, etc.), you can have it provide DRY reader/writer assignment when you get/write one model vs. another.

Would like to keep things together, DRY and easily understandable when needs are simple, but be able to quickly branch out and create new views and security just as simply and easily. Would like something that works regardless of whether we are focused on providing JSON services for Javascript frameworks (that vary slightly in how they would best like to read and write JSON) or whether we need to use the same security/views for HTML rendered stuff (ActiveAdmin, etc.). Having to work with two MVC frameworks (both Angular and Rails) is fun enough :slight_smile: without having to start making even more files and classes appear to define what needs to be written and what is allowed to be received and persisted, but having additional classes when needed for additional views isn’t terrible as long as it can either slightly add/remove what is read or written or fully redefine that in parts. That is what I was aiming for, but restful_json is still pretty dirty at the moment.

(P.S.- sorry for throwing two “nices” in that last comment. I didn’t notice I had repeated that until I posted. Nice nice! :slight_smile: )

My goal is to understand whether there is a planned way not have to write the attribute name in both strong_parameters and in the (de)serializer.

The idea of the representer in Roar seems like it is a lot closer to making both providing JSON representations and updating data via incoming JSON easier.

I respect the clean way that params are handled in strong_parameters and trying to OO-ify (de)serialization in ActiveModel::Serializer, but I think that it would help if someone actually tried writing a Rails app to serve up both an AngularJS and an Ember app and then focus on how that segment of the population is being served by what exists currently in Rails 4.

I know that people complained when there were big changes in Rails 3, but since Node, etc. are getting so hot now, could that be a sign that bigger changes need to happen to make it more friendly for those use cases?

Gary- I absolutely agree with you that the document knowledge is spread over the entire framework in the current Rails: ParamsParser, active_serializer and strong_parameters all know about properties, structures and semantics of incoming/outgoing documents. And even worse: They might have different states creating redundancy. Representers as found in Roar embrace all that in an object-oriented module. Use the gem but don’t expect anything like that in the core too soon.