-
Notifications
You must be signed in to change notification settings - Fork 35
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Attributes/Persistence not friendly to noSQL embedding #40
Comments
In the long term, I believe Jsonapi-suite's persistence logic needs an overhaul to be able to suppor specific persistence behaviors and not just ActiveRecord's. I was thinking of a sideposting adapter like the sideloading adapter. I also don't like that
In the short term, passing the class JsonapiCompliable::Util::Persistence
def process_has_many(relationships)
...
x[:object] = x[:sideload].resource
.persist_with_relationships(x[:meta], x[:attributes], x[:relationships],
parent_object: x[:parent_object])
end
def persist_object(method, attributes, parent_object: nil)
if parent_object.present?
return persist_embedded_object(method, attributes, parent_object)
end
....
def persist_embedded_object(method, attributes, parent_object)
case method
when :destroy
@resource.destroy(attributes[:id], parent_object)
when :disassociate, nil
@resource.update(attributes, parent_object)
else
@resource.send(method, attributes, parent_object)
end
end
# Add one more argument to initialize method to store parent_object
def initialize(resource, meta, attributes, relationships, parent_object: {})
@resource = resource
@meta = meta
@attributes = attributes
@relationships = relationships
@parent_object = parent_object
end
def run
...
children = process_has_many(@relationships) do |x|
if x[:sideload].type.in?([:embeds_many, :embeds_one])
x[:parent_object] = persisted
else
update_foreign_key(persisted, x[:attributes], x)
end
end
end
class JsonapiCompliable::Resource
# - Add @parent_object argument when calling persist_object
def persist_with_relationships(meta, attributes, relationships,
parent_object: nil)
persistence = JsonapiCompliable::Util::Persistence \
.new(self, meta, attributes, relationships, parent_object: parent_object)
persistence.run
end
end As a final note, I believe what is missing to clean the code (and get rid of that x variable) would be a specific Those are just some suggestions, anyway I'm looking for hints in case there's a better way to integrate embedded sideposting with jsonapi-suite |
Here is a link to a compare view with my changes to make Mongoid work (I hope I didn't miss any) |
@Startouf thanks for digging in to this. I agree the In the meantime, here's what I believe is a simpler fix for your use case.What if we took This still has the downside of your parent being saved first, when you want to save things all at once. This probably means refactoring the persistence logic to have some Talking through it, though, I'm not sure this is the best approach. If you have a compound document, I would think these are more akin to attributes than associations. After all, it's not possible to fetch the "inner" relationship contents without the "outer" embedded document, right? Part of the reason this becomes difficult is this seems like it's really one object, but we're trying to treat it as several different objects. In other words, we could put all this logic in, but you'd still have a resource that cannot save itself without its parent. This makes it different than all other resources. If something cannot save itself without a parent, it's coupled to the parent and probably a better fit for In summary, even if we could easily get this API: def create(attributes, parents)
# ... create ...
end I'm not sure we should. A better option might be a new type of relationship - something like Thoughts? |
@Startouf I ended up needing something similar for a different use case. The default case is still def create(attrs)
end But you can now optionally do def create(attrs, parent = nil)
end This applies to You can use these lower-level methods as well if needed: def associate(parent, child, association_name, association_type)
end
def disassociate(parent, child, association_name, association_type)
end |
As discussed in the slack, embedded noSQL relationships are not easily integratable in JsonapiCompliable module.
The current logic assumes a
foreign_key
is required to save associations, however Mongoid'sembeds_one
andembeds_many
do not require the foreign key but the parent object itself. The nested objects are directly added as an attribute hash to the parent_object. It is almost as if it behaved as an attribute (with the big difference that embedded records are identified by an ID, indexable, and a special Mongoid proxy allows to use Active Model scopes on embedded relations)In a nutshell, the resource
#create
,#update
, and maybe even#destroy
methods need a way to access theparent_object
of the relation.The text was updated successfully, but these errors were encountered: