json_api_client 1.8.0 → 1.9.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|