json_api_client 1.8.0 → 1.9.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +54 -0
- data/lib/json_api_client/connection.rb +3 -1
- data/lib/json_api_client/helpers/dirty.rb +5 -1
- data/lib/json_api_client/middleware/status.rb +13 -1
- data/lib/json_api_client/resource.rb +12 -4
- data/lib/json_api_client/utils.rb +1 -0
- data/lib/json_api_client/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 26efa266b2d3eb7d2b504738b19392474c832b02
|
4
|
+
data.tar.gz: 5b60463dae1806e7318298cbd58ab5ce968453ae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5830accd29e4821e85a32c0d39e650cc6603882a0022f9fe8cb633ec60c3efc030cc36d6d11d931ffd10cf38b4272ff3bac3184ca1547f81fe53b8071f92bbec
|
7
|
+
data.tar.gz: 487d5411c3f399a737b72c0ff007076f71e92ab84b93fca19a9d3e54f9b345082358e9b98340ed7a5bfdd543f994ee4bac5be37759ace8ded75d74824b177e21
|
data/README.md
CHANGED
@@ -474,6 +474,44 @@ module MyApi
|
|
474
474
|
end
|
475
475
|
```
|
476
476
|
|
477
|
+
##### Custom status handler
|
478
|
+
|
479
|
+
You can change handling of response status using `connection_options`. For example you can override 400 status handling.
|
480
|
+
By default it raises `JsonApiClient::Errors::ClientError` but you can skip exception if you want to process errors from the server.
|
481
|
+
You need to provide a `proc` which should call `throw(:handled)` default handler for this status should be skipped.
|
482
|
+
```ruby
|
483
|
+
class ApiBadRequestHandler
|
484
|
+
def self.call(_env)
|
485
|
+
# do not raise exception
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
class CustomUnauthorizedError < StandardError
|
490
|
+
attr_reader :env
|
491
|
+
|
492
|
+
def initialize(env)
|
493
|
+
@env = env
|
494
|
+
super('not authorized')
|
495
|
+
end
|
496
|
+
end
|
497
|
+
|
498
|
+
MyApi::Base.connection_options[:status_handlers] = {
|
499
|
+
400 => ApiBadRequestHandler,
|
500
|
+
401 => ->(env) { raise CustomUnauthorizedError, env }
|
501
|
+
}
|
502
|
+
|
503
|
+
module MyApi
|
504
|
+
class User < Base
|
505
|
+
# will use the customized status_handlers
|
506
|
+
end
|
507
|
+
end
|
508
|
+
|
509
|
+
user = MyApi::User.create(name: 'foo')
|
510
|
+
# server responds with { errors: [ { detail: 'bad request' } ] }
|
511
|
+
user.errors.messages # { base: ['bad request'] }
|
512
|
+
# on 401 it will raise CustomUnauthorizedError instead of JsonApiClient::Errors::NotAuthorized
|
513
|
+
```
|
514
|
+
|
477
515
|
##### Specifying an HTTP Proxy
|
478
516
|
|
479
517
|
All resources have a class method ```connection_options``` used to pass options to the JsonApiClient::Connection initializer.
|
@@ -553,6 +591,22 @@ class MyApi::Base < JsonApiClient::Resource
|
|
553
591
|
end
|
554
592
|
```
|
555
593
|
|
594
|
+
### Custom type
|
595
|
+
|
596
|
+
If your model must be named differently from classified type of resource you can easily customize it.
|
597
|
+
It will work both for defined and not defined relationships
|
598
|
+
|
599
|
+
```ruby
|
600
|
+
class MyApi::Base < JsonApiClient::Resource
|
601
|
+
resolve_custom_type 'document--files', 'File'
|
602
|
+
end
|
603
|
+
|
604
|
+
class MyApi::File < MyApi::Base
|
605
|
+
def self.resource_name
|
606
|
+
'document--files'
|
607
|
+
end
|
608
|
+
end
|
609
|
+
```
|
556
610
|
|
557
611
|
### Type Casting
|
558
612
|
|
@@ -7,10 +7,12 @@ module JsonApiClient
|
|
7
7
|
site = options.fetch(:site)
|
8
8
|
connection_options = options.slice(:proxy, :ssl, :request, :headers, :params)
|
9
9
|
adapter_options = Array(options.fetch(:adapter, Faraday.default_adapter))
|
10
|
+
status_middleware_options = {}
|
11
|
+
status_middleware_options[:custom_handlers] = options[:status_handlers] if options[:status_handlers].present?
|
10
12
|
@faraday = Faraday.new(site, connection_options) do |builder|
|
11
13
|
builder.request :json
|
12
14
|
builder.use Middleware::JsonRequest
|
13
|
-
builder.use Middleware::Status
|
15
|
+
builder.use Middleware::Status, status_middleware_options
|
14
16
|
builder.use Middleware::ParseJson
|
15
17
|
builder.adapter(*adapter_options)
|
16
18
|
end
|
@@ -18,6 +18,10 @@ module JsonApiClient
|
|
18
18
|
@changed_attributes = ActiveSupport::HashWithIndifferentAccess.new
|
19
19
|
end
|
20
20
|
|
21
|
+
def forget_change!(attr)
|
22
|
+
@changed_attributes.delete(attr.to_s)
|
23
|
+
end
|
24
|
+
|
21
25
|
def set_all_attributes_dirty
|
22
26
|
attributes.each do |k, v|
|
23
27
|
set_attribute_was(k, v)
|
@@ -68,4 +72,4 @@ module JsonApiClient
|
|
68
72
|
|
69
73
|
end
|
70
74
|
end
|
71
|
-
end
|
75
|
+
end
|
@@ -1,6 +1,11 @@
|
|
1
1
|
module JsonApiClient
|
2
2
|
module Middleware
|
3
3
|
class Status < Faraday::Middleware
|
4
|
+
def initialize(app, options)
|
5
|
+
super(app)
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
4
9
|
def call(environment)
|
5
10
|
@app.call(environment).on_complete do |env|
|
6
11
|
handle_status(env[:status], env)
|
@@ -15,9 +20,16 @@ module JsonApiClient
|
|
15
20
|
raise Errors::ConnectionError.new environment, e.to_s
|
16
21
|
end
|
17
22
|
|
18
|
-
|
23
|
+
private
|
24
|
+
|
25
|
+
def custom_handler_for(code)
|
26
|
+
@options.fetch(:custom_handlers, {})[code]
|
27
|
+
end
|
19
28
|
|
20
29
|
def handle_status(code, env)
|
30
|
+
custom_handler = custom_handler_for(code)
|
31
|
+
return custom_handler.call(env) if custom_handler.present?
|
32
|
+
|
21
33
|
case code
|
22
34
|
when 200..399
|
23
35
|
when 401
|
@@ -35,6 +35,7 @@ module JsonApiClient
|
|
35
35
|
:request_params_class,
|
36
36
|
:keep_request_params,
|
37
37
|
:search_included_in_result_set,
|
38
|
+
:custom_type_to_class,
|
38
39
|
instance_accessor: false
|
39
40
|
class_attribute :add_defaults_to_changes,
|
40
41
|
instance_writer: false
|
@@ -52,6 +53,7 @@ module JsonApiClient
|
|
52
53
|
self.keep_request_params = false
|
53
54
|
self.add_defaults_to_changes = false
|
54
55
|
self.search_included_in_result_set = false
|
56
|
+
self.custom_type_to_class = {}
|
55
57
|
|
56
58
|
#:underscored_key, :camelized_key, :dasherized_key, or custom
|
57
59
|
self.json_key_format = :underscored_key
|
@@ -63,6 +65,11 @@ module JsonApiClient
|
|
63
65
|
extend Forwardable
|
64
66
|
def_delegators :_new_scope, :where, :order, :includes, :select, :all, :paginate, :page, :with_params, :first, :find, :last
|
65
67
|
|
68
|
+
def resolve_custom_type(type_name, class_name)
|
69
|
+
classified_type = key_formatter.unformat(type_name.to_s).singularize.classify
|
70
|
+
self.custom_type_to_class = custom_type_to_class.merge(classified_type => class_name.to_s)
|
71
|
+
end
|
72
|
+
|
66
73
|
# The table name for this resource. i.e. Article -> articles, Person -> people
|
67
74
|
#
|
68
75
|
# @return [String] The table name for this resource
|
@@ -322,6 +329,7 @@ module JsonApiClient
|
|
322
329
|
self.links = self.class.linker.new(params.delete(:links) || {})
|
323
330
|
self.relationships = self.class.relationship_linker.new(self.class, params.delete(:relationships) || {})
|
324
331
|
self.attributes = self.class.default_attributes.merge params.except(*self.class.prefix_params)
|
332
|
+
self.forget_change!(:type)
|
325
333
|
self.__belongs_to_params = params.slice(*self.class.prefix_params)
|
326
334
|
|
327
335
|
setup_default_properties
|
@@ -394,7 +402,7 @@ module JsonApiClient
|
|
394
402
|
#
|
395
403
|
# @return [Hash] Representation of this object as JSONAPI object
|
396
404
|
def as_json_api(*)
|
397
|
-
attributes.slice(
|
405
|
+
attributes.slice(self.class.primary_key, :type).tap do |h|
|
398
406
|
relationships_for_serialization.tap do |r|
|
399
407
|
h[:relationships] = self.class.key_formatter.format_keys(r) unless r.empty?
|
400
408
|
end
|
@@ -403,11 +411,11 @@ module JsonApiClient
|
|
403
411
|
end
|
404
412
|
|
405
413
|
def as_json(*)
|
406
|
-
attributes.slice(
|
414
|
+
attributes.slice(self.class.primary_key, :type).tap do |h|
|
407
415
|
relationships.as_json.tap do |r|
|
408
416
|
h[:relationships] = r unless r.empty?
|
409
417
|
end
|
410
|
-
h[:attributes] = attributes.except(
|
418
|
+
h[:attributes] = attributes.except(self.class.primary_key, :type).as_json
|
411
419
|
end
|
412
420
|
end
|
413
421
|
|
@@ -504,7 +512,7 @@ module JsonApiClient
|
|
504
512
|
end
|
505
513
|
|
506
514
|
def path_attributes
|
507
|
-
_belongs_to_params.merge attributes.slice(
|
515
|
+
_belongs_to_params.merge attributes.slice( self.class.primary_key ).symbolize_keys
|
508
516
|
end
|
509
517
|
|
510
518
|
protected
|
@@ -2,6 +2,7 @@ module JsonApiClient
|
|
2
2
|
module Utils
|
3
3
|
|
4
4
|
def self.compute_type(klass, type_name)
|
5
|
+
return klass.custom_type_to_class.fetch(type_name).constantize if klass.custom_type_to_class.key?(type_name)
|
5
6
|
# If the type is prefixed with a scope operator then we assume that
|
6
7
|
# the type_name is an absolute reference.
|
7
8
|
return type_name.constantize if type_name.match(/^::/)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: json_api_client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jeff Ching
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-01-
|
11
|
+
date: 2019-01-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|