contentful 0.1.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.
- data/.README.md.swp +0 -0
- data/.gitignore +2 -0
- data/.rspec +1 -0
- data/.travis.yml +10 -0
- data/ChangeLog.md +3 -0
- data/Gemfile +3 -0
- data/LICENSE.txt +21 -0
- data/README.md +193 -0
- data/Rakefile +30 -0
- data/contentful.gemspec +31 -0
- data/do_request.sh +5 -0
- data/doc/Contentful.html +131 -0
- data/doc/Contentful/AccessDenied.html +158 -0
- data/doc/Contentful/Array.html +346 -0
- data/doc/Contentful/Asset.html +315 -0
- data/doc/Contentful/BadRequest.html +158 -0
- data/doc/Contentful/Client.html +1407 -0
- data/doc/Contentful/ContentType.html +183 -0
- data/doc/Contentful/DynamicEntry.html +333 -0
- data/doc/Contentful/Entry.html +198 -0
- data/doc/Contentful/Error.html +413 -0
- data/doc/Contentful/Field.html +161 -0
- data/doc/Contentful/File.html +160 -0
- data/doc/Contentful/Link.html +275 -0
- data/doc/Contentful/Locale.html +161 -0
- data/doc/Contentful/NotFound.html +158 -0
- data/doc/Contentful/Request.html +669 -0
- data/doc/Contentful/Resource.html +606 -0
- data/doc/Contentful/Resource/AssetFields.html +413 -0
- data/doc/Contentful/Resource/AssetFields/ClassMethods.html +174 -0
- data/doc/Contentful/Resource/ClassMethods.html +271 -0
- data/doc/Contentful/Resource/Fields.html +398 -0
- data/doc/Contentful/Resource/Fields/ClassMethods.html +187 -0
- data/doc/Contentful/Resource/SystemProperties.html +444 -0
- data/doc/Contentful/Resource/SystemProperties/ClassMethods.html +174 -0
- data/doc/Contentful/ResourceBuilder.html +1400 -0
- data/doc/Contentful/Response.html +546 -0
- data/doc/Contentful/ServerError.html +158 -0
- data/doc/Contentful/Space.html +183 -0
- data/doc/Contentful/Support.html +198 -0
- data/doc/Contentful/Unauthorized.html +158 -0
- data/doc/Contentful/UnparsableJson.html +158 -0
- data/doc/Contentful/UnparsableResource.html +158 -0
- data/doc/_index.html +410 -0
- data/doc/class_list.html +54 -0
- data/doc/css/common.css +1 -0
- data/doc/css/full_list.css +57 -0
- data/doc/css/style.css +338 -0
- data/doc/file.README.html +214 -0
- data/doc/file_list.html +56 -0
- data/doc/frames.html +26 -0
- data/doc/index.html +214 -0
- data/doc/js/app.js +219 -0
- data/doc/js/full_list.js +178 -0
- data/doc/js/jquery.js +4 -0
- data/doc/method_list.html +533 -0
- data/doc/top-level-namespace.html +112 -0
- data/examples/custom_classes.rb +43 -0
- data/examples/dynamic_entries.rb +126 -0
- data/examples/example_queries.rb +27 -0
- data/examples/raise_errors.rb +22 -0
- data/examples/raw_mode.rb +15 -0
- data/examples/resource_mapping.rb +33 -0
- data/lib/contentful.rb +3 -0
- data/lib/contentful/array.rb +47 -0
- data/lib/contentful/asset.rb +34 -0
- data/lib/contentful/client.rb +193 -0
- data/lib/contentful/content_type.rb +16 -0
- data/lib/contentful/dynamic_entry.rb +54 -0
- data/lib/contentful/entry.rb +12 -0
- data/lib/contentful/error.rb +52 -0
- data/lib/contentful/field.rb +16 -0
- data/lib/contentful/file.rb +13 -0
- data/lib/contentful/link.rb +20 -0
- data/lib/contentful/locale.rb +12 -0
- data/lib/contentful/location.rb +12 -0
- data/lib/contentful/request.rb +37 -0
- data/lib/contentful/resource.rb +146 -0
- data/lib/contentful/resource/asset_fields.rb +50 -0
- data/lib/contentful/resource/fields.rb +39 -0
- data/lib/contentful/resource/system_properties.rb +48 -0
- data/lib/contentful/resource_builder.rb +197 -0
- data/lib/contentful/response.rb +64 -0
- data/lib/contentful/space.rb +14 -0
- data/lib/contentful/support.rb +18 -0
- data/lib/contentful/version.rb +3 -0
- data/spec/array_spec.rb +69 -0
- data/spec/asset_spec.rb +62 -0
- data/spec/auto_includes_spec.rb +12 -0
- data/spec/client_class_spec.rb +59 -0
- data/spec/client_configuration_spec.rb +197 -0
- data/spec/coercions_spec.rb +10 -0
- data/spec/content_type_spec.rb +44 -0
- data/spec/dynamic_entry_spec.rb +34 -0
- data/spec/entry_spec.rb +53 -0
- data/spec/error_class_spec.rb +60 -0
- data/spec/error_requests_spec.rb +32 -0
- data/spec/field_spec.rb +36 -0
- data/spec/file_spec.rb +28 -0
- data/spec/fixtures/json_responses/content_type.json +83 -0
- data/spec/fixtures/json_responses/not_found.json +13 -0
- data/spec/fixtures/json_responses/nyancat.json +48 -0
- data/spec/fixtures/json_responses/unparsable.json +13 -0
- data/spec/fixtures/vcr_cassettes/array.yml +288 -0
- data/spec/fixtures/vcr_cassettes/array_page_1.yml +106 -0
- data/spec/fixtures/vcr_cassettes/array_page_2.yml +73 -0
- data/spec/fixtures/vcr_cassettes/asset.yml +96 -0
- data/spec/fixtures/vcr_cassettes/bad_request.yml +76 -0
- data/spec/fixtures/vcr_cassettes/content_type.yml +147 -0
- data/spec/fixtures/vcr_cassettes/entries.yml +561 -0
- data/spec/fixtures/vcr_cassettes/entry.yml +112 -0
- data/spec/fixtures/vcr_cassettes/entry_cache.yml +288 -0
- data/spec/fixtures/vcr_cassettes/field.yml +147 -0
- data/spec/fixtures/vcr_cassettes/locale.yml +81 -0
- data/spec/fixtures/vcr_cassettes/location.yml +305 -0
- data/spec/fixtures/vcr_cassettes/not_found.yml +71 -0
- data/spec/fixtures/vcr_cassettes/nyancat.yml +112 -0
- data/spec/fixtures/vcr_cassettes/nyancat_include.yml +112 -0
- data/spec/fixtures/vcr_cassettes/reloaded_entry.yml +112 -0
- data/spec/fixtures/vcr_cassettes/space.yml +81 -0
- data/spec/fixtures/vcr_cassettes/unauthorized.yml +64 -0
- data/spec/link_spec.rb +40 -0
- data/spec/locale_spec.rb +20 -0
- data/spec/location_spec.rb +30 -0
- data/spec/request_spec.rb +48 -0
- data/spec/resource_spec.rb +52 -0
- data/spec/response_spec.rb +50 -0
- data/spec/space_spec.rb +36 -0
- data/spec/spec_helper.rb +6 -0
- data/spec/support/client.rb +6 -0
- data/spec/support/json_responses.rb +11 -0
- data/spec/support/vcr.rb +16 -0
- metadata +374 -0
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
require_relative 'resource/system_properties'
|
|
2
|
+
require 'date'
|
|
3
|
+
|
|
4
|
+
module Contentful
|
|
5
|
+
# Include this module to declare a class to be a contentful resource.
|
|
6
|
+
# This is done by the default in the existing resource classes
|
|
7
|
+
#
|
|
8
|
+
# You can define your own classes that behave like contentful resources:
|
|
9
|
+
# See examples/custom_classes.rb to see how.
|
|
10
|
+
#
|
|
11
|
+
# Take a look at examples/resource_mapping.rb on how to register them to be returned
|
|
12
|
+
# by the client by default
|
|
13
|
+
module Resource
|
|
14
|
+
COERCIONS = {
|
|
15
|
+
string: ->(v){ v.to_s },
|
|
16
|
+
integer: ->(v){ v.to_i },
|
|
17
|
+
float: ->(v){ v.to_f },
|
|
18
|
+
boolean: ->(v){ !!v },
|
|
19
|
+
date: ->(v){ DateTime.parse(v) },
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
attr_reader :properties, :request, :client
|
|
23
|
+
|
|
24
|
+
def initialize(object, request = nil, client = nil)
|
|
25
|
+
self.class.update_coercions!
|
|
26
|
+
|
|
27
|
+
@properties = extract_from_object object, :property, self.class.property_coercions.keys
|
|
28
|
+
@request = request
|
|
29
|
+
@client = client
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def inspect(info = nil)
|
|
33
|
+
properties_info = properties.empty? ? "" : " @properties=#{properties.inspect}"
|
|
34
|
+
"#<#{self.class}:#{properties_info}#{info}>"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
# Returns true for resources that behave like an array
|
|
38
|
+
def array?
|
|
39
|
+
false
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Resources that don't include SystemProperties return nil for #sys
|
|
43
|
+
def sys
|
|
44
|
+
nil
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# Resources that don't include Fields or AssetFields return nil for #fields
|
|
48
|
+
def fields
|
|
49
|
+
nil
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Issues the request that was made to fetch this response again.
|
|
53
|
+
# Only works for top-level resources
|
|
54
|
+
def reload
|
|
55
|
+
if request
|
|
56
|
+
request.get
|
|
57
|
+
else
|
|
58
|
+
false
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def extract_from_object(object, namespace, keys = nil)
|
|
66
|
+
if object
|
|
67
|
+
keys ||= object.keys
|
|
68
|
+
keys.each.with_object({}){ |name, res|
|
|
69
|
+
res[name.to_sym] = coerce_value_or_array(
|
|
70
|
+
object.is_a?(::Array) ? object : object[name.to_s],
|
|
71
|
+
self.class.public_send(:"#{namespace}_coercions")[name.to_sym],
|
|
72
|
+
)
|
|
73
|
+
}
|
|
74
|
+
else
|
|
75
|
+
{}
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def coerce_value_or_array(value, what = nil)
|
|
80
|
+
if value.is_a? ::Array
|
|
81
|
+
value.map{ |v| coerce_or_create_class(v, what) }
|
|
82
|
+
else
|
|
83
|
+
coerce_or_create_class(value, what)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def coerce_or_create_class(value, what)
|
|
88
|
+
case what
|
|
89
|
+
when Symbol
|
|
90
|
+
COERCIONS[what] ? COERCIONS[what][value] : value
|
|
91
|
+
when Class
|
|
92
|
+
what.new(value, client)
|
|
93
|
+
else
|
|
94
|
+
value
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
# Register the resources properties on class level by using the #property method
|
|
99
|
+
module ClassMethods
|
|
100
|
+
def property_coercions
|
|
101
|
+
@property_coercions ||= {}
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# Defines which properties of a resource your class expects
|
|
105
|
+
# Define them in :camelCase, they will be available as #snake_cased methods
|
|
106
|
+
#
|
|
107
|
+
# You can pass in a second "type" argument:
|
|
108
|
+
# - If it is a class, it will be initialized for the property
|
|
109
|
+
# - Symbols are looked up in the COERCION constant for a lambda that
|
|
110
|
+
# defines a type conversion to apply
|
|
111
|
+
#
|
|
112
|
+
# Note: This second argument is not meant for contentful sub-resources,
|
|
113
|
+
# but for structured objects (like locales in a space)
|
|
114
|
+
# Sub-resources are handled by the resource builder
|
|
115
|
+
def property(name, property_class = nil)
|
|
116
|
+
property_coercions[name.to_sym] = property_class
|
|
117
|
+
define_method Contentful::Support.snakify(name) do
|
|
118
|
+
properties[name.to_sym]
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
# Ensure inherited classes pick up coercions
|
|
123
|
+
def update_coercions!
|
|
124
|
+
return if @coercions_updated
|
|
125
|
+
|
|
126
|
+
if superclass.respond_to? :property_coercions
|
|
127
|
+
@property_coercions = superclass.property_coercions.dup.merge(@property_coercions || {})
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
if superclass.respond_to? :sys_coercions
|
|
131
|
+
@sys_coercions = superclass.sys_coercions.dup.merge(@sys_coercions || {})
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
if superclass.respond_to? :fields_coercions
|
|
135
|
+
@fields_coercions = superclass.fields_coercions.dup.merge(@fields_coercions || {})
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
@coercions_updated = true
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.included(base)
|
|
143
|
+
base.extend(ClassMethods)
|
|
144
|
+
end
|
|
145
|
+
end
|
|
146
|
+
end
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
require_relative '../file'
|
|
2
|
+
|
|
3
|
+
module Contentful
|
|
4
|
+
module Resource
|
|
5
|
+
# Special fields for Asset. Don't include together wit Contentful::Resource::Fields
|
|
6
|
+
#
|
|
7
|
+
# It depends on system properties being available
|
|
8
|
+
module AssetFields
|
|
9
|
+
FIELDS_COERCIONS = {
|
|
10
|
+
title: :string,
|
|
11
|
+
description: :string,
|
|
12
|
+
file: File,
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
def fields
|
|
16
|
+
@fields[locale]
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def initialize(object, *)
|
|
20
|
+
super
|
|
21
|
+
@fields = {}
|
|
22
|
+
@fields[locale] = extract_from_object object["fields"], :fields
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def inspect(info = nil)
|
|
26
|
+
if fields.empty?
|
|
27
|
+
super(info)
|
|
28
|
+
else
|
|
29
|
+
super("#{info} @fields=#{fields.inspect}")
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
module ClassMethods
|
|
34
|
+
def fields_coercions
|
|
35
|
+
FIELDS_COERCIONS
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def self.included(base)
|
|
40
|
+
base.extend(ClassMethods)
|
|
41
|
+
|
|
42
|
+
base.fields_coercions.keys.each{ |name|
|
|
43
|
+
base.send :define_method, Contentful::Support.snakify(name) do
|
|
44
|
+
fields[name.to_sym]
|
|
45
|
+
end
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
module Contentful
|
|
2
|
+
module Resource
|
|
3
|
+
# Include this module into your Resource class to enable it
|
|
4
|
+
# to deal with entry fields (but not asset fields)
|
|
5
|
+
#
|
|
6
|
+
# It depends on system properties being available
|
|
7
|
+
module Fields
|
|
8
|
+
# Returns all fields of the asset
|
|
9
|
+
def fields
|
|
10
|
+
@fields[locale]
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def initialize(object, *)
|
|
14
|
+
super
|
|
15
|
+
@fields = {}
|
|
16
|
+
@fields[locale] = extract_from_object object["fields"], :fields
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def inspect(info = nil)
|
|
20
|
+
if fields.empty?
|
|
21
|
+
super(info)
|
|
22
|
+
else
|
|
23
|
+
super("#{info} @fields=#{fields.inspect}")
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
# No coercions, since no content type available
|
|
29
|
+
def fields_coercions
|
|
30
|
+
{}
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def self.included(base)
|
|
35
|
+
base.extend(ClassMethods)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
module Contentful
|
|
2
|
+
module Resource
|
|
3
|
+
# Adds the feature to have system properties to a Resource.
|
|
4
|
+
module SystemProperties
|
|
5
|
+
SYS_COERCIONS = {
|
|
6
|
+
type: :string,
|
|
7
|
+
id: :string,
|
|
8
|
+
space: nil,
|
|
9
|
+
contentType: nil,
|
|
10
|
+
linkType: :string,
|
|
11
|
+
revision: :integer,
|
|
12
|
+
createdAt: :date,
|
|
13
|
+
updatedAt: :date,
|
|
14
|
+
locale: :string,
|
|
15
|
+
}
|
|
16
|
+
attr_reader :sys
|
|
17
|
+
|
|
18
|
+
def initialize(object, *)
|
|
19
|
+
super
|
|
20
|
+
@sys = extract_from_object object["sys"], :sys
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def inspect(info = nil)
|
|
24
|
+
if sys.empty?
|
|
25
|
+
super(info)
|
|
26
|
+
else
|
|
27
|
+
super("#{info} @sys=#{sys.inspect}")
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
module ClassMethods
|
|
32
|
+
def sys_coercions
|
|
33
|
+
SYS_COERCIONS
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def self.included(base)
|
|
38
|
+
base.extend(ClassMethods)
|
|
39
|
+
|
|
40
|
+
base.sys_coercions.keys.each{ |name|
|
|
41
|
+
base.send :define_method, Contentful::Support.snakify(name) do
|
|
42
|
+
sys[name.to_sym]
|
|
43
|
+
end
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
require_relative 'error'
|
|
2
|
+
require_relative 'resource'
|
|
3
|
+
require_relative 'space'
|
|
4
|
+
require_relative 'content_type'
|
|
5
|
+
require_relative 'entry'
|
|
6
|
+
require_relative 'dynamic_entry'
|
|
7
|
+
require_relative 'asset'
|
|
8
|
+
require_relative 'array'
|
|
9
|
+
require_relative 'link'
|
|
10
|
+
|
|
11
|
+
module Contentful
|
|
12
|
+
# Transforms a Contentful::Response into a Contentful::Resource or a Contentful::Error
|
|
13
|
+
# See example/resource_mapping.rb for avanced usage
|
|
14
|
+
class ResourceBuilder
|
|
15
|
+
DEFAULT_RESOURCE_MAPPING = {
|
|
16
|
+
'Space' => Space,
|
|
17
|
+
'ContentType' => ContentType,
|
|
18
|
+
'Entry' => :try_dynamic_entry,
|
|
19
|
+
'Asset' => Asset,
|
|
20
|
+
'Array' => Array,
|
|
21
|
+
'Link' => Link,
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
attr_reader :client, :response, :resource_mapping
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def initialize(client, response, resource_mapping = {})
|
|
28
|
+
@response = response
|
|
29
|
+
@client = client
|
|
30
|
+
@included_resources = {}
|
|
31
|
+
@resource_mapping = default_resource_mapping.merge(resource_mapping)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# Starts the parsing process.
|
|
35
|
+
# Either returns an Error, or the parsed Resource
|
|
36
|
+
def run
|
|
37
|
+
case response.status
|
|
38
|
+
when :contentful_error
|
|
39
|
+
Error[response.raw.response.status].new(response)
|
|
40
|
+
when :unparsable_json
|
|
41
|
+
UnparsableJson.new(response)
|
|
42
|
+
when :not_contentful
|
|
43
|
+
Error.new(response)
|
|
44
|
+
else
|
|
45
|
+
begin
|
|
46
|
+
create_all_resources!
|
|
47
|
+
rescue UnparsableResource => error
|
|
48
|
+
error
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
# PARSING MECHANISM
|
|
54
|
+
# - raise error if response not valid
|
|
55
|
+
# - look for included objects and parse them to resources
|
|
56
|
+
# - parse main object to resource
|
|
57
|
+
# - replace links in included resources with included resources
|
|
58
|
+
# - replace links in main resource with included resources
|
|
59
|
+
# - return main resource
|
|
60
|
+
def create_all_resources!
|
|
61
|
+
create_included_resources! response.object["includes"]
|
|
62
|
+
res = create_resource(response.object)
|
|
63
|
+
|
|
64
|
+
unless @included_resources.empty?
|
|
65
|
+
replace_links_in_included_resources_with_included_resources
|
|
66
|
+
replace_links_with_included_resources(res)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
res
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
# Creates a single resource from the
|
|
73
|
+
def create_resource(object)
|
|
74
|
+
res = detect_resource_class(object).new(object, response.request, client)
|
|
75
|
+
replace_children res, object
|
|
76
|
+
replace_children_array(res, :items) if res.array?
|
|
77
|
+
|
|
78
|
+
res
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
# When using Dynamic Entry Mode: Automatically converts Entry to DynamicEntry
|
|
82
|
+
def try_dynamic_entry(object)
|
|
83
|
+
get_dynamic_entry(object) || Entry
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Finds the proper DynamicEntry class for an entry
|
|
87
|
+
def get_dynamic_entry(object)
|
|
88
|
+
if id = object["sys"] &&
|
|
89
|
+
object["sys"]["contentType"] &&
|
|
90
|
+
object["sys"]["contentType"]["sys"] &&
|
|
91
|
+
object["sys"]["contentType"]["sys"]["id"]
|
|
92
|
+
client.dynamic_entry_cache[id.to_sym]
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Uses the resource mapping to find the proper Resource class to initialize
|
|
97
|
+
# for this Response object type
|
|
98
|
+
#
|
|
99
|
+
# The mapping value can be a
|
|
100
|
+
# - Class
|
|
101
|
+
# - Proc: Will be called, expected to return the proper Class
|
|
102
|
+
# - Symbol: Will be called as method of the ResourceBuilder itself
|
|
103
|
+
def detect_resource_class(object)
|
|
104
|
+
type = object["sys"] && object["sys"]["type"]
|
|
105
|
+
case res_class = resource_mapping[type]
|
|
106
|
+
when Symbol
|
|
107
|
+
public_send(res_class, object)
|
|
108
|
+
when Proc
|
|
109
|
+
res_class[object]
|
|
110
|
+
when nil
|
|
111
|
+
raise UnsparsableResource.new(response)
|
|
112
|
+
else
|
|
113
|
+
res_class
|
|
114
|
+
end
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
# The default mapping for #detect_resource_class
|
|
118
|
+
def default_resource_mapping
|
|
119
|
+
DEFAULT_RESOURCE_MAPPING
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
private
|
|
124
|
+
|
|
125
|
+
def detect_child_objects(object)
|
|
126
|
+
if object.is_a?(Hash)
|
|
127
|
+
object.select{ |k,v| v.is_a?(Hash) && v.has_key?("sys") }
|
|
128
|
+
else
|
|
129
|
+
{}
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def replace_children(res, object)
|
|
134
|
+
object.each{ |name, potential_objects|
|
|
135
|
+
detect_child_objects(potential_objects).each{ |child_name, child_object|
|
|
136
|
+
res.public_send(name)[child_name.to_sym] = create_resource(child_object)
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def replace_children_array(res, array_field)
|
|
142
|
+
items = res.public_send(array_field)
|
|
143
|
+
items.map!{ |resource_object| create_resource(resource_object) }
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def create_included_resources!(included_objects)
|
|
147
|
+
if included_objects
|
|
148
|
+
included_objects.each{ |type, objects|
|
|
149
|
+
@included_resources[type] = Hash[
|
|
150
|
+
objects.map{ |object|
|
|
151
|
+
res = create_resource(object)
|
|
152
|
+
[res.id, res]
|
|
153
|
+
}
|
|
154
|
+
]
|
|
155
|
+
}
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def replace_links_with_included_resources(res)
|
|
160
|
+
[:properties, :sys, :fields].each{ |_what|
|
|
161
|
+
if what = res.public_send(_what)
|
|
162
|
+
what.each{ |name, child_res|
|
|
163
|
+
replace_link_or_check_recursively child_res, what, name, res
|
|
164
|
+
}
|
|
165
|
+
end
|
|
166
|
+
}
|
|
167
|
+
if res.array?
|
|
168
|
+
res.each.with_index{ |child_res, index|
|
|
169
|
+
replace_link_or_check_recursively child_res, res.items, index, child_res
|
|
170
|
+
}
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def replace_link_or_check_recursively(res, what, name, resource_to_replace)
|
|
175
|
+
if res.is_a? Link
|
|
176
|
+
maybe_replace_link(res, what, name)
|
|
177
|
+
elsif res.is_a?(Resource) && res.sys
|
|
178
|
+
replace_links_with_included_resources(resource_to_replace)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
def replace_links_in_included_resources_with_included_resources
|
|
183
|
+
@included_resources.each{ |_, for_type|
|
|
184
|
+
for_type.each{ |_, res|
|
|
185
|
+
replace_links_with_included_resources(res)
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def maybe_replace_link(resource, parent, index)
|
|
191
|
+
if @included_resources[resource.link_type] &&
|
|
192
|
+
@included_resources[resource.link_type].has_key?(resource.id)
|
|
193
|
+
parent[index] = @included_resources[resource.link_type][resource.id]
|
|
194
|
+
end
|
|
195
|
+
end
|
|
196
|
+
end
|
|
197
|
+
end
|