Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/jsonapi/resource_serializer.rb
Original file line number Diff line number Diff line change
Expand Up @@ -217,7 +217,7 @@ def format_route(route)
end

def self_link(source, association)
"#{self_href(source)}/links/#{format_route(association.name)}"
"#{self_href(source)}/relationships/#{format_route(association.name)}"
end

def related_link(source, association)
Expand Down
14 changes: 7 additions & 7 deletions lib/jsonapi/routing_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -95,17 +95,17 @@ def jsonapi_link(*links)
methods = links_methods(options)

if methods.include?(:show)
match "links/#{formatted_association_name}", controller: options[:controller],
match "relationships/#{formatted_association_name}", controller: options[:controller],
action: 'show_association', association: link_type.to_s, via: [:get]
end

if methods.include?(:update)
match "links/#{formatted_association_name}", controller: options[:controller],
match "relationships/#{formatted_association_name}", controller: options[:controller],
action: 'update_association', association: link_type.to_s, via: [:put, :patch]
end

if methods.include?(:destroy)
match "links/#{formatted_association_name}", controller: options[:controller],
match "relationships/#{formatted_association_name}", controller: options[:controller],
action: 'destroy_association', association: link_type.to_s, via: [:delete]
end
end
Expand All @@ -121,22 +121,22 @@ def jsonapi_links(*links)
methods = links_methods(options)

if methods.include?(:show)
match "links/#{formatted_association_name}", controller: options[:controller],
match "relationships/#{formatted_association_name}", controller: options[:controller],
action: 'show_association', association: link_type.to_s, via: [:get]
end

if methods.include?(:create)
match "links/#{formatted_association_name}", controller: options[:controller],
match "relationships/#{formatted_association_name}", controller: options[:controller],
action: 'create_association', association: link_type.to_s, via: [:post]
end

if methods.include?(:update)
match "links/#{formatted_association_name}", controller: options[:controller],
match "relationships/#{formatted_association_name}", controller: options[:controller],
action: 'update_association', association: link_type.to_s, via: [:put, :patch]
end

