-
Notifications
You must be signed in to change notification settings - Fork 1.4k
Add supports for :links and :data options to has_many associations for jsonapi adapter #1028
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -8,14 +8,16 @@ class JsonApi < Adapter | |
| def initialize(serializer, options = {}) | ||
| super | ||
| @hash = { data: [] } | ||
|
|
||
| @url_helper = options[:url_helper] | ||
| if fields = options.delete(:fields) | ||
| @fieldset = ActiveModel::Serializer::Fieldset.new(fields, serializer.json_key) | ||
| else | ||
| @fieldset = options[:fieldset] | ||
| end | ||
| end | ||
|
|
||
| attr_reader :url_helper | ||
|
|
||
| def serializable_hash(options = nil) | ||
| options ||= {} | ||
| if serializer.respond_to?(:each) | ||
|
|
@@ -44,10 +46,17 @@ def fragment_cache(cached_hash, non_cached_hash) | |
|
|
||
| private | ||
|
|
||
| def add_relationships(resource, name, serializers) | ||
| def add_relationships(resource, name, serializers, opts) | ||
| resource[:relationships] ||= {} | ||
| resource[:relationships][name] ||= { data: [] } | ||
| resource[:relationships][name][:data] += serializers.map { |serializer| { type: serializer.json_api_type, id: serializer.id.to_s } } | ||
|
|
||
| if opts.fetch(:data, true) | ||
| resource[:relationships][name] ||= { data: [] } | ||
| resource[:relationships][name][:data] += serializers.map { |serializer| { type: serializer.json_api_type, id: serializer.id.to_s } } | ||
| end | ||
| if opts.fetch(:links, false) | ||
| resource[:relationships][name] ||= {} | ||
| resource[:relationships][name][:links] = { related: url_helper.url_for([serializer.object, name]) } | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Did you consider using
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Might this PR want to talk to #1018 (though these are different links)
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. #1018 is kind stopped for sometime, I wouldn't worry abou that right now, but indeed:
This would be nice. |
||
| end | ||
| end | ||
|
|
||
| def add_relationship(resource, name, serializer, val=nil) | ||
|
|
@@ -144,7 +153,7 @@ def add_resource_relationships(attrs, serializer, options = {}) | |
| attrs[:relationships] ||= {} | ||
|
|
||
| if serializer.respond_to?(:each) | ||
| add_relationships(attrs, key, serializer) | ||
| add_relationships(attrs, key, serializer, opts) | ||
| else | ||
| if opts[:virtual_value] | ||
| add_relationship(attrs, key, nil, opts[:virtual_value]) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| require 'test_helper' | ||
|
|
||
| module ActionController | ||
| module Serialization | ||
| class JsonApiHasManyUrlTest < ActionController::TestCase | ||
| class MyController < ActionController::Base | ||
|
|
||
| def render_resource_with_url_association | ||
| @tag = Tag.new(id: 1) | ||
| @tag.posts = [] | ||
| render json: @tag, adapter: :json_api, serializer: LinkTagSerializer | ||
| end | ||
| end | ||
|
|
||
| tests MyController | ||
|
|
||
| def test_render_resource_with_url_association | ||
| get :render_resource_with_url_association | ||
| expected = { | ||
| data: { | ||
| id: "1", | ||
| type: "tags", | ||
| relationships: { | ||
| posts: { | ||
| links: { | ||
| related: "http://test.host/tags/1/posts" | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } | ||
| assert_equal expected.to_json, response.body | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Would be nice to have test covering with both |
||
| end | ||
| end | ||
| end | ||
| end | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,10 +1,15 @@ | ||
| class Model | ||
| extend ActiveModel::Naming | ||
| FILE_DIGEST = Digest::MD5.hexdigest(File.open(__FILE__).read) | ||
|
|
||
| def self.model_name | ||
| @_model_name ||= ActiveModel::Name.new(self) | ||
| end | ||
|
|
||
| def to_model | ||
| self | ||
| end | ||
|
|
||
| def initialize(hash={}) | ||
| @attributes = hash | ||
| end | ||
|
|
@@ -29,9 +34,14 @@ def id | |
| @attributes[:id] || @attributes['id'] || object_id | ||
| end | ||
|
|
||
| def to_param | ||
| id.to_s | ||
| end | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hiya, Thanks for this. Would you mind helping me understand these changes?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, could you help us on understanding these? 😄
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 👍 Nice, could you add some comments on top of those method explaining this to help new contributors when jumping into the code 😄 |
||
|
|
||
| ### Helper methods, not required to be serializable | ||
| # | ||
| # Convenience for adding @attributes readers and writers | ||
|
|
||
| def method_missing(meth, *args) | ||
| if meth.to_s =~ /^(.*)=$/ | ||
| @attributes[$1.to_sym] = args[0] | ||
|
|
@@ -87,6 +97,7 @@ def cache_key | |
| "#{self.class.name.downcase}/#{self.id}" | ||
| end | ||
| end | ||
| Tag = Class.new(Model) | ||
|
|
||
| module Spam; end | ||
| Spam::UnrelatedLink = Class.new(Model) | ||
|
|
@@ -243,6 +254,10 @@ def self.root_name | |
| has_one :blog, key: :site | ||
| end | ||
|
|
||
| LinkTagSerializer = Class.new(ActiveModel::Serializer) do | ||
| has_many :posts, links: true, data: false | ||
| end | ||
|
|
||
| VirtualValueSerializer = Class.new(ActiveModel::Serializer) do | ||
| attributes :id | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
makes me sad we need to do this :( so much coupling, but I guess that's where we're going. I coulda sworn you could
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can do that, but what we are trying to is more like
Rails.application.routes.url_for([@post, :comments])There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's right. Any way we can at least narrow the interface to not include the entire controller? This is just be being paranoid of scope creep enabled by it being easy to do. I like it when tools make it hard to do things the authors don't want you to :)