Skip to content

Commit 2081d23

Browse files
committed
resolving diff with upstream
2 parents 96746b5 + 1f6879d commit 2081d23

File tree

12 files changed

+209
-52
lines changed

12 files changed

+209
-52
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
## Unreleased
44

5+
- [#311](https://githup.com/JsonApiClient/json_api_client/pull/311) - Raise JsonApiClient::Errors::ClientError for unhandled 4xx responses
6+
57
## v1.6.1
68

79
- [#297](https://githup.com/JsonApiClient/json_api_client/pull/297) - Fix test_helper

lib/json_api_client/associations/belongs_to.rb

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,6 @@
11
module JsonApiClient
22
module Associations
33
module BelongsTo
4-
extend ActiveSupport::Concern
5-
6-
module ClassMethods
7-
def belongs_to(attr_name, options = {})
8-
# self.associations = self.associations + [HasOne::Association.new(attr_name, self, options)]
9-
self.associations += [BelongsTo::Association.new(attr_name, self, options)]
10-
end
11-
end
12-
134
class Association < BaseAssociation
145
include Helpers::URI
156
def param

lib/json_api_client/associations/has_many.rb

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
module JsonApiClient
22
module Associations
33
module HasMany
4-
extend ActiveSupport::Concern
5-
6-
module ClassMethods
7-
def has_many(attr_name, options = {})
8-
self.associations = self.associations + [HasMany::Association.new(attr_name, self, options)]
9-
end
10-
end
11-
124
class Association < BaseAssociation
135
end
146
end

lib/json_api_client/associations/has_one.rb

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,6 @@
11
module JsonApiClient
22
module Associations
33
module HasOne
4-
extend ActiveSupport::Concern
5-
6-
module ClassMethods
7-
def has_one(attr_name, options = {})
8-
self.associations += [HasOne::Association.new(attr_name, self, options)]
9-
end
10-
end
11-
124
class Association < BaseAssociation
135
def from_result_set(result_set)
146
result_set.first

lib/json_api_client/helpers.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,5 +4,6 @@ module Helpers
44
autoload :Dirty, 'json_api_client/helpers/dirty'
55
autoload :DynamicAttributes, 'json_api_client/helpers/dynamic_attributes'
66
autoload :URI, 'json_api_client/helpers/uri'
7+
autoload :Associatable, 'json_api_client/helpers/associatable'
78
end
89
end
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
module JsonApiClient
2+
module Helpers
3+
module Associatable
4+
extend ActiveSupport::Concern
5+
6+
included do
7+
class_attribute :associations, instance_accessor: false
8+
self.associations = []
9+
attr_accessor :__cached_associations
10+
end
11+
12+
module ClassMethods
13+
def _define_association(attr_name, association_klass, options = {})
14+
attr_name = attr_name.to_sym
15+
association = association_klass.new(attr_name, self, options)
16+
self.associations += [association]
17+
18+
define_method(attr_name) do
19+
_cached_relationship(attr_name) do
20+
relationship_definition = relationship_definition_for(attr_name)
21+
return unless relationship_definition
22+
relationship_data_for(attr_name, relationship_definition)
23+
end
24+
end
25+
26+
define_method("#{attr_name}=") do |value|
27+
_clear_cached_relationship(attr_name)
28+
relationships.public_send("#{attr_name}=", value)
29+
end
30+
end
31+
32+
def belongs_to(attr_name, options = {})
33+
_define_association(attr_name, JsonApiClient::Associations::BelongsTo::Association, options)
34+
end
35+
36+
def has_many(attr_name, options = {})
37+
_define_association(attr_name, JsonApiClient::Associations::HasMany::Association, options)
38+
end
39+
40+
def has_one(attr_name, options = {})
41+
_define_association(attr_name, JsonApiClient::Associations::HasOne::Association, options)
42+
end
43+
end
44+
45+
def _cached_associations
46+
self.__cached_associations ||= {}
47+
end
48+
49+
def _clear_cached_relationships
50+
self.__cached_associations = {}
51+
end
52+
53+
def _clear_cached_relationship(attr_name)
54+
_cached_associations.delete(attr_name)
55+
end
56+
57+
def _cached_relationship(attr_name)
58+
return _cached_associations[attr_name] if _cached_associations.has_key?(attr_name)
59+
_cached_associations[attr_name] = yield
60+
end
61+
62+
end
63+
end
64+
end

lib/json_api_client/helpers/dynamic_attributes.rb

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,7 @@ def has_attribute?(attr_name)
3939

4040
def method_missing(method, *args, &block)
4141
if has_attribute?(method)
42-
self.class.class_eval do
43-
define_method(method) do
44-
attributes[method]
45-
end
46-
end
47-
return send(method)
42+
return attributes[method]
4843
end
4944

5045
normalized_method = safe_key_formatter.unformat(method.to_s)

lib/json_api_client/middleware/status.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def handle_status(code, env)
2929
when 409
3030
raise Errors::Conflict, env
3131
when 400..499
32-
# some other error
32+
raise Errors::ClientError, env
3333
when 500..599
3434
raise Errors::ServerError, env
3535
else

lib/json_api_client/resource.rb

Lines changed: 33 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ class Resource
1212

1313
include Helpers::DynamicAttributes
1414
include Helpers::Dirty
15+
include Helpers::Associatable
1516

1617
attr_accessor :last_result_set,
1718
:links,
@@ -29,7 +30,6 @@ class Resource
2930
:relationship_linker,
3031
:read_only_attributes,
3132
:requestor_class,
32-
:associations,
3333
:json_key_format,
3434
:route_format,
3535
:request_params_class,
@@ -47,7 +47,6 @@ class Resource
4747
self.relationship_linker = Relationships::Relations
4848
self.read_only_attributes = [:id, :type, :links, :meta, :relationships]
4949
self.requestor_class = Query::Requestor
50-
self.associations = []
5150
self.request_params_class = RequestParams
5251
self.keep_request_params = false
5352
self.add_defaults_to_changes = false
@@ -58,10 +57,6 @@ class Resource
5857
#:underscored_route, :camelized_route, :dasherized_route, or custom
5958
self.route_format = :underscored_route
6059

61-
include Associations::BelongsTo
62-
include Associations::HasMany
63-
include Associations::HasOne
64-
6560
class << self
6661
extend Forwardable
6762
def_delegators :_new_scope, :where, :order, :includes, :select, :all, :paginate, :page, :with_params, :first, :find, :last
@@ -253,6 +248,12 @@ def member_endpoint(name, options = {})
253248
# @option options [Symbol] :default The default value for the property
254249
def property(name, options = {})
255250
schema.add(name, options)
251+
define_method(name) do
252+
attributes[name]
253+
end
254+
define_method("#{name}=") do |value|
255+
set_attribute(name, value)
256+
end
256257
end
257258

258259
# Declare multiple properties with the same optional options
@@ -430,8 +431,10 @@ def save
430431
self.attributes = updated.attributes
431432
self.links.attributes = updated.links.attributes
432433
self.relationships.attributes = updated.relationships.attributes
434+
self.relationships.last_result_set = last_result_set
433435
clear_changes_information
434436
self.relationships.clear_changes_information
437+
_clear_cached_relationships
435438
end
436439
true
437440
end
@@ -447,6 +450,9 @@ def destroy
447450
false
448451
else
449452
self.attributes.clear
453+
self.relationships.attributes.clear
454+
self.relationships.last_result_set = nil
455+
_clear_cached_relationships
450456
true
451457
end
452458
end
@@ -491,27 +497,36 @@ def setup_default_properties
491497
end
492498
end
493499

494-
def method_missing(method, *args)
495-
association = association_for(method)
496-
497-
return super unless association || (relationships && relationships.has_attribute?(method))
500+
def relationship_definition_for(name)
501+
relationships[name] if relationships && relationships.has_attribute?(name)
502+
end
498503

499-
return nil unless relationship_definitions = relationships[method]
504+
def included_data_for(name, relationship_definition)
505+
last_result_set.included.data_for(name, relationship_definition)
506+
end
500507

508+
def relationship_data_for(name, relationship_definition)
501509
# look in included data
502-
if relationship_definitions.key?("data")
503-
return last_result_set.included.data_for(method, relationship_definitions)
510+
if relationship_definition.key?("data")
511+
return included_data_for(name, relationship_definition)
504512
end
505513

506-
if association = association_for(method)
507-
# look for a defined relationship url
508-
if relationship_definitions["links"] && url = relationship_definitions["links"]["related"]
509-
return association.data(url)
510-
end
514+
url = relationship_definition["links"]["related"]
515+
if relationship_definition["links"] && url
516+
return association_for(name).data(url)
511517
end
518+
512519
nil
513520
end
514521

522+
def method_missing(method, *args)
523+
relationship_definition = relationship_definition_for(method)
524+
525+
return super unless relationship_definition
526+
527+
relationship_data_for(method, relationship_definition)
528+
end
529+
515530
def respond_to_missing?(symbol, include_all = false)
516531
return true if relationships && relationships.has_attribute?(symbol)
517532
return true if association_for(symbol)

test/unit/resource_test.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ def test_formatted_key_accessors
8686
def test_associations_as_params
8787
article = Article.new(foo: 'bar', 'author' => {'type' => 'authors', 'id' => 1})
8888
assert_equal(article.foo, 'bar')
89-
assert_equal(article.attributes['author']['type'], 'authors')
90-
assert_equal(article.attributes['author']['id'], 1)
89+
assert_equal({'type' => 'authors', 'id' => 1}, article.relationships.author)
90+
assert article.relationships.attribute_changed?(:author)
9191
end
9292

9393
def test_default_params_overrideable

test/unit/status_test.rb

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,17 @@ def test_server_responding_with_404_status_meta
5656
end
5757
end
5858

59+
def test_server_responding_with_408_status
60+
stub_request(:get, "http://example.com/users/1")
61+
.to_return(headers: {content_type: "application/vnd.api+json"}, body: {
62+
meta: {
63+
status: 408,
64+
message: "Request timeout"
65+
}
66+
}.to_json)
67+
68+
assert_raises JsonApiClient::Errors::ClientError do
69+
User.find(1)
70+
end
71+
end
5972
end

0 commit comments

Comments
 (0)