contentful 1.2.2 → 2.0.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.
Files changed (78) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +21 -0
  3. data/LICENSE.txt +1 -0
  4. data/README.md +8 -0
  5. data/contentful.gemspec +2 -1
  6. data/examples/custom_classes.rb +23 -26
  7. data/examples/raise_errors.rb +2 -2
  8. data/lib/contentful.rb +0 -1
  9. data/lib/contentful/array.rb +27 -19
  10. data/lib/contentful/array_like.rb +51 -0
  11. data/lib/contentful/asset.rb +43 -11
  12. data/lib/contentful/base_resource.rb +87 -0
  13. data/lib/contentful/client.rb +43 -34
  14. data/lib/contentful/coercions.rb +116 -0
  15. data/lib/contentful/content_type.rb +23 -8
  16. data/lib/contentful/content_type_cache.rb +26 -0
  17. data/lib/contentful/deleted_asset.rb +2 -5
  18. data/lib/contentful/deleted_entry.rb +2 -5
  19. data/lib/contentful/entry.rb +55 -33
  20. data/lib/contentful/error.rb +1 -1
  21. data/lib/contentful/field.rb +37 -9
  22. data/lib/contentful/fields_resource.rb +115 -0
  23. data/lib/contentful/file.rb +7 -8
  24. data/lib/contentful/link.rb +3 -6
  25. data/lib/contentful/locale.rb +6 -6
  26. data/lib/contentful/location.rb +7 -5
  27. data/lib/contentful/resource_builder.rb +72 -226
  28. data/lib/contentful/space.rb +16 -6
  29. data/lib/contentful/support.rb +41 -3
  30. data/lib/contentful/sync_page.rb +17 -10
  31. data/lib/contentful/version.rb +1 -1
  32. data/spec/array_spec.rb +4 -8
  33. data/spec/client_class_spec.rb +12 -23
  34. data/spec/client_configuration_spec.rb +13 -23
  35. data/spec/content_type_spec.rb +0 -5
  36. data/spec/entry_spec.rb +130 -125
  37. data/spec/error_requests_spec.rb +1 -1
  38. data/spec/field_spec.rb +0 -5
  39. data/spec/file_spec.rb +0 -5
  40. data/spec/fixtures/vcr_cassettes/entry.yml +54 -64
  41. data/spec/fixtures/vcr_cassettes/entry/include_resolution.yml +101 -0
  42. data/spec/fixtures/vcr_cassettes/entry/marshall.yml +227 -251
  43. data/spec/fixtures/vcr_cassettes/entry/raw.yml +88 -124
  44. data/spec/fixtures/vcr_cassettes/entry_locales.yml +56 -74
  45. data/spec/fixtures/vcr_cassettes/human.yml +63 -40
  46. data/spec/fixtures/vcr_cassettes/location.yml +99 -211
  47. data/spec/fixtures/vcr_cassettes/multi_locale_array_reference.yml +12 -16
  48. data/spec/fixtures/vcr_cassettes/not_found.yml +26 -21
  49. data/spec/fixtures/vcr_cassettes/nyancat.yml +53 -63
  50. data/spec/fixtures/vcr_cassettes/ratelimit.yml +1 -1
  51. data/spec/fixtures/vcr_cassettes/reloaded_entry.yml +54 -64
  52. data/spec/fixtures/vcr_cassettes/unauthorized.yml +1 -1
  53. data/spec/fixtures/vcr_cassettes/unavailable.yml +27 -15
  54. data/spec/link_spec.rb +3 -2
  55. data/spec/locale_spec.rb +0 -5
  56. data/spec/location_spec.rb +1 -6
  57. data/spec/request_spec.rb +3 -2
  58. data/spec/resource_building_spec.rb +10 -7
  59. data/spec/response_spec.rb +1 -1
  60. data/spec/space_spec.rb +0 -5
  61. data/spec/spec_helper.rb +3 -0
  62. data/spec/support/json_responses.rb +3 -3
  63. data/spec/sync_page_spec.rb +1 -6
  64. data/spec/sync_spec.rb +11 -7
  65. metadata +69 -20
  66. data/examples/dynamic_entries.rb +0 -124
  67. data/examples/resource_mapping.rb +0 -32
  68. data/lib/contentful/constants.rb +0 -504
  69. data/lib/contentful/dynamic_entry.rb +0 -57
  70. data/lib/contentful/resource.rb +0 -239
  71. data/lib/contentful/resource/array_like.rb +0 -39
  72. data/lib/contentful/resource/asset_fields.rb +0 -58
  73. data/lib/contentful/resource/custom_resource.rb +0 -29
  74. data/lib/contentful/resource/fields.rb +0 -73
  75. data/lib/contentful/resource/system_properties.rb +0 -55
  76. data/spec/coercions_spec.rb +0 -23
  77. data/spec/dynamic_entry_spec.rb +0 -75
  78. data/spec/resource_spec.rb +0 -79
