jsonapi-resources 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,7 +1,7 @@
1
1
  module JSONAPI
2
2
  class ResourceSerializer
3
3
 
4
- attr_reader :url_generator, :key_formatter, :serialization_options, :primary_class_name
4
+ attr_reader :link_builder, :key_formatter, :serialization_options, :primary_class_name
5
5
 
6
6
  # initialize
7
7
  # Options can include
@@ -21,7 +21,7 @@ module JSONAPI
21
21
  @include = options.fetch(:include, [])
22
22
  @include_directives = options[:include_directives]
23
23
  @key_formatter = options.fetch(:key_formatter, JSONAPI.configuration.key_formatter)
24
- @url_generator = generate_link_builder(primary_resource_klass, options)
24
+ @link_builder = generate_link_builder(primary_resource_klass, options)
25
25
  @always_include_to_one_linkage_data = options.fetch(:always_include_to_one_linkage_data,
26
26
  JSONAPI.configuration.always_include_to_one_linkage_data)
27
27
  @always_include_to_many_linkage_data = options.fetch(:always_include_to_many_linkage_data,
@@ -72,8 +72,8 @@ module JSONAPI
72
72
  }
73
73
  end
74
74
 
75
- def find_link(query_params)
76
- url_generator.query_link(query_params)
75
+ def query_link(query_params)
76
+ link_builder.query_link(query_params)
77
77
  end
78
78
 
79
79
  def format_key(key)
@@ -226,7 +226,7 @@ module JSONAPI
226
226
 
227
227
  def relationship_links(source)
228
228
  links = {}
229
- links[:self] = url_generator.self_link(source)
229
+ links[:self] = link_builder.self_link(source)
230
230
 
231
231
  links
232
232
  end
@@ -237,11 +237,11 @@ module JSONAPI
237
237
  end
238
238
 
239
239
  def self_link(source, relationship)
240
- url_generator.relationships_self_link(source, relationship)
240
+ link_builder.relationships_self_link(source, relationship)
241
241
  end
242
242
 
243
243
  def related_link(source, relationship)
244
- url_generator.relationships_related_link(source, relationship)
244
+ link_builder.relationships_related_link(source, relationship)
245
245
  end
246
246
 
247
247
  def to_one_linkage(source, relationship)
@@ -1,5 +1,5 @@
1
1
  module JSONAPI
2
2
  module Resources
3
- VERSION = '0.6.2'
3
+ VERSION = '0.7.0'
4
4
  end
5
5
  end
@@ -74,9 +74,9 @@ module JSONAPI
74
74
  result.pagination_params.each_pair do |link_name, params|
75
75
  if result.is_a?(JSONAPI::RelatedResourcesOperationResult)
76
76
  relationship = result.source_resource.class._relationships[result._type.to_sym]
77
- links[link_name] = serializer.url_generator.relationships_related_link(result.source_resource, relationship, query_params(params))
77
+ links[link_name] = serializer.link_builder.relationships_related_link(result.source_resource, relationship, query_params(params))
78
78
  else
79
- links[link_name] = serializer.find_link(query_params(params))
79
+ links[link_name] = serializer.query_link(query_params(params))
80
80
  end
81
81
  end
82
82
  end
@@ -2183,7 +2183,7 @@ class PeopleControllerTest < ActionController::TestCase
2183
2183
  assert_equal json_response['data'][0]['attributes']['name'], 'Joe Author'
2184
2184
  end
2185
2185
 
2186
- def test_get_related_resource
2186
+ def test_get_related_resource_no_namespace
2187
2187
  original_config = JSONAPI.configuration.dup
2188
2188
  JSONAPI.configuration.json_key_format = :dasherized_key
2189
2189
  JSONAPI.configuration.route_format = :underscored_key
@@ -2253,6 +2253,15 @@ class PeopleControllerTest < ActionController::TestCase
2253
2253
  end
