Skip to content

Commit 6f5bdd5

Browse files
committed
fixes #982 fix relationship linkage
when belongs_to relationship has overridden primary_key when polymorphic relationship has overridden primary_key add tests
1 parent 4b75036 commit 6f5bdd5

File tree

10 files changed

+154
-3
lines changed

10 files changed

+154
-3
lines changed

lib/jsonapi/relationship.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,10 @@ def readonly?
6464
@options[:readonly]
6565
end
6666

67+
def redefined_pkey?
68+
belongs_to? && primary_key != resource_klass._default_primary_key
69+
end
70+
6771
class ToOne < Relationship
6872
attr_reader :foreign_key_on
6973

lib/jsonapi/resource.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -783,7 +783,11 @@ def _model_name
783783
end
784784

785785
def _primary_key
786-
@_primary_key ||= _model_class.respond_to?(:primary_key) ? _model_class.primary_key : :id
786+
@_primary_key ||= _default_primary_key
787+
end
788+
789+
def _default_primary_key
790+
@_default_primary_key ||=_model_class.respond_to?(:primary_key) ? _model_class.primary_key : :id
787791
end
788792

789793
def _cache_field

lib/jsonapi/resource_serializer.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -454,7 +454,7 @@ def link_object(source, relationship, include_linkage = false)
454454
def foreign_key_value(source, relationship)
455455
related_resource_id = if source.preloaded_fragments.has_key?(format_key(relationship.name))
456456
source.preloaded_fragments[format_key(relationship.name)].values.first.try(:id)
457-
elsif source.respond_to?(relationship.foreign_key)
457+
elsif !relationship.redefined_pkey? && !relationship.polymorphic? && source.respond_to?(relationship.foreign_key)
458458
# If you have direct access to the underlying id, you don't have to load the relationship
459459
# which can save quite a lot of time when loading a lot of data.
460460
# This does not apply to e.g. has_one :through relationships.

test/fixtures/access_cards.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
john_doe_worker_card:
2+
id: 1
3+
token: "some-token"
4+
security_level: "admin"

test/fixtures/active_record.rb

Lines changed: 80 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,30 @@
310310
t.string :name
311311
end
312312

313-
# special cases
313+
create_table :storages, force: true do |t|
314+
t.string :token, null: false
315+
t.string :name
316+
t.timestamps null: false
317+
end
318+
319+
create_table :keepers, force: true do |t|
320+
t.string :name
321+
t.string :keepable_type, null: false
322+
t.integer :keepable_id, null: false
323+
t.timestamps null: false
324+
end
325+
326+
create_table :access_cards, force: true do |t|
327+
t.string :token, null: false
328+
t.string :security_level
329+
t.timestamps null: false
330+
end
331+
332+
create_table :workers, force: true do |t|
333+
t.string :name
334+
t.integer :access_card_id, null: false
335+
t.timestamps null: false
336+
end
314337
end
315338

316339
### MODELS
@@ -655,6 +678,22 @@ class Customer < Customer
655678
end
656679
end
657680

681+
class Storage < ActiveRecord::Base
682+
has_one :keeper, class_name: 'Keeper', as: :keepable
683+
end
684+
685+
class Keeper < ActiveRecord::Base
686+
belongs_to :keepable, polymorphic: true
687+
end
688+
689+
class AccessCard < ActiveRecord::Base
690+
has_one :worker, class_name: 'Worker'
691+
end
692+
693+
class Worker < ActiveRecord::Base
694+
belongs_to :access_card
695+
end
696+
658697
### CONTROLLERS
659698
class AuthorsController < JSONAPI::ResourceControllerMetal
660699
end
@@ -930,6 +969,17 @@ class DoctorsController < JSONAPI::ResourceController
930969
class RespondentController < JSONAPI::ResourceController
931970
end
932971

972+
class StoragesController < BaseController
973+
end
974+
975+
class KeepersController < BaseController
976+
end
977+
978+
class AccessCardsController < BaseController
979+
end
980+
981+
class WorkersController < BaseController
982+
end
933983
### RESOURCES
934984
class BaseResource < JSONAPI::Resource
935985
abstract
@@ -1894,6 +1944,35 @@ class RespondentResource < JSONAPI::Resource
18941944
abstract
18951945
end
18961946

