Add embedded associations in ActiveModel#43399
Add embedded associations in ActiveModel#43399mansakondo wants to merge 1 commit intorails:mainrails/rails:mainfrom mansakondo:embedded-associationsmansakondo/rails:embedded-associationsCopy head branch name to clipboard
Conversation
a798d8a to
1ae629e
Compare
There was a problem hiding this comment.
Design
ActiveModel::Type::Document
A polymorphic cast type (registered as :document). Maps JSON objects to POROs that includes ActiveModel::Embedding::Document. Provides support for defining collections
ActiveModel::Embedding::Associations
API for defining embedded associations. Uses the Attributes API with the :document type.
ActiveModel::Embedding::Document
A mixin which includes everything needed to work with the :document type (ActiveModel::Model, ActiveModel::Attributes, ActiveModel::Serializers::JSON, ActiveModel::Embedding::Associations). Provides an id attribute and implements methods like #persisted? and #save to emulate persistence.
ActiveModel::Embedding::Collecting
A mixin which provides capabailities similar to ActiveRecord collection proxies. Provides support for nested attributes.
ActiveModel::Embedding::Collection
Default collection class. Includes ActiveModel::Embedding::Collecting.
Fix typo Handle case when `value` is already type casted Rename `#find` to `#find_by_id`
1ae629e to
b480a5b
Compare
|
Thank you so much for the pull request and all the work you put on this. I have someone in my team working in the same idea, but with a very different API and implementation, so it is very likely that I'll not merge this PR. I'll keep it open though, in case our implementation end up not working as we like. I'll update this PR with more information. Thank you again. |
|
Ok thanks for the reply. |
|
I think there are more feature here than what I was planning to implement like embedding in JSON columns. As we have the API we want I'll probaly ask here if you are interested in porting this implementation to use the new API. |
|
Yeah sure with pleasure. |
|
This pull request has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. |
|
Hi @rafaelfranca. Since this PR was closed, I wanted to know if you and your team are still working on a way to model semi-structured data in Rails ? |
|
Ok thanks for letting me know. |
Relational databases are very powerful. Their power comes from their ability to...
But sometimes, we can stumble accross data that don't fit in the relational model. We call this kind of data: semi-structured data. When this happens, the things that makes relational databases powerful are the things that gets in our way, and complicate our model instead of simplifying it.
That's why document databases exist, to model and store semi structured data. However, if we choose to use a document database, we'll loose all the power of using a relational database.
Luckily for us, relational databases like Postgres and MySQL now has good JSON support. So most of us won't need to use a document database like MongoDB, as it would be overkill. Most of the time, we only need to denormalize some parts of our model. So it makes more sense to use simple JSON columns for those, instead of going all-in, and dump your beloved relational database for MongoDB.
Currently in Rails, we can have full control over how our JSON data is stored and retrieved from the database, by using the Attributes API to serialize and deserialize our data.
That's what this extension does, in order to provide a convenient way to model semi-structured data in a Rails application.
Usage
Let's say that we need to store books in our database. We might want to "embed" data such as parts, chapters and sections without creating additional tables. By doing so, we can retrieve all the embedded data of a book in a single read operation, instead of performing expensive multi-table joins.
We can then model our data this way:
And display it like this (with nested attributes support out-of-the-box):
Validations
Custom collections
Custom types
Associations
embeds_many
Maps a JSON array to a collection.
Options:
:class_name: Specify the class of the documents in the collection. Inferred by default.:collection: Specify a custom collection class which includesActiveModel:: Embedding::Collecting(ActiveModel::Embedding::Collectionby default).:cast_type: Specify a custom type that should be used to cast the documents in the collection. (the:class_nameis ignored if this option is present.)embed_one
Maps a JSON object to a document.
Options:
:class_name: Same as above.:cast_type: Same as above.Embedded associations should only be used if you're sure that the data you want to embed is encapsulated. Which means, that embedded associations should only be accessed through the parent, and not from the outside. Thus, this should only be used if performing joins isn't a viable option.
Read this section from the original README (and this article) for more insights on the use cases of this feature.
Concepts
Document
A JSON object mapped to a PORO which includes
ActiveModel::Embedding::Document. Usually part of a collection.Collection
A JSON array mapped to an
ActiveModel::Embedding::Collection(or any class that includesActiveModel::Embedding::Collecting). Stores collections of documents.Embedded associations
Models structural hierarchies in semi-structured data, by "embedding" the content of children directly in the parent, instead of using references like foreign keys. See Embedded Data Models from MongoDB's docs.
Semi-structured data
Data that don't fit in the relational model.