2254
2254
  end
2255
2255
 
2256
+ class BooksControllerTest < ActionController::TestCase
2257
+ def test_books_include_correct_type
2258
+ $test_user = Person.find(1)
2259
+ get :index, {filter: {id: '1'}, include: 'authors'}
2260
+ assert_response :success
2261
+ assert_equal 'authors', json_response['included'][0]['type']
2262
+ end
2263
+ end
2264
+
2256
2265
  class Api::V5::AuthorsControllerTest < ActionController::TestCase
2257
2266
  def test_get_person_as_author
2258
2267
  get :index, {filter: {id: '1'}}
@@ -2288,7 +2297,7 @@ class Api::V5::AuthorsControllerTest < ActionController::TestCase
2288
2297
  def meta(options)
2289
2298
  {
2290
2299
  fixed: 'Hardcoded value',
2291
- computed: "#{self.class._type.to_s}: #{options[:serializer].url_generator.self_link(self)}",
2300
+ computed: "#{self.class._type.to_s}: #{options[:serializer].link_builder.self_link(self)}",
2292
2301
  computed_foo: options[:serialization_options][:foo],
2293
2302
  options[:serializer].format_key('test_key') => 'test value'
2294
2303
  }
@@ -2322,7 +2331,7 @@ class Api::V5::AuthorsControllerTest < ActionController::TestCase
2322
2331
  {
2323
2332
  custom_hash: {
2324
2333
  fixed: 'Hardcoded value',
2325
- computed: "#{self.class._type.to_s}: #{options[:serializer].url_generator.self_link(self)}",
2334
+ computed: "#{self.class._type.to_s}: #{options[:serializer].link_builder.self_link(self)}",
2326
2335
  computed_foo: options[:serialization_options][:foo],
2327
2336
  options[:serializer].format_key('test_key') => 'test value'
2328
2337
  }
@@ -3100,19 +3109,17 @@ class Api::V1::MoonsControllerTest < ActionController::TestCase
3100
3109
  def test_get_related_resource
3101
3110
  get :get_related_resource, {crater_id: 'S56D', relationship: 'moon', source: "api/v1/craters"}
3102
3111
  assert_response :success
3103
- assert_hash_equals json_response,
3104
- {
3105
- data: {
3106
- id: "1",
3107
- type: "moons",
3108
- links: {self: "http://test.host/moons/1"},
3109
- attributes: {name: "Titan", description: "Best known of the Saturn moons."},
3110
- relationships: {
3111
- planet: {links: {self: "http://test.host/moons/1/relationships/planet", related: "http://test.host/moons/1/planet"}},
3112
- craters: {links: {self: "http://test.host/moons/1/relationships/craters", related: "http://test.host/moons/1/craters"}}}
3113
- }
3114
- }
3115
-
3112
+ assert_hash_equals({
3113
+ data: {
3114
+ id: "1",
3115
+ type: "moons",
3116
+ links: {self: "http://test.host/api/v1/moons/1"},
3117
+ attributes: {name: "Titan", description: "Best known of the Saturn moons."},
3118
+ relationships: {
3119
+ planet: {links: {self: "http://test.host/api/v1/moons/1/relationships/planet", related: "http://test.host/api/v1/moons/1/planet"}},
3120
+ craters: {links: {self: "http://test.host/api/v1/moons/1/relationships/craters", related: "http://test.host/api/v1/moons/1/craters"}}}
3121
+ }
3122
+ }, json_response)
3116
3123
  end
3117
3124
 
3118
3125
  def test_get_related_resources_with_select_some_db_columns
@@ -3141,23 +3148,24 @@ class Api::V1::CratersControllerTest < ActionController::TestCase
3141
3148
  def test_get_related_resources
3142
3149
  get :get_related_resources, {moon_id: '1', relationship: 'craters', source: "api/v1/moons"}
3143
3150
  assert_response :success
3144
- assert_hash_equals json_response,
3145
- {
3146
- data: [
3147
- {id:"A4D3",
3148
- type:"craters",
3149
- links:{self: "http://test.host/api/v1/craters/A4D3"},
3150
- attributes:{code: "A4D3", description: "Small crater"},
3151
- relationships:{moon: {links: {self: "http://test.host/api/v1/craters/A4D3/relationships/moon", related: "http://test.host/api/v1/craters/A4D3/moon"}}}
3152
- },
3153
- {id: "S56D",
3154
- type: "craters",
3155
- links:{self: "http://test.host/api/v1/craters/S56D"},
3156
- attributes:{code: "S56D", description: "Very large crater"},
3157
- relationships:{moon: {links: {self: "http://test.host/api/v1/craters/S56D/relationships/moon", related: "http://test.host/api/v1/craters/S56D/moon"}}}
3158
- }
3159
- ]
3160
- }
3151
+ assert_hash_equals({
3152
+ data: [
3153
+ {
3154
+ id:"A4D3",
3155
+ type:"craters",
3156
+ links:{self: "http://test.host/api/v1/craters/A4D3"},
3157
+ attributes:{code: "A4D3", description: "Small crater"},
3158
+ relationships:{moon: {links: {self: "http://test.host/api/v1/craters/A4D3/relationships/moon", related: "http://test.host/api/v1/craters/A4D3/moon"}}}
3159
+ },
3160
+ {
3161
+ id: "S56D",
3162
+ type: "craters",
3163
+ links:{self: "http://test.host/api/v1/craters/S56D"},
3164
+ attributes:{code: "S56D", description: "Very large crater"},
3165
+ relationships:{moon: {links: {self: "http://test.host/api/v1/craters/S56D/relationships/moon", related: "http://test.host/api/v1/craters/S56D/moon"}}}
3166
+ }
3167
+ ]
3168
+ }, json_response)
3161
3169
  end
3162
3170
 
3163
3171
  def test_show_relationship
@@ -3236,3 +3244,39 @@ class VehiclesControllerTest < ActionController::TestCase
3236
3244
  end
3237
3245
  end
3238
3246
  end
3247
+
3248
+ class Api::V7::ClientsControllerTest < ActionController::TestCase
3249
+ def test_get_namespaced_model_not_matching_resource_using_model_hint
3250
+ get :index
3251
+ assert_response :success
3252
+ assert_equal 'clients', json_response['data'][0]['type']
3253
+ ensure
3254
+ Api::V7::ClientResource._model_hints['api/v7/customer'] = 'clients'
3255
+ end
3256
+
3257
+ def test_get_namespaced_model_not_matching_resource_not_using_model_hint
3258
+ Api::V7::ClientResource._model_hints.delete('api/v7/customer')
3259
+ get :index
3260
+ assert_response :success
3261
+ assert_equal 'customers', json_response['data'][0]['type']
3262
+ ensure
3263
+ Api::V7::ClientResource._model_hints['api/v7/customer'] = 'clients'
3264
+ end
3265
+ end
3266
+
3267
+ class Api::V7::CustomersControllerTest < ActionController::TestCase
3268
+ def test_get_namespaced_model_matching_resource
3269
+ get :index
3270
+ assert_response :success
3271
+ assert_equal 'customers', json_response['data'][0]['type']
3272
+ end
3273
+ end
3274
+
3275
+ class Api::V7::CategoriesControllerTest < ActionController::TestCase
3276
+ def test_uncaught_error_in_controller
3277
+
3278
+ get :show, {id: '1'}
3279
+ assert_response 500
3280
+ assert_match /Internal Server Error/, json_response['errors'][0]['detail']
3281
+ end
3282
+ end
@@ -15,6 +15,7 @@ ActiveRecord::Schema.define do
15
15
  t.belongs_to :preferences
16
16
  t.integer :hair_cut_id, index: true
17
17
  t.boolean :book_admin, default: false
18
+ t.boolean :special, default: false
18
19
  t.timestamps null: false
19
20
  end
20
21
 
@@ -134,6 +135,11 @@ ActiveRecord::Schema.define do
134
135
  t.boolean :banned, default: false
135
136
  end
136
137
 
138
+ create_table :book_authors, force: true do |t|
139
+ t.integer :book_id
140
+ t.integer :person_id
141
+ end
142
+
137
143
  create_table :book_comments, force: true do |t|
138
144
  t.text :body
139
145
  t.belongs_to :book, index: true
@@ -254,6 +260,8 @@ class Person < ActiveRecord::Base
254
260
  belongs_to :hair_cut
255
261
  has_one :author_detail
256
262
 
263
+ has_and_belongs_to_many :books, join_table: :book_authors
264
+
257
265
  ### Validations
258
266
  validates :name, presence: true
259
267
  validates :date_joined, presence: true
@@ -408,6 +416,8 @@ end
408
416
  class Book < ActiveRecord::Base
409
417
  has_many :book_comments
410
418
  has_many :approved_book_comments, -> { where(approved: true) }, class_name: "BookComment"
419
+
420
+ has_and_belongs_to_many :authors, join_table: :book_authors, class_name: "Person"
411
421
  end
412
422
 
413
423
  class BookComment < ActiveRecord::Base
@@ -502,6 +512,16 @@ end
502
512
  class WebPage < ActiveRecord::Base
503
513
  end
504
514
 
515
+ module Api
516
+ module V7
517
+ class Client < Customer
518
+ end
519
+
520
+ class Customer < Customer
521
+ end
522
+ end
523
+ end
524
+
505
525
  ### OperationsProcessor
506
526
  class CountingActiveRecordOperationsProcessor < ActiveRecordOperationsProcessor
507
527
  after_find_operation do
@@ -545,6 +565,15 @@ class PostsController < BaseController
545
565
  head :forbidden
546
566
  end
547
567
 
568
+ def handle_exceptions(e)
569
+ case e
570
+ when PostsController::SpecialError
571
+ raise e
572
+ else
573
+ super(e)
574
+ end
575
+ end
576
+
548
577
  #called by test_on_server_error
549
578
  def self.set_callback_message(error)
550
579
  @callback_message = "Sent from method"
@@ -599,6 +628,12 @@ end
599
628
  class BoatsController < JSONAPI::ResourceController
600
629
  end
601
630
 
631
+ class BooksController < JSONAPI::ResourceController
632
+ end
633
+
634
+ class AuthorsController < JSONAPI::ResourceController
635
+ end
636
+
602
637
  ### CONTROLLERS
603
638
  module Api
604
639
  module V1
@@ -731,6 +766,12 @@ module Api
731
766
 
732
767
  class OrderFlagsController < JSONAPI::ResourceController
733
768
  end
769
+
770
+ class CategoriesController < JSONAPI::ResourceController
771
+ end
772
+
773
+ class ClientsController < JSONAPI::ResourceController
774
+ end
734
775
  end
735
776
 
736
777
  module V8
@@ -755,18 +796,27 @@ class PersonResource < BaseResource
755
796
  has_one :preferences
756
797
  has_one :hair_cut
757
798
 
758
- filter :name
759
-
760
- def self.verify_custom_filter(filter, values, context)
761
- case filter
762
- when :name
763
- values.each do |value|
764
- if value.length < 3
765
- raise JSONAPI::Exceptions::InvalidFilterValue.new(filter, value)
766
- end
767
- end
799
+ filter :name, verify: ->(values, _context) {
800
+ values.each do |value|
801
+ if value.length < 3
802
+ raise JSONAPI::Exceptions::InvalidFilterValue.new(:name, value)
803
+ end
768
804
  end
769
- return filter, values
805
+ return values
806
+ }
807
+ end
808
+
809
+ class SpecialBaseResource < BaseResource
810
+ abstract
811
+
812
+ model_hint model: Person, resource: :special_person
813
+ end
814
+
815
+ class SpecialPersonResource < SpecialBaseResource
816
+ model_name 'Person'
817
+
818
+ def self.records(options = {})
819
+ Person.where(special: true)
770
820
  end
771
821
  end
772
822
 
@@ -871,7 +921,18 @@ class PostResource < JSONAPI::Resource
871
921
  end
872
922
 
873
923
  filters :title, :author, :tags, :comments
874
- filters :id, :ids
924
+ filter :id, verify: ->(values, context) {
925
+ verify_keys(values, context)
926
+ return values
927
+ }
928
+ filter :ids,
929
+ verify: ->(values, context) {
930
+ verify_keys(values, context)
931
+ return values
932
+ },
933
+ apply: -> (records, value, _options) {
934
+ records.where('id IN (?)', value)
935
+ }
875
936
 
876
937
  def self.updatable_fields(context)
877
938
  super(context) - [:author, :subject]
@@ -885,17 +946,6 @@ class PostResource < JSONAPI::Resource
885
946
  super(context) - [:id]
886
947
  end
887
948
 
888
- def self.verify_custom_filter(filter, values, context = nil)
889
- case filter
890
- when :id
891
- verify_keys(values, context)
892
- when :ids #coerce :ids to :id
893
- verify_keys(values, context)
894
- return :id, values
895
- end
896
- return filter, values
897
- end
898
-
899
949
  def self.verify_key(key, context = nil)
900
950
  super(key)
901
951
  raise JSONAPI::Exceptions::RecordNotFound.new(key) unless find_by_key(key, context: context)
@@ -1058,6 +1108,19 @@ class WebPageResource < JSONAPI::Resource
1058
1108
  attribute :link
1059
1109
  end
1060
1110
 
1111
+ class AuthorResource < JSONAPI::Resource
1112
+ model_name 'Person'
1113
+ attributes :name
1114
+ end
1115
+
1116
+ class BookResource < JSONAPI::Resource
1117
+ has_many :authors, class_name: 'Author'
1118
+ end
1119
+
1120
+ class AuthorDetailResource < JSONAPI::Resource
1121
+ attributes :author_stuff
1122
+ end
1123
+
1061
1124
  module Api
1062
1125
  module V1
1063
1126
  class WriterResource < JSONAPI::Resource
@@ -1088,32 +1151,32 @@ module Api
1088
1151
  filters :writer
1089
1152
  end
1090
1153
 
1091
- PersonResource = PersonResource.dup
1092
- CommentResource = CommentResource.dup
1093
- TagResource = TagResource.dup
1094
- SectionResource = SectionResource.dup
1095
- IsoCurrencyResource = IsoCurrencyResource.dup
1096
- ExpenseEntryResource = ExpenseEntryResource.dup
1097
- BreedResource = BreedResource.dup
1098
- PlanetResource = PlanetResource.dup
1099
- PlanetTypeResource = PlanetTypeResource.dup
1100
- MoonResource = MoonResource.dup
1101
- CraterResource = CraterResource.dup
1102
- PreferencesResource = PreferencesResource.dup
1103
- EmployeeResource = EmployeeResource.dup
1104
- FriendResource = FriendResource.dup
1105
- HairCutResource = HairCutResource.dup
1106
- VehicleResource = VehicleResource.dup
1107
- CarResource = CarResource.dup
1108
- BoatResource = BoatResource.dup
1154
+ class PersonResource < PersonResource; end
1155
+ class CommentResource < CommentResource; end
1156
+ class TagResource < TagResource; end
1157
+ class SectionResource < SectionResource; end
1158
+ class IsoCurrencyResource < IsoCurrencyResource; end
1159
+ class ExpenseEntryResource < ExpenseEntryResource; end
1160
+ class BreedResource < BreedResource; end
1161
+ class PlanetResource < PlanetResource; end
1162
+ class PlanetTypeResource < PlanetTypeResource; end
1163
+ class MoonResource < MoonResource; end
1164
+ class CraterResource < CraterResource; end
1165
+ class PreferencesResource < PreferencesResource; end
1166
+ class EmployeeResource < EmployeeResource; end
1167
+ class FriendResource < FriendResource; end
1168
+ class HairCutResource < HairCutResource; end
1169
+ class VehicleResource < VehicleResource; end
1170
+ class CarResource < CarResource; end
1171
+ class BoatResource < BoatResource; end
1109
1172
  end
1110
1173
  end
1111
1174
 
1112
1175
  module Api
1113
1176
  module V2
1114
- PreferencesResource = PreferencesResource.dup
1115
- PersonResource = PersonResource.dup
1116
- PostResource = PostResource.dup
1177
+ class PreferencesResource < PreferencesResource; end
1178
+ class PersonResource < PersonResource; end
1179
+ class PostResource < PostResource; end
1117
1180
 
1118
1181
  class BookResource < JSONAPI::Resource
1119
1182
  attribute :title
@@ -1132,24 +1195,18 @@ module Api
1132
1195
 
1133
1196
  has_many :aliased_comments, class_name: 'BookComments', relation_name: :approved_book_comments
1134
1197
 
1135
- filters :banned, :book_comments
1136
-
1137
- class << self
1138
- def apply_filter(records, filter, value, options)
1139
- context = options[:context]
1140
- current_user = context ? context[:current_user] : nil
1198
+ filters :book_comments
1199
+ filter :banned, apply: ->(records, value, options) {
1200
+ context = options[:context]
1201
+ current_user = context ? context[:current_user] : nil
1141
1202
 
1142
- case filter
1143
- when :banned
1144
- # Only book admins my filter for banned books
1145
- if current_user && current_user.book_admin
1146
- return records.where('books.banned = ?', value[0] == 'true')
1147
- end
1148
- else
1149
- return super(records, filter, value)
1150
- end
1203
+ # Only book admins my filter for banned books
1204
+ if current_user && current_user.book_admin
1205
+ records.where('books.banned = ?', value[0] == 'true')
1151
1206
  end
1207
+ }
1152
1208
 
1209
+ class << self
1153
1210
  def books
1154
1211
  Book.arel_table
1155
1212
  end
@@ -1178,7 +1235,15 @@ module Api
1178
1235
  has_one :book
1179
1236
  has_one :author, class_name: 'Person'
1180
1237
 
1181
- filters :approved, :book
1238
+ filters :book
1239
+ filter :approved, apply: ->(records, value, options) {
1240
+ context = options[:context]
1241
+ current_user = context ? context[:current_user] : nil
1242
+
1243
+ if current_user && current_user.book_admin
1244
+ records.where(approved_comments(value[0] == 'true'))
1245
+ end
1246
+ }
1182
1247
 
1183
1248
  class << self
1184
1249
  def book_comments
@@ -1189,23 +1254,6 @@ module Api
1189
1254
  book_comments[:approved].eq(approved)
1190
1255
  end
1191
1256
 
1192
- def apply_filter(records, filter, value, options)
1193
- context = options[:context]
1194
- current_user = context ? context[:current_user] : nil
1195
-
1196
- case filter
1197
- when :approved
1198
- # Only book admins my filter for unapproved comments
1199
- if current_user && current_user.book_admin
1200
- records.where(approved_comments(value[0] == 'true'))
1201
- end
1202
- else
1203
- #:nocov:
1204
- return super(records, filter, value)
1205
- #:nocov:
1206
- end
1207
- end
1208
-
1209
1257
  def records(options = {})
1210
1258
  current_user = options[:context][:current_user]
1211
1259
  _model_class.for_user(current_user)
@@ -1217,17 +1265,17 @@ end
1217
1265
 
1218
1266
  module Api
1219
1267
  module V3
1220
- PostResource = PostResource.dup
1221
- PreferencesResource = PreferencesResource.dup
1268
+ class PostResource < PostResource; end
1269
+ class PreferencesResource < PreferencesResource; end
1222
1270
  end
1223
1271
  end
1224
1272
 
1225
1273
  module Api
1226
1274
  module V4
1227
- PostResource = PostResource.dup
1228
- ExpenseEntryResource = ExpenseEntryResource.dup
1229
- IsoCurrencyResource = IsoCurrencyResource.dup
1230
-
1275
+ class PostResource < PostResource; end
1276
+ class PersonResource < PersonResource; end
1277
+ class ExpenseEntryResource < ExpenseEntryResource; end
1278
+ class IsoCurrencyResource < IsoCurrencyResource; end
1231
1279
 
1232
1280
  class BookResource < Api::V2::BookResource
1233
1281
  paginator :paged
@@ -1278,11 +1326,14 @@ module Api
1278
1326
  attributes :author_stuff
1279
1327
  end
1280
1328
 
1281
- PersonResource = PersonResource.dup
1282
- PostResource = PostResource.dup
1283
- ExpenseEntryResource = ExpenseEntryResource.dup
1284
- IsoCurrencyResource = IsoCurrencyResource.dup
1285
- EmployeeResource = EmployeeResource.dup
1329
+ class PersonResource < PersonResource; end
1330
+ class PostResource < PostResource; end
1331
+ class TagResource < TagResource; end
1332
+ class SectionResource < SectionResource; end
1333
+ class CommentResource < CommentResource; end
1334
+ class ExpenseEntryResource < ExpenseEntryResource; end
1335
+ class IsoCurrencyResource < IsoCurrencyResource; end
1336
+ class EmployeeResource < EmployeeResource; end
1286
1337
  end
1287
1338
  end
1288
1339
 
@@ -1349,10 +1400,32 @@ module Api
1349
1400
  end
1350
1401
 
1351
1402
  module V7
1352
- CustomerResource = V6::CustomerResource.dup
1353
- PurchaseOrderResource = V6::PurchaseOrderResource.dup
1354
- OrderFlagResource = V6::OrderFlagResource.dup
1355
- LineItemResource = V6::LineItemResource.dup
1403
+ class PurchaseOrderResource < V6::PurchaseOrderResource; end
1404
+ class OrderFlagResource < V6::OrderFlagResource; end
1405
+ class LineItemResource < V6::LineItemResource; end
1406
+
1407
+ class CustomerResource < V6::CustomerResource
1408
+ model_name 'Api::V7::Customer'
1409
+ attribute :name
1410
+ has_many :purchase_orders
1411
+ end
1412
+
1413
+ class ClientResource < JSONAPI::Resource
1414
+ model_name 'Api::V7::Customer'
1415
+
1416
+ attribute :name
1417
+
1418
+ has_many :purchase_orders
1419
+ end
1420
+
1421
+ class CategoryResource < CategoryResource
1422
+ attribute :name
1423
+
1424
+ # Raise exception for failure in controller
1425
+ def name
1426
+ fail "Something Exceptional Happened"
1427
+ end
1428
+ end
1356
1429
  end
1357
1430
 
1358
1431
  module V8
@@ -1392,7 +1465,10 @@ module Legacy
1392
1465
  end
1393
1466
 
1394
1467
  class FlatPostResource < JSONAPI::Resource
1395
- model_name "::Legacy::FlatPost"
1468
+ model_name "Legacy::FlatPost", add_model_hint: false
1469
+
1470
+ model_hint model: "Legacy::FlatPost", resource: FlatPostResource
1471
+
1396
1472
  attribute :title
1397
1473
  end
1398
1474