1947+
class StorageResource < JSONAPI::Resource
1948+
key_type :string
1949+
primary_key :token
1950+
1951+
attribute :name
1952+
end
1953+
1954+
class KeeperResource < JSONAPI::Resource
1955+
has_one :keepable, polymorphic: true, foreign_key: :keepable_id
1956+
1957+
attribute :name
1958+
end
1959+
1960+
class KeepableResource < JSONAPI::Resource
1961+
end
1962+
1963+
class AccessCardResource < JSONAPI::Resource
1964+
key_type :string
1965+
primary_key :token
1966+
1967+
attribute :security_level
1968+
end
1969+
1970+
class WorkerResource < JSONAPI::Resource
1971+
has_one :access_card
1972+
1973+
attribute :name
1974+
end
1975+
18971976
### PORO Data - don't do this in a production app
18981977
$breed_data = BreedData.new
18991978
$breed_data.add(Breed.new(0, 'persian'))

test/fixtures/keepers.yml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
john_doe:
2+
id: 1
3+
name: "John Doe"
4+
keepable_id: 1 # storages.yml warehouse_1
5+
keepable_type: "Storage"

test/fixtures/storages.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
warehouse_1:
2+
id: 1
3+
name: "Warehouse 1"
4+
token: "some-token"

test/fixtures/workers.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
john_doe_worker:
2+
id: 1
3+
name: "John Doe"
4+
access_card_id: 1 # access_cards.yml john_doe_worker_card

test/integration/requests/request_test.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1102,4 +1102,48 @@ def test_getting_resource_with_correct_type_when_sti
11021102
assert_cacheable_jsonapi_get '/vehicles/1'
11031103
assert_equal 'cars', json_response['data']['type']
11041104
end
1105+
1106+
def test_get_resource_with_polymorphic_relationship_and_changed_primary_key
1107+
keeper = Keeper.find(1)
1108+
storage = keeper.keepable
1109+
assert_cacheable_jsonapi_get '/keepers/1?include=keepable'
1110+
assert_jsonapi_response 200
1111+
1112+
data = json_response['data']
1113+
refute_nil data
1114+
assert_equal keeper.id.to_s, data['id']
1115+
1116+
refute_nil data['relationships']
1117+
refute_nil data['relationships']['keepable']
1118+
refute_nil data['relationships']['keepable']['data']
1119+
assert_equal 'storages', data['relationships']['keepable']['data']['type']
1120+
assert_equal storage.token, data['relationships']['keepable']['data']['id']
1121+
1122+
included = json_response['included']
1123+
refute_nil included
1124+
assert_equal 'storages', included.first['type']
1125+
assert_equal storage.token, included.first['id']
1126+
end
1127+
1128+
def test_get_resource_with_belongs_to_relationship_and_changed_primary_key
1129+
worker = Worker.find(1)
1130+
access_card = worker.access_card
1131+
assert_cacheable_jsonapi_get '/workers/1?include=access_card'
1132+
assert_jsonapi_response 200
1133+
1134+
data = json_response['data']
1135+
refute_nil data
1136+
assert_equal worker.id.to_s, data['id']
1137+
1138+
refute_nil data['relationships']
1139+
refute_nil data['relationships']['access_card']
1140+
refute_nil data['relationships']['access_card']['data']
1141+
assert_equal 'access_cards', data['relationships']['access_card']['data']['type']
1142+
assert_equal access_card.token, data['relationships']['access_card']['data']['id']
1143+
1144+
included = json_response['included']
1145+
refute_nil included
1146+
assert_equal 'access_cards', included.first['type']
1147+
assert_equal access_card.token, included.first['id']
1148+
end
11051149
end

test/test_helper.rb

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -377,6 +377,9 @@ class CatResource < JSONAPI::Resource
377377
end
378378
end
379379

380+
jsonapi_resources :keepers, only: [:show]
381+
jsonapi_resources :workers, only: [:show]
382+
380383
mount MyEngine::Engine => "/boomshaka", as: :my_engine
381384
mount ApiV2Engine::Engine => "/api_v2", as: :api_v2_engine
382385
end

0 commit comments

Comments
 (0)