@@ -58,5 +58,5 @@ module Contentful
58
58
  class UnparsableJson < Error; end
59
59
 
60
60
  # Raised when response is not parsable as a Contentful::Resource
61
- class UnparsableResource < Error; end
61
+ class UnparsableResource < StandardError; end
62
62
  end
@@ -1,17 +1,45 @@
1
- require_relative 'resource'
1
+ require_relative 'location'
2
+ require_relative 'coercions'
2
3
 
3
4
  module Contentful
4
5
  # A ContentType's field schema
5
6
  # See https://www.contentful.com/developers/documentation/content-management-api/#resources-content-types-fields
6
7
  class Field
7
- include Contentful::Resource
8
+ # Coercions from Contentful Types to Ruby native types
9
+ KNOWN_TYPES = {
10
+ 'String' => StringCoercion,
11
+ 'Text' => TextCoercion,
12
+ 'Symbol' => SymbolCoercion,
13
+ 'Integer' => IntegerCoercion,
14
+ 'Float' => FloatCoercion,
15
+ 'Boolean' => BooleanCoercion,
16
+ 'Date' => DateCoercion,
17
+ 'Location' => LocationCoercion,
18
+ 'Object' => ObjectCoercion,
19
+ 'Array' => ArrayCoercion,
20
+ 'Link' => LinkCoercion
21
+ }
8
22
 
9
- property :id, :string
10
- property :name, :string
11
- property :type, :string
12
- property :linkType, :string
13
- property :items, Field
14
- property :required, :boolean
15
- property :localized, :boolean
23
+ attr_reader :raw, :id, :name, :type, :link_type, :items, :required, :localized
24
+
25
+ def initialize(json)
26
+ @raw = json
27
+ @id = json.fetch('id', nil)
28
+ @name = json.fetch('name', nil)
29
+ @type = json.fetch('type', nil)
30
+ @link_type = json.fetch('linkType', nil)
31
+ @items = json.key?('items') ? Field.new(json.fetch('items', {})) : nil
32
+ @required = json.fetch('required', false)
33
+ @localized = json.fetch('localized', false)
34
+ end
35
+
36
+ # Coerces value to proper type
37
+ def coerce(value)
38
+ return value if type.nil?
39
+
40
+ options = {}
41
+ options[:coercion_class] = KNOWN_TYPES[items.type] unless items.nil?
42
+ KNOWN_TYPES[type].new(value, options).coerce
43
+ end
16
44
  end
17
45
  end
