Feature/dynamic relationships stage 1#709
Feature/dynamic relationships stage 1#709garytaylor wants to merge 15 commits intoJSONAPI-Resources:masterfrom shiftcommerce:feature/dynamic-relationships-stage-1
Conversation
Changes from cerebris
This change allows a resource to add to the relationships in the instance - for "virtual" relationships that are not defined in the model.
This is paving the way for dynamic virtual relationships based on the model data
When adding new relationships on a class, these new methods are now used in place of the code being defined inline (to allow re use in the next phase) Note - the same code is being executed - just in a slightly different way - no functionality changes or breaking changes, with the exception of if someone has these methods already defined
…still respond to :save which is the important thing.
…y relations that are not real AR relations that can be passed to AR's include method. This resolves the issue where a 'relationship' is purely a method on an AR object that might return an array, an AR scope etc.. but is not a true relationship. When the query is executed the relationship will not exist and AR gets confused
Merge latest from cerebris into master
…ionship_names_to_relations when they are not defined as AR relationships. This prevents issues when the query with its includes is executed
…into cerebris-master # Conflicts: # lib/jsonapi/configuration.rb
…into cerebris-master # Conflicts: # lib/jsonapi/configuration.rb
Relationships that do not exist in the class can now still be included
|
Any progress on this? Is there a chance that this will be merged? |
|
I've got some concerns about the added complexity and performance implications of this PR for what I'm seeing as an edge case. Have you tried simply setting up relationships and selectively hiding them using the |
EDIT: scratch all of this, turns out this already works.I'm personally interested in using this type of feature for 'pseudo-relationships'. Suppose we have the following setup: class Movie
has_many :votes
end
class Vote
belongs_to :movie
belongs_to :person
# with unique index on [:person_id, :movie_id]
end
class Person
has_many :votes
endWhat I would like is to give the MovieResource a pseudo-relationship with a Vote, such that I can do something like this: class MovieResource
has_one :vote
def vote
@model.votes.find_by(person_id: context[:current_user])
endThat doesn't seem possible currently, since |
|
Sorry guys - not been looking at emails as often as I should. It is sometimes very useful to present information as dynamic relationships The change that I made was mainly refactoring to allow existing code to be Cheers Gary On Thu, Aug 11, 2016 at 8:51 AM Hidde-Jan Jongsma notifications@github.com
|
This PR prepares the ground for allowing "dynamic relationships" which allow relationships to be defined based on the data in the model.
This is extremely useful when you want to present the data that you have in say some metadata as a relationship to assist the front end developers who have a nice convenient jsonapi client gem.
Probably best if we have an example
This is an example of how my data might look without dynamic relationships
The key thing here is the "related-images" bit which is an array of ids. The data could be stored like this for a number of reasons, but isn't much help for a front end developer who would need to know to call something like :-
So, because we want all of our API users to be our friends and not hate us - with this change, the "_relationships" is now an instance method as well as a class method. We cant override the class method for this to add relationships as this would affect all instance. So, instead, we might override the instance method and add the relationships from data in the instance.
The actual overriding code mentioned above is not included in this PR, this is purely the ground work for this to even be allowed to happen. A decent API to allow the dynamic relationships to be easily defined is another subject.
This PR does not change the functionality of the existing system (unless the config validate_includes is set to false (mentioned below)) - it is mainly refactoring of the code that was dynamically generated in the JSONAPI::Resource class for the relationships. This code is now moved into the JSONAPI::AssociatedResource class which is then called by the dynamically generated code mentioned above.
This is purely for reuse. We can now call the same code WITHOUT needing it to be defined as a method on the resource (such as "records_for_<>") - instead we detect that this method is not defined and try "records_for(relationship_name)" instead which the resource can fetch the data based on the dynamic relationship name.
The change to the _relationships method will not affect existing systems as the definition of it simply calls the class method as standard - which is identical to what it used to do.
So, I mentioned the validate_includes config flag - so what is this for ?
Under normal operation, if a client requested a relationship using the includes parameter that is not defined in the resource up front, it will respond with a bad request.
This prevents dynamic relationships from the word go.
So, if we set this to false, this prevents this validation which does mean that if the relationship does not exist, then we will get an error from a different place. But, if the relationship is a dynamic one, then it can work.