if methods.include?(:destroy)
match "links/#{formatted_association_name}/:keys", controller: options[:controller],
match "relationships/#{formatted_association_name}/:keys", controller: options[:controller],
action: 'destroy_association', association: link_type.to_s, via: [:delete]
end
end
Expand Down
16 changes: 8 additions & 8 deletions test/controllers/controller_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1394,7 +1394,7 @@ def test_show_has_one_relationship
id: '1'
},
links: {
self: 'http://test.host/posts/1/links/author',
self: 'http://test.host/posts/1/relationships/author',
related: 'http://test.host/posts/1/author'
}
}
Expand All @@ -1409,7 +1409,7 @@ def test_show_has_many_relationship
{type: 'tags', id: '5'}
],
links: {
self: 'http://test.host/posts/2/links/tags',
self: 'http://test.host/posts/2/relationships/tags',
related: 'http://test.host/posts/2/tags'
}
}
Expand All @@ -1428,7 +1428,7 @@ def test_show_has_one_relationship_nil
{
data: nil,
links: {
self: 'http://test.host/posts/17/links/author',
self: 'http://test.host/posts/17/relationships/author',
related: 'http://test.host/posts/17/author'
}
}
Expand Down Expand Up @@ -1881,19 +1881,19 @@ def test_get_related_resource
relationships: {
comments: {
links: {
self: 'http://test.host/people/1/links/comments',
self: 'http://test.host/people/1/relationships/comments',
related: 'http://test.host/people/1/comments'
}
},
posts: {
links: {
self: 'http://test.host/people/1/links/posts',
self: 'http://test.host/people/1/relationships/posts',
related: 'http://test.host/people/1/posts'
}
},
preferences: {
links: {
self: 'http://test.host/people/1/links/preferences',
self: 'http://test.host/people/1/relationships/preferences',
related: 'http://test.host/people/1/preferences'
},
data: {
Expand All @@ -1903,7 +1903,7 @@ def test_get_related_resource
},
"hair-cut" => {
"links" => {
"self" => "http://test.host/people/1/links/hair_cut",
"self" => "http://test.host/people/1/relationships/hair_cut",
"related" => "http://test.host/people/1/hair_cut"
},
"data" => nil
Expand Down Expand Up @@ -2057,7 +2057,7 @@ class Api::V1::PostsControllerTest < ActionController::TestCase
def test_show_post_namespaced
get :show, {id: '1'}
assert_response :success
assert_equal 'http://test.host/api/v1/posts/1/links/writer', json_response['data']['relationships']['writer']['links']['self']
assert_equal 'http://test.host/api/v1/posts/1/relationships/writer', json_response['data']['relationships']['writer']['links']['self']
end

def test_show_post_namespaced_include
Expand Down
28 changes: 14 additions & 14 deletions test/integration/requests/request_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ def test_get_camelized_route_and_key_filtered
def test_get_camelized_route_and_links
JSONAPI.configuration.json_key_format = :camelized_key
JSONAPI.configuration.route_format = :camelized_route
get '/api/v4/expenseEntries/1/links/isoCurrency'
get '/api/v4/expenseEntries/1/relationships/isoCurrency'
assert_equal 200, status
assert_hash_equals({'links' => {
'self' => 'http://www.example.com/api/v4/expenseEntries/1/links/isoCurrency',
'self' => 'http://www.example.com/api/v4/expenseEntries/1/relationships/isoCurrency',
'related' => 'http://www.example.com/api/v4/expenseEntries/1/isoCurrency'
},
'data' => {
Expand Down Expand Up @@ -205,21 +205,21 @@ def test_post_single_minimal_invalid

def test_update_association_without_content_type
ruby = Section.find_by(name: 'ruby')
patch '/posts/3/links/section', { 'data' => {type: 'sections', id: ruby.id.to_s }}.to_json
patch '/posts/3/relationships/section', { 'data' => {type: 'sections', id: ruby.id.to_s }}.to_json

assert_equal 415, status
end

def test_patch_update_association_has_one
ruby = Section.find_by(name: 'ruby')
patch '/posts/3/links/section', { 'data' => {type: 'sections', id: ruby.id.to_s }}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE
patch '/posts/3/relationships/section', { 'data' => {type: 'sections', id: ruby.id.to_s }}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE

assert_equal 204, status
end

def test_put_update_association_has_one
ruby = Section.find_by(name: 'ruby')
put '/posts/3/links/section', { 'data' => {type: 'sections', id: ruby.id.to_s }}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE
put '/posts/3/relationships/section', { 'data' => {type: 'sections', id: ruby.id.to_s }}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE

assert_equal 204, status
end
Expand All @@ -228,14 +228,14 @@ def test_patch_update_association_has_many_acts_as_set
# Comments are acts_as_set=false so PUT/PATCH should respond with 403

rogue = Comment.find_by(body: 'Rogue Comment Here')
patch '/posts/5/links/comments', { 'data' => [{type: 'comments', id: rogue.id.to_s }]}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE
patch '/posts/5/relationships/comments', { 'data' => [{type: 'comments', id: rogue.id.to_s }]}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE

assert_equal 403, status
end

def test_post_update_association_has_many
rogue = Comment.find_by(body: 'Rogue Comment Here')
post '/posts/5/links/comments', { 'data' => [{type: 'comments', id: rogue.id.to_s }]}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE
post '/posts/5/relationships/comments', { 'data' => [{type: 'comments', id: rogue.id.to_s }]}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE

assert_equal 204, status
end
Expand All @@ -244,7 +244,7 @@ def test_put_update_association_has_many_acts_as_set
# Comments are acts_as_set=false so PUT/PATCH should respond with 403. Note: JR currently treats PUT and PATCH as equivalent

rogue = Comment.find_by(body: 'Rogue Comment Here')
put '/posts/5/links/comments', { 'data' => [{type: 'comments', id: rogue.id.to_s }]}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE
put '/posts/5/relationships/comments', { 'data' => [{type: 'comments', id: rogue.id.to_s }]}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE

assert_equal 403, status
end
Expand Down Expand Up @@ -416,7 +416,7 @@ def test_flow_link_has_one_self_link
assert_equal 200, status
assert_hash_equals(json_response, {
'links' => {
'self' => 'http://www.example.com/posts/1/links/author',
'self' => 'http://www.example.com/posts/1/relationships/author',
'related' => 'http://www.example.com/posts/1/author'
},
'data' => {type: 'people', id: '1'}
Expand All @@ -433,7 +433,7 @@ def test_flow_link_has_many_self_link
assert_hash_equals(json_response,
{
'links' => {
'self' => 'http://www.example.com/posts/1/links/tags',
'self' => 'http://www.example.com/posts/1/relationships/tags',
'related' => 'http://www.example.com/posts/1/tags'
},
'data' => [
Expand All @@ -460,7 +460,7 @@ def test_flow_link_has_many_self_link_put
assert_hash_equals(json_response,
{
'links' => {
'self' => 'http://www.example.com/posts/5/links/tags',
'self' => 'http://www.example.com/posts/5/relationships/tags',
'related' => 'http://www.example.com/posts/5/tags'
},
'data' => [
Expand Down Expand Up @@ -644,7 +644,7 @@ def test_patch_formatted_dasherized_replace_has_many
def test_post_has_many_link
JSONAPI.configuration.route_format = :dasherized_route
JSONAPI.configuration.json_key_format = :dasherized_key
post '/api/v6/purchase-orders/3/links/line-items',
post '/api/v6/purchase-orders/3/relationships/line-items',
{
'data' => [
{'type' => 'line-items', 'id' => '3'},
Expand All @@ -658,7 +658,7 @@ def test_post_has_many_link
def test_patch_has_many_link
JSONAPI.configuration.route_format = :dasherized_route
JSONAPI.configuration.json_key_format = :dasherized_key
patch '/api/v6/purchase-orders/3/links/order-flags',
patch '/api/v6/purchase-orders/3/relationships/order-flags',
{
'data' => [
{'type' => 'order-flags', 'id' => '1'},
Expand All @@ -672,7 +672,7 @@ def test_patch_has_many_link
def test_patch_has_one
JSONAPI.configuration.route_format = :dasherized_route
JSONAPI.configuration.json_key_format = :dasherized_key
patch '/api/v6/line-items/5/links/purchase-order',
patch '/api/v6/line-items/5/relationships/purchase-order',
{
'data' => {'type' => 'purchase-orders', 'id' => '3'}
}.to_json, "CONTENT_TYPE" => JSONAPI::MEDIA_TYPE
Expand Down
28 changes: 14 additions & 14 deletions test/integration/routes/routes_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,37 +18,37 @@ def test_routing_posts_show
end

def test_routing_posts_links_author_show
assert_routing({path: '/posts/1/links/author', method: :get},
assert_routing({path: '/posts/1/relationships/author', method: :get},
{controller: 'posts', action: 'show_association', post_id: '1', association: 'author'})
end

def test_routing_posts_links_author_destroy
assert_routing({path: '/posts/1/links/author', method: :delete},
assert_routing({path: '/posts/1/relationships/author', method: :delete},
{controller: 'posts', action: 'destroy_association', post_id: '1', association: 'author'})
end

def test_routing_posts_links_author_update
assert_routing({path: '/posts/1/links/author', method: :patch},
assert_routing({path: '/posts/1/relationships/author', method: :patch},
{controller: 'posts', action: 'update_association', post_id: '1', association: 'author'})
end

def test_routing_posts_links_tags_show
assert_routing({path: '/posts/1/links/tags', method: :get},
assert_routing({path: '/posts/1/relationships/tags', method: :get},
{controller: 'posts', action: 'show_association', post_id: '1', association: 'tags'})
end

def test_routing_posts_links_tags_destroy
assert_routing({path: '/posts/1/links/tags/1,2', method: :delete},
assert_routing({path: '/posts/1/relationships/tags/1,2', method: :delete},
{controller: 'posts', action: 'destroy_association', post_id: '1', keys: '1,2', association: 'tags'})
end

def test_routing_posts_links_tags_create
assert_routing({path: '/posts/1/links/tags', method: :post},
assert_routing({path: '/posts/1/relationships/tags', method: :post},
{controller: 'posts', action: 'create_association', post_id: '1', association: 'tags'})
end

def test_routing_posts_links_tags_update_acts_as_set
assert_routing({path: '/posts/1/links/tags', method: :patch},
assert_routing({path: '/posts/1/relationships/tags', method: :patch},
{controller: 'posts', action: 'update_association', post_id: '1', association: 'tags'})
end

Expand All @@ -64,13 +64,13 @@ def test_routing_v1_posts_delete
end

def test_routing_v1_posts_links_writer_show
assert_routing({path: '/api/v1/posts/1/links/writer', method: :get},
assert_routing({path: '/api/v1/posts/1/relationships/writer', method: :get},
{controller: 'api/v1/posts', action: 'show_association', post_id: '1', association: 'writer'})
end

# V2
def test_routing_v2_posts_links_author_show
assert_routing({path: '/api/v2/posts/1/links/author', method: :get},
assert_routing({path: '/api/v2/posts/1/relationships/author', method: :get},
{controller: 'api/v2/posts', action: 'show_association', post_id: '1', association: 'author'})
end

Expand Down Expand Up @@ -100,7 +100,7 @@ def test_routing_v4_expenseEntries_resources
assert_routing({path: '/api/v4/expenseEntries/1', method: :get},
{action: 'show', controller: 'api/v4/expense_entries', id: '1'})

assert_routing({path: '/api/v4/expenseEntries/1/links/isoCurrency', method: :get},
assert_routing({path: '/api/v4/expenseEntries/1/relationships/isoCurrency', method: :get},
{controller: 'api/v4/expense_entries', action: 'show_association', expense_entry_id: '1', association: 'iso_currency'})
end

Expand All @@ -119,7 +119,7 @@ def test_routing_v5_expenseEntries_resources
assert_routing({path: '/api/v5/expense-entries/1', method: :get},
{action: 'show', controller: 'api/v5/expense_entries', id: '1'})

assert_routing({path: '/api/v5/expense-entries/1/links/iso-currency', method: :get},
assert_routing({path: '/api/v5/expense-entries/1/relationships/iso-currency', method: :get},
{controller: 'api/v5/expense_entries', action: 'show_association', expense_entry_id: '1', association: 'iso_currency'})
end

Expand All @@ -129,7 +129,7 @@ def test_routing_authors_show
end

def test_routing_author_links_posts_create_not_acts_as_set
assert_routing({path: '/api/v5/authors/1/links/posts', method: :post},
assert_routing({path: '/api/v5/authors/1/relationships/posts', method: :post},
{controller: 'api/v5/authors', action: 'create_association', author_id: '1', association: 'posts'})
end

Expand All @@ -146,12 +146,12 @@ def test_routing_primary_key_jsonapi_resources
# end

# def test_routing_posts_links_author_except_destroy
# assert_routing({ path: '/api/v3/posts/1/links/author', method: :delete },
# assert_routing({ path: '/api/v3/posts/1/relationships/author', method: :delete },
# { controller: 'api/v3/posts', action: 'destroy_association', post_id: '1', association: 'author' })
# end
#
# def test_routing_posts_links_tags_only_create_show
# assert_routing({ path: '/api/v3/posts/1/links/tags/1,2', method: :delete },
# assert_routing({ path: '/api/v3/posts/1/relationships/tags/1,2', method: :delete },
# { controller: 'api/v3/posts', action: 'destroy_association', post_id: '1', keys: '1,2', association: 'tags' })
# end

Expand Down
Loading