diff --git a/lib/action_controller/serialization.rb b/lib/action_controller/serialization.rb index 11c70fe6d..1b996f145 100644 --- a/lib/action_controller/serialization.rb +++ b/lib/action_controller/serialization.rb @@ -42,7 +42,7 @@ def use_adapter? @_serializer_opts[:scope] ||= serialization_scope @_serializer_opts[:scope_name] = _serialization_scope - + @_adapter_opts[:url_helper] = self # omg hax object = serializer.new(resource, @_serializer_opts) adapter = ActiveModel::Serializer::Adapter.create(object, @_adapter_opts) diff --git a/lib/active_model/serializer/adapter/json_api.rb b/lib/active_model/serializer/adapter/json_api.rb index f604b67fa..2bdf51443 100644 --- a/lib/active_model/serializer/adapter/json_api.rb +++ b/lib/active_model/serializer/adapter/json_api.rb @@ -6,6 +6,7 @@ def initialize(serializer, options = {}) super serializer.root = true @hash = {} + @url_helper = options[:url_helper] @top = @options.fetch(:top) { @hash } if fields = options.delete(:fields) @@ -138,21 +139,27 @@ def serialized_object_type(serializer) end end + attr_reader :url_helper + def add_resource_links(attrs, serializer, options = {}) options[:add_linked] = options.fetch(:add_linked, true) serializer.each_association do |name, association, opts| attrs[:links] ||= {} - if association.respond_to?(:each) - add_links(attrs, name, association) + if opts[:url] + attrs[:links][name] = url_helper.url_for([serializer.object, name]) else - add_link(attrs, name, association) - end + if association.respond_to?(:each) + add_links(attrs, name, association) + else + add_link(attrs, name, association) + end - if @options[:embed] != :ids && options[:add_linked] - Array(association).each do |association| - add_linked(name, association) + if @options[:embed] != :ids && options[:add_linked] + Array(association).each do |association| + add_linked(name, association) + end end end end diff --git a/test/adapter/json_api/has_many_url_test.rb b/test/adapter/json_api/has_many_url_test.rb new file mode 100644 index 000000000..1133c66b3 --- /dev/null +++ b/test/adapter/json_api/has_many_url_test.rb @@ -0,0 +1,27 @@ +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 + end + end + + tests MyController + + def test_render_resource_with_url_association + get :render_resource_with_url_association + response = JSON.parse(@response.body) + assert response.key? 'tags' + assert response['tags'].key? 'links' + assert response['tags']['links'].key? 'posts' + assert_equal 'http://test.host/tags/1/posts', response['tags']['links']['posts'] + end + end + end +end diff --git a/test/fixtures/poro.rb b/test/fixtures/poro.rb index d04d79dd5..d5d426d1b 100644 --- a/test/fixtures/poro.rb +++ b/test/fixtures/poro.rb @@ -1,4 +1,5 @@ class Model + extend ActiveModel::Naming def initialize(hash={}) @attributes = hash end @@ -24,7 +25,7 @@ def id end def to_param - id + id.to_s end def method_missing(meth, *args) @@ -63,6 +64,8 @@ class ProfilePreviewSerializer < ActiveModel::Serializer Bio = Class.new(Model) Blog = Class.new(Model) Role = Class.new(Model) +Tag = Class.new(Model) + module Spam; end Spam::UnrelatedLink = Class.new(Model) @@ -167,6 +170,10 @@ def self.root_name belongs_to :author, serializer: AuthorPreviewSerializer end +TagSerializer = Class.new(ActiveModel::Serializer) do + has_many :posts, url: true +end + Spam::UnrelatedLinkSerializer = Class.new(ActiveModel::Serializer) do attributes :id end diff --git a/test/test_helper.rb b/test/test_helper.rb index f3977b610..41d69ca1a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -23,6 +23,7 @@ class Foo < Rails::Application module TestHelper Routes = ActionDispatch::Routing::RouteSet.new Routes.draw do + get 'tags/:tag_id/posts', to: 'application#index', as: 'tag_posts' get ':controller(/:action(/:id))' get ':controller(/:action)' end