@@ -0,0 +1,115 @@
1
+ require_relative 'support'
2
+ require_relative 'base_resource'
3
+
4
+ module Contentful
5
+ # Base definition of a Contentful Resource containing Field properties
6
+ class FieldsResource < BaseResource
7
+ def initialize(item, _configuration, localized = false, includes = [], *)
8
+ super
9
+
10
+ @fields = hydrate_fields(localized, includes)
11
+
12
+ define_fields_methods!
13
+ end
14
+
15
+ # Returns all fields of the asset
16
+ #
17
+ # @return [Hash] fields for Resource on selected locale
18
+ def fields(wanted_locale = nil)
19
+ wanted_locale = internal_resource_locale if wanted_locale.nil?
20
+ @fields.fetch(wanted_locale.to_s, {})
21
+ end
22
+
23
+ # Returns all fields of the asset with locales nested by field
24
+ #
25
+ # @return [Hash] fields for Resource grouped by field name
26
+ def fields_with_locales
27
+ remapped_fields = {}
28
+ locales.each do |locale|
29
+ fields(locale).each do |name, value|
30
+ remapped_fields[name] ||= {}
31
+ remapped_fields[name][locale.to_sym] = value
32
+ end
33
+ end
34
+
35
+ remapped_fields
36
+ end
37
+
38
+ # Provides a list of the available locales for a Resource
39
+ def locales
40
+ @fields.keys
41
+ end
42
+
43
+ # @private
44
+ def marshal_dump
45
+ raw_with_links
46
+ end
47
+
48
+ # @private
49
+ def marshal_load(raw_object)
50
+ super(raw_object)
51
+ localized = raw_object.fetch('fields', {}).all? { |_, v| v.is_a?(Hash) }
52
+ @fields = hydrate_fields(localized, [])
53
+ define_fields_methods!
54
+ end
55
+
56
+ # @private
57
+ def raw_with_links
58
+ links = fields.keys.select { |property| known_link?(property) }
59
+ processed_raw = raw.clone
60
+ raw['fields'].each do |k, v|
61
+ processed_raw['fields'][k] = links.include?(Support.snakify(k).to_sym) ? send(Support.snakify(k)) : v
62
+ end
63
+
64
+ processed_raw
65
+ end
66
+
67
+ private
68
+
69
+ def define_fields_methods!
70
+ fields.each do |k, v|
71
+ define_singleton_method k do
72
+ v
73
+ end
74
+ end
75
+ end
76
+
77
+ def hydrate_fields(localized, includes)
78
+ return {} unless raw.key?('fields')
79
+
80
+ locale = internal_resource_locale
81
+ result = { locale => {} }
82
+
83
+ if localized
84
+ raw['fields'].each do |name, locales|
85
+ locales.each do |loc, value|
86
+ result[loc] ||= {}
87
+ result[loc][Support.snakify(name).to_sym] = coerce(
88
+ Support.snakify(name),
89
+ value,
90
+ localized,
91
+ includes
92
+ )
93
+ end
94
+ end
95
+ else
96
+ raw['fields'].each do |name, value|
97
+ result[locale][Support.snakify(name).to_sym] = coerce(
98
+ Support.snakify(name),
99
+ value,
100
+ localized,
101
+ includes
102
+ )
103
+ end
104
+ end
105
+
106
+ result
107
+ end
108
+
109
+ protected
110
+
111
+ def coerce(_field_id, value, _localized, _includes)
112
+ value
113
+ end
114
+ end
115
+ end
@@ -1,13 +1,12 @@
1
- require_relative 'resource'
2
-
3
1
  module Contentful
4
2
  # An Assets's file info
5
3
  class File
6
- include Contentful::Resource
7
-
8
- property :fileName, :string
9
- property :contentType, :string
10
- property :details
11
- property :url, :string
4
+ attr_reader :file_name, :content_type, :details, :url
5
+ def initialize(json)
6
+ @file_name = json.fetch('fileName', nil)
7
+ @content_type = json.fetch('contentType', nil)
8
+ @details = json.fetch('details', nil)
9
+ @url = json.fetch('url', nil)
10
+ end
12
11
  end
13
12
  end
@@ -1,15 +1,12 @@
1
- require_relative 'resource'
1
+ require_relative 'base_resource'
2
2
 
3
3
  module Contentful
4
4
  # Resource Class for Links
5
5
  # https://www.contentful.com/developers/documentation/content-delivery-api/#links
6
- class Link
7
- include Contentful::Resource
8
- include Contentful::Resource::SystemProperties
9
-
6
+ class Link < BaseResource
10
7
  # Queries contentful for the Resource the Link is refering to
11
8
  # Takes an optional query hash
12
- def resolve(query = {})
9
+ def resolve(client, query = {})
13
10
  id_and_query = [(id unless link_type == 'Space')].compact + [query]
14
11
  client.public_send(
15
12
  Contentful::Support.snakify(link_type).to_sym,
@@ -1,13 +1,13 @@
1
- require_relative 'resource'
2
-
3
1
  module Contentful
4
2
  # A Locale definition as included in Space
5
3
  # Read more about Localization at https://www.contentful.com/developers/documentation/content-delivery-api/#i18n
6
4
  class Locale
7
- include Contentful::Resource
5
+ attr_reader :code, :name, :default
8
6
 
9
- property :code, :string
10
- property :name, :string
11
- property :default, :boolean
7
+ def initialize(json)
8
+ @code = json.fetch('code', nil)
9
+ @name = json.fetch('name', nil)
10
+ @default = json.fetch('default', false)
11
+ end
12
12
  end
13
13
  end
@@ -1,12 +1,14 @@
1
- require_relative 'resource'
2
-
3
1
  module Contentful
4
2
  # Location Field Type
5
3
  # You can directly query for them: https://www.contentful.com/developers/documentation/content-delivery-api/#search-filter-geo
6
4
  class Location
7
- include Contentful::Resource
5
+ attr_reader :lat, :lon
6
+ alias latitude lat
7
+ alias longitude lon
8
8
 
9
- property :lat, :float
10
- property :lon, :float
9
+ def initialize(json)
10
+ @lat = json.fetch('lat', nil)
11
+ @lon = json.fetch('lon', nil)
12
+ end
11
13
  end
12
14
  end
@@ -1,9 +1,7 @@
1
1
  require_relative 'error'
2
- require_relative 'resource'
3
2
  require_relative 'space'
4
3
  require_relative 'content_type'
5
4
  require_relative 'entry'
6
- require_relative 'dynamic_entry'
7
5
  require_relative 'asset'
8
6
  require_relative 'array'
9
7
  require_relative 'link'
@@ -19,9 +17,9 @@ module Contentful
19
17
  DEFAULT_RESOURCE_MAPPING = {
20
18
  'Space' => Space,
21
19
  'ContentType' => ContentType,
22
- 'Entry' => :find_entry_class,
20
+ 'Entry' => Entry,
23
21
  'Asset' => Asset,
24
- 'Array' => :array_or_sync_page,
22
+ 'Array' => Array,
25
23
  'Link' => Link,
26
24
  'DeletedEntry' => DeletedEntry,
27
25
  'DeletedAsset' => DeletedAsset
@@ -30,271 +28,119 @@ module Contentful
30
28
  # @see _ README for more information on Entry Mapping
31
29
  DEFAULT_ENTRY_MAPPING = {}
32
30
 
33
- attr_reader :client, :response, :resource_mapping, :entry_mapping, :resource
31
+ attr_reader :json, :default_locale, :endpoint, :depth, :localized, :resource_mapping, :entry_mapping, :resource
34
32
 
35
- def initialize(client,
36
- response,
37
- resource_mapping = {},
38
- entry_mapping = {},
39
- default_locale = Contentful::Client::DEFAULT_CONFIGURATION[:default_locale])
40
- @response = response
41
- @client = client
42
- @included_resources = {}
43
- @known_resources = Hash.new { |h, k| h[k] = {} }
44
- @default_locale = default_locale
45
- @resource_mapping = default_resource_mapping.merge(resource_mapping)
46
- @entry_mapping = default_entry_mapping.merge(entry_mapping)
33
+ def initialize(json, configuration = {}, localized = false, depth = 0, endpoint = nil)
34
+ @json = json
35
+ @default_locale = configuration.fetch(:default_locale, ::Contentful::Client::DEFAULT_CONFIGURATION[:default_locale])
36
+ @resource_mapping = default_resource_mapping.merge(configuration.fetch(:resource_mapping, {}))
37
+ @entry_mapping = default_entry_mapping.merge(configuration.fetch(:entry_mapping, {}))
38
+ @includes_for_single = configuration.fetch(:includes_for_single, [])
39
+ @localized = localized
40
+ @depth = depth
41
+ @endpoint = endpoint
42
+ @configuration = configuration
47
43
  end
48
44
 
49
45
  # Starts the parsing process.
46
+ #
50
47
  # @return [Contentful::Resource, Contentful::Error]
51
48
  def run
52
- if response.status == :ok
53
- create_all_resources!
54
- else
55
- response.object
56
- end
57
- end
58
-
59
- # PARSING MECHANISM
60
- # - raise error if response not valid
61
- # - look for included objects and parse them to resources
62
- # - parse main object to resource
63
- # - replace links in included resources with known resources
64
- # - replace links in main resource with known resources
65
- # - return main resource
66
- def create_all_resources!
67
- create_included_resources! response.object['includes']
68
- @resource = create_resource(response.object)
69
-
70
- unless @included_resources.empty?
71
- replace_links_in_included_resources_with_known_resources
72
- end
73
-
74
- replace_links_with_known_resources @resource
75
-
76
- @resource
49
+ return build_array if array?
50
+ build_single
77
51
  rescue UnparsableResource => error
78
52
  error
79
53
  end
80
54
 
81
- # Creates a single resource from the response object
82
- def create_resource(object)
83
- res_class = detect_resource_class(object)
84
- res = res_class.new(object, response.request, client, @default_locale)
85
-
86
- add_to_known_resources res
87
- replace_children res, object
88
- replace_child_array res.items if res.array?
89
-
90
- res
91
- end
92
-
93
- # Checks in a custom class for an entry was defined in entry_mapping
94
- def find_entry_class(object)
95
- entry_mapping[content_type_id_for_entry(object)] || try_dynamic_entry(object)
96
- end
97
-
98
- # Automatically converts Entry to DynamicEntry if in cache
99
- def try_dynamic_entry(object)
100
- get_dynamic_entry(object) || Entry
101
- end
102
-
103
- # Finds the proper DynamicEntry class for an entry
104
- def get_dynamic_entry(object)
105
- content_id = content_type_id_for_entry(object)
106
- client.dynamic_entry_cache[content_id.to_sym] if content_id
107
- end
108
-
109
- # Returns the id of the related ContentType, if there is one
110
- def content_type_id_for_entry(object)
111
- object['sys'] &&
112
- object['sys']['contentType'] &&
113
- object['sys']['contentType']['sys'] &&
114
- object['sys']['contentType']['sys']['id']
115
- end
116
-
117
- # Detects if a resource is an Contentful::Array or a SyncPage
118
- def array_or_sync_page(object)
119
- if object['nextPageUrl'] || object['nextSyncUrl']
120
- SyncPage
121
- else
122
- Array
123
- end
124
- end
125
-
126
- # Uses the resource mapping to find the proper Resource class to initialize
127
- # for this Response object type
128
- #
129
- # The mapping value can be a
130
- # - Class
131
- # - Proc: Will be called, expected to return the proper Class
132
- # - Symbol: Will be called as method of the ResourceBuilder itself
133
- def detect_resource_class(object)
134
- type = object['sys'] && object['sys']['type']
135
-
136
- case res_class = resource_mapping[type]
137
- when Symbol
138
- public_send(res_class, object)
139
- when Proc
140
- res_class[object]
141
- when nil
142
- fail UnparsableResource, response
143
- else
144
- res_class
145
- end
146
- end
147
-
148
- # The default mapping for #detect_resource_class
149
- def default_resource_mapping
150
- DEFAULT_RESOURCE_MAPPING.dup
151
- end
152
-
153
- # The default entry mapping
154
- def default_entry_mapping
155
- DEFAULT_ENTRY_MAPPING.dup
156
- end
157
-
158
55
  private
159
56
 
160
- def detect_child_objects(object)
161
- if object.is_a? Hash
162
- object.select { |_, v| v.is_a?(Hash) && v.key?('sys') }
163
- else
164
- {}
57
+ def build_array
58
+ includes = fetch_includes
59
+ result = json['items'].map do |item|
60
+ build_item(item, includes)
165
61
  end
62
+ array_class = fetch_array_class
63
+ array_class.new(json.dup.merge('items' => result), default_locale, endpoint)
166
64
  end
167
65
 
168
- def detect_child_arrays(object)
169
- if object.is_a? Hash
170
- object.select do |_, v|
171
- v.is_a?(::Array) &&
172
- v.first &&
173
- v.first.is_a?(Hash) &&
174
- v.first.key?('sys')
175
- end
176
- else
177
- {}
178
- end
66
+ def build_single
67
+ includes = @includes_for_single
68
+ build_item(json, includes)
179
69
  end
180
70
 
181
- def add_to_known_resources(res)
182
- @known_resources[res.type][res.id] = res if res.sys && res.id && res.type != 'Link'
183
- end
71
+ def build_item(item, includes = [])
72
+ buildables = %w(Entry Asset ContentType Space DeletedEntry DeletedAsset)
73
+ item_type = buildables.detect { |b| b.to_s == item['sys']['type'] }
74
+ fail UnparsableResource, 'Item type is not known, could not parse' if item_type.nil?
75
+ item_class = resource_class(item)
184
76
 
185
- def localized_entry?(object, property_name, potential_objects)
186
- object['sys']['type'] == 'Entry' &&
187
- property_name == 'fields' &&
188
- potential_objects.is_a?(::Hash) &&
189
- potential_objects.any? { |_, p| Support.localized?(p) }
77
+ item_class.new(item, @configuration, localized?, includes, depth)
190
78
  end
191
79
 
192
- def replace_children(res, object)
193
- object.each do |name, potential_objects|
194
- replace_localized_children(res, object, name, potential_objects)
195
-
196
- detect_child_objects(potential_objects).each do |child_name, child_object|
197
- res.public_send(name)[child_name.to_sym] = create_resource(child_object)
198
- end
199
- next if name == 'includes'
200
- detect_child_arrays(potential_objects).each do |child_name, _child_array|
201
- replace_child_array res.public_send(name)[child_name.to_sym]
80
+ def fetch_includes
81
+ includes = json['items'].dup
82
+ %w(Entry Asset).each do |type|
83
+ if json.fetch('includes', {}).key?(type)
84
+ includes.concat(json['includes'].fetch(type, []))
202
85
  end
203
86
  end
87
+ includes
204
88
  end
205
89
 
206
- def replace_localized_children(result, object, property_name, potential_objects)
207
- return unless localized_entry?(object, property_name, potential_objects)
208
-
209
- localized_objects = potential_objects.select { |_, p| Support.localized?(p) }
210
- localized_objects.each do |field_name, localized_object|
211
- detect_child_objects(localized_object).each do |locale, child_object|
212
- result.public_send(property_name, locale)[field_name.to_sym] = create_resource(child_object)
213
- end
214
- detect_child_arrays(localized_object).each do |locale, _child_array|
215
- replace_child_array result.public_send(property_name, locale)[field_name.to_sym]
216
- end
217
- end
90
+ def resource_class(item)
91
+ return fetch_custom_resource_class(item) if %w(Entry Asset).include?(item['sys']['type'])
92
+ resource_mapping[item['sys']['type']]
218
93
  end
219
94
 
220
- def replace_child_array(child_array)
221
- child_array.map! { |resource_object| create_resource(resource_object) }
222
- end
95
+ def fetch_custom_resource_class(item)
96
+ case item['sys']['type']
97
+ when 'Entry'
98
+ resource_class = entry_mapping[item['sys']['contentType']['sys']['id']]
99
+ return resource_class unless resource_class.nil?
223
100
 
224
- def create_included_resources!(included_objects)
225
- if included_objects
226
- included_objects.each do |type, objects|
227
- @included_resources[type] = Hash[
228
- objects.map do |object|
229
- res = create_resource(object)
230
- [res.id, res]
231
- end
232
- ]
233
- end
101
+ return fetch_custom_resource_mapping(item, 'Entry', Entry)
102
+ when 'Asset'
103
+ return fetch_custom_resource_mapping(item, 'Asset', Asset)
234
104
  end
235
105
  end
236
106
 
237
- def replace_links_with_known_resources(res, seen_resource_ids = [])
238
- seen_resource_ids << res.id
239
-
240
- property_containers = [:properties, :sys].map do |property_container_name|
241
- res.public_send(property_container_name)
242
- end
243
-
244
- if res.is_a?(Entry)
245
- res.locales.each do |locale|
246
- property_containers << res.fields(locale)
247
- end
248
- else
249
- property_containers << res.fields
250
- end
107
+ def fetch_custom_resource_mapping(item, type, default_class)
108
+ resources = resource_mapping[type]
109
+ return default_class if resources.nil?
251
110
 
252
- property_containers.compact!
111
+ return resources if resources.is_a?(Class)
112
+ return resources[item] if resources.respond_to?(:call)
253
113
 
254
- property_containers.each do |property_container|
255
- replace_links_in_properties(property_container, seen_resource_ids)
256
- end
114
+ default_class
115
+ end
257
116
 
258
- replace_links_in_array res.items, seen_resource_ids if res.array?
117
+ def fetch_array_class
118
+ return SyncPage if sync?
119
+ ::Contentful::Array
259
120
  end
260
121
 
261
- def replace_links_in_properties(property_container, seen_resource_ids)
262
- property_container.each do |property_name, property_value|
263
- if property_value.is_a? ::Array
264
- replace_links_in_array property_value, seen_resource_ids
265
- else
266
- replace_link_or_check_recursively property_value, property_container, property_name, seen_resource_ids
267
- end
268
- end
122
+ def localized?
123
+ return true if @localized
124
+ return true if array? && sync?
125
+ false
269
126
  end
270
127
 
271
- def replace_links_in_array(property_container, seen_resource_ids)
272
- property_container.each.with_index do |child_property, property_index|
273
- replace_link_or_check_recursively child_property, property_container, property_index, seen_resource_ids
274
- end
128
+ def array?
129
+ json.fetch('sys', {}).fetch('type', '') == 'Array'
275
130
  end
276
131
 
277
- def replace_link_or_check_recursively(property_value, property_container, property_name, seen_resource_ids)
278
- if property_value.is_a? Link
279
- maybe_replace_link(property_value, property_container, property_name)
280
- elsif property_value.is_a?(Resource) && property_value.sys && !seen_resource_ids.include?(property_value.id)
281
- replace_links_with_known_resources(property_value, seen_resource_ids)
282
- end
132
+ def sync?
133
+ json.fetch('nextSyncUrl', nil) || json.fetch('nextPageUrl', nil)
283
134
  end
284
135
 
285
- def maybe_replace_link(link, parent, key)
286
- if @known_resources[link.link_type] &&
287
- @known_resources[link.link_type].key?(link.id)
288
- parent[key] = @known_resources[link.link_type][link.id]
289
- end
136
+ # The default mapping for #detect_resource_class
137
+ def default_resource_mapping
138
+ DEFAULT_RESOURCE_MAPPING.dup
290
139
  end
291
140
 
292
- def replace_links_in_included_resources_with_known_resources
293
- @included_resources.each do |_, for_type|
294
- for_type.each do |_, res|
295
- replace_links_with_known_resources(res)
296
- end
297
- end
141
+ # The default entry mapping
142
+ def default_entry_mapping
143
+ DEFAULT_ENTRY_MAPPING.dup
298
144
  end
299
145
  end
300
146
  end