contentful-management 0.0.1.pre

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 (188) hide show
  1. data/.gitignore +24 -0
  2. data/.reek +3 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +16 -0
  5. data/.travis.yml +9 -0
  6. data/CHANGELOG.md +2 -0
  7. data/Gemfile +13 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +408 -0
  10. data/Rakefile +37 -0
  11. data/bin/cma-console +8 -0
  12. data/contentful-management.gemspec +33 -0
  13. data/examples/blog.rb +82 -0
  14. data/examples/content_types.rb +45 -0
  15. data/examples/create_space.rb +35 -0
  16. data/lib/contentful/management.rb +12 -0
  17. data/lib/contentful/management/array.rb +35 -0
  18. data/lib/contentful/management/asset.rb +163 -0
  19. data/lib/contentful/management/client.rb +160 -0
  20. data/lib/contentful/management/content_type.rb +180 -0
  21. data/lib/contentful/management/dynamic_entry.rb +71 -0
  22. data/lib/contentful/management/entry.rb +213 -0
  23. data/lib/contentful/management/error.rb +62 -0
  24. data/lib/contentful/management/field.rb +34 -0
  25. data/lib/contentful/management/file.rb +15 -0
  26. data/lib/contentful/management/http_client.rb +22 -0
  27. data/lib/contentful/management/link.rb +23 -0
  28. data/lib/contentful/management/locale.rb +48 -0
  29. data/lib/contentful/management/location.rb +15 -0
  30. data/lib/contentful/management/request.rb +82 -0
  31. data/lib/contentful/management/resource.rb +166 -0
  32. data/lib/contentful/management/resource/array_like.rb +37 -0
  33. data/lib/contentful/management/resource/fields.rb +69 -0
  34. data/lib/contentful/management/resource/refresher.rb +21 -0
  35. data/lib/contentful/management/resource/system_properties.rb +56 -0
  36. data/lib/contentful/management/resource_builder.rb +269 -0
  37. data/lib/contentful/management/response.rb +72 -0
  38. data/lib/contentful/management/space.rb +159 -0
  39. data/lib/contentful/management/support.rb +24 -0
  40. data/lib/contentful/management/version.rb +6 -0
  41. data/spec/fixtures/vcr_cassettes/array_page_1.yml +1337 -0
  42. data/spec/fixtures/vcr_cassettes/asset/all.yml +611 -0
  43. data/spec/fixtures/vcr_cassettes/asset/archive.yml +228 -0
  44. data/spec/fixtures/vcr_cassettes/asset/archive_published.yml +177 -0
  45. data/spec/fixtures/vcr_cassettes/asset/archived_false.yml +228 -0
  46. data/spec/fixtures/vcr_cassettes/asset/archived_true.yml +228 -0
  47. data/spec/fixtures/vcr_cassettes/asset/create.yml +150 -0
  48. data/spec/fixtures/vcr_cassettes/asset/create_with_already_used_id.yml +56 -0
  49. data/spec/fixtures/vcr_cassettes/asset/create_with_custom_id.yml +150 -0
  50. data/spec/fixtures/vcr_cassettes/asset/destroy.yml +159 -0
  51. data/spec/fixtures/vcr_cassettes/asset/destroy_published.yml +175 -0
  52. data/spec/fixtures/vcr_cassettes/asset/find.yml +108 -0
  53. data/spec/fixtures/vcr_cassettes/asset/find_not_found.yml +64 -0
  54. data/spec/fixtures/vcr_cassettes/asset/image_url.yml +133 -0
  55. data/spec/fixtures/vcr_cassettes/asset/locale.yml +110 -0
  56. data/spec/fixtures/vcr_cassettes/asset/publish.yml +228 -0
  57. data/spec/fixtures/vcr_cassettes/asset/publish_already_published.yml +176 -0
  58. data/spec/fixtures/vcr_cassettes/asset/published_false.yml +228 -0
  59. data/spec/fixtures/vcr_cassettes/asset/published_true.yml +226 -0
  60. data/spec/fixtures/vcr_cassettes/asset/save_update.yml +242 -0
  61. data/spec/fixtures/vcr_cassettes/asset/set_locale.yml +110 -0
  62. data/spec/fixtures/vcr_cassettes/asset/unarchive.yml +228 -0
  63. data/spec/fixtures/vcr_cassettes/asset/unarchive_already_unarchive.yml +168 -0
  64. data/spec/fixtures/vcr_cassettes/asset/unarchive_already_unarchived.yml +168 -0
  65. data/spec/fixtures/vcr_cassettes/asset/unpublish.yml +228 -0
  66. data/spec/fixtures/vcr_cassettes/asset/unpublish_already_unpublished.yml +168 -0
  67. data/spec/fixtures/vcr_cassettes/asset/update_file.yml +207 -0
  68. data/spec/fixtures/vcr_cassettes/asset/update_to_specified_locale.yml +224 -0
  69. data/spec/fixtures/vcr_cassettes/asset/update_with_default_locale_without_file.yml +214 -0
  70. data/spec/fixtures/vcr_cassettes/content_type/activate.yml +246 -0
  71. data/spec/fixtures/vcr_cassettes/content_type/activate_with_invalid_version.yml +186 -0
  72. data/spec/fixtures/vcr_cassettes/content_type/activated_false.yml +246 -0
  73. data/spec/fixtures/vcr_cassettes/content_type/activated_true.yml +257 -0
  74. data/spec/fixtures/vcr_cassettes/content_type/all.yml +190 -0
  75. data/spec/fixtures/vcr_cassettes/content_type/create.yml +87 -0
  76. data/spec/fixtures/vcr_cassettes/content_type/create_content_type_with_id.yml +87 -0
  77. data/spec/fixtures/vcr_cassettes/content_type/create_with_Array_field.yml +94 -0
  78. data/spec/fixtures/vcr_cassettes/content_type/create_with_Boolean_field.yml +94 -0
  79. data/spec/fixtures/vcr_cassettes/content_type/create_with_Date_field.yml +94 -0
  80. data/spec/fixtures/vcr_cassettes/content_type/create_with_Integer_field.yml +94 -0
  81. data/spec/fixtures/vcr_cassettes/content_type/create_with_Link_field.yml +95 -0
  82. data/spec/fixtures/vcr_cassettes/content_type/create_with_Location_field.yml +94 -0
  83. data/spec/fixtures/vcr_cassettes/content_type/create_with_Number_field.yml +94 -0
  84. data/spec/fixtures/vcr_cassettes/content_type/create_with_Object_field.yml +94 -0
  85. data/spec/fixtures/vcr_cassettes/content_type/create_with_Symbol_field.yml +94 -0
  86. data/spec/fixtures/vcr_cassettes/content_type/create_with_Text_field.yml +94 -0
  87. data/spec/fixtures/vcr_cassettes/content_type/deactivate.yml +246 -0
  88. data/spec/fixtures/vcr_cassettes/content_type/deactivate_already_deactivated.yml +176 -0
  89. data/spec/fixtures/vcr_cassettes/content_type/deactivate_with_entries.yml +236 -0
  90. data/spec/fixtures/vcr_cassettes/content_type/deactivate_with_version_change.yml +248 -0
  91. data/spec/fixtures/vcr_cassettes/content_type/destroy.yml +148 -0
  92. data/spec/fixtures/vcr_cassettes/content_type/destroy_activated.yml +164 -0
  93. data/spec/fixtures/vcr_cassettes/content_type/entry/create.yml +1344 -0
  94. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_camel_case_id_to_multiple_locales.yml +235 -0
  95. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_entries.yml +398 -0
  96. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_entries_for_multiple_locales.yml +3157 -0
  97. data/spec/fixtures/vcr_cassettes/content_type/entry/create_with_multiple_locales.yml +230 -0
  98. data/spec/fixtures/vcr_cassettes/content_type/fields/add.yml +345 -0
  99. data/spec/fixtures/vcr_cassettes/content_type/fields/create.yml +353 -0
  100. data/spec/fixtures/vcr_cassettes/content_type/fields/create_array_with_params.yml +228 -0
  101. data/spec/fixtures/vcr_cassettes/content_type/fields/create_with_params.yml +221 -0
  102. data/spec/fixtures/vcr_cassettes/content_type/fields/destroy.yml +349 -0
  103. data/spec/fixtures/vcr_cassettes/content_type/fields/update_field.yml +358 -0
  104. data/spec/fixtures/vcr_cassettes/content_type/find.yml +180 -0
  105. data/spec/fixtures/vcr_cassettes/content_type/find_not_found.yml +64 -0
  106. data/spec/fixtures/vcr_cassettes/content_type/save_new.yml +876 -0
  107. data/spec/fixtures/vcr_cassettes/content_type/save_updated.yml +345 -0
  108. data/spec/fixtures/vcr_cassettes/content_type/save_with_added_field.yml +217 -0
  109. data/spec/fixtures/vcr_cassettes/content_type/update.yml +175 -0
  110. data/spec/fixtures/vcr_cassettes/content_type/update_change_field_name.yml +222 -0
  111. data/spec/fixtures/vcr_cassettes/content_type/update_remove_field.yml +231 -0
  112. data/spec/fixtures/vcr_cassettes/content_type/update_with_fields.yml +222 -0
  113. data/spec/fixtures/vcr_cassettes/content_type/update_with_one_new_field.yml +251 -0
  114. data/spec/fixtures/vcr_cassettes/entry/all.yml +139 -0
  115. data/spec/fixtures/vcr_cassettes/entry/archive.yml +222 -0
  116. data/spec/fixtures/vcr_cassettes/entry/archive_published.yml +187 -0
  117. data/spec/fixtures/vcr_cassettes/entry/archived_false.yml +178 -0
  118. data/spec/fixtures/vcr_cassettes/entry/archived_true.yml +248 -0
  119. data/spec/fixtures/vcr_cassettes/entry/create.yml +245 -0
  120. data/spec/fixtures/vcr_cassettes/entry/create_test.yml +150 -0
  121. data/spec/fixtures/vcr_cassettes/entry/create_with_asset.yml +403 -0
  122. data/spec/fixtures/vcr_cassettes/entry/create_with_assets.yml +419 -0
  123. data/spec/fixtures/vcr_cassettes/entry/create_with_entries.yml +418 -0
  124. data/spec/fixtures/vcr_cassettes/entry/create_with_entry.yml +493 -0
  125. data/spec/fixtures/vcr_cassettes/entry/create_with_location.yml +259 -0
  126. data/spec/fixtures/vcr_cassettes/entry/create_with_symbols.yml +271 -0
  127. data/spec/fixtures/vcr_cassettes/entry/destory_published.yml +172 -0
  128. data/spec/fixtures/vcr_cassettes/entry/destroy.yml +156 -0
  129. data/spec/fixtures/vcr_cassettes/entry/find.yml +129 -0
  130. data/spec/fixtures/vcr_cassettes/entry/find_not_found.yml +64 -0
  131. data/spec/fixtures/vcr_cassettes/entry/publish.yml +248 -0
  132. data/spec/fixtures/vcr_cassettes/entry/publish_already_published.yml +186 -0
  133. data/spec/fixtures/vcr_cassettes/entry/published_false.yml +248 -0
  134. data/spec/fixtures/vcr_cassettes/entry/published_true.yml +257 -0
  135. data/spec/fixtures/vcr_cassettes/entry/save_update.yml +211 -0
  136. data/spec/fixtures/vcr_cassettes/entry/unarchive.yml +248 -0
  137. data/spec/fixtures/vcr_cassettes/entry/unarchive_already_unarchived.yml +178 -0
  138. data/spec/fixtures/vcr_cassettes/entry/unpublish.yml +248 -0
  139. data/spec/fixtures/vcr_cassettes/entry/unpublish_already_unpublished.yml +178 -0
  140. data/spec/fixtures/vcr_cassettes/entry/update.yml +626 -0
  141. data/spec/fixtures/vcr_cassettes/entry/update_unlocalized_field.yml +308 -0
  142. data/spec/fixtures/vcr_cassettes/entry/update_with_custom_locale.yml +332 -0
  143. data/spec/fixtures/vcr_cassettes/get_request.yml +37 -0
  144. data/spec/fixtures/vcr_cassettes/locale/all_for_space.yml +321 -0
  145. data/spec/fixtures/vcr_cassettes/locale/create_for_space.yml +95 -0
  146. data/spec/fixtures/vcr_cassettes/locale/find.yml +95 -0
  147. data/spec/fixtures/vcr_cassettes/locale/find_for_space_not_found.yml +67 -0
  148. data/spec/fixtures/vcr_cassettes/space/all.yml +1201 -0
  149. data/spec/fixtures/vcr_cassettes/space/asset/all.yml +475 -0
  150. data/spec/fixtures/vcr_cassettes/space/asset/assets.yml +826 -0
  151. data/spec/fixtures/vcr_cassettes/space/asset/create.yml +508 -0
  152. data/spec/fixtures/vcr_cassettes/space/asset/create_with_multiple_locales.yml +1062 -0
  153. data/spec/fixtures/vcr_cassettes/space/asset/find.yml +634 -0
  154. data/spec/fixtures/vcr_cassettes/space/content_type/all.yml +470 -0
  155. data/spec/fixtures/vcr_cassettes/space/content_type/content_types.yml +341 -0
  156. data/spec/fixtures/vcr_cassettes/space/content_type/create.yml +425 -0
  157. data/spec/fixtures/vcr_cassettes/space/content_type/find.yml +493 -0
  158. data/spec/fixtures/vcr_cassettes/space/create.yml +85 -0
  159. data/spec/fixtures/vcr_cassettes/space/create_when_limit_has_been_reached.yml +67 -0
  160. data/spec/fixtures/vcr_cassettes/space/create_with_unknown_organization.yml +65 -0
  161. data/spec/fixtures/vcr_cassettes/space/create_without_organization.yml +83 -0
  162. data/spec/fixtures/vcr_cassettes/space/destory.yml +196 -0
  163. data/spec/fixtures/vcr_cassettes/space/entry/all.yml +634 -0
  164. data/spec/fixtures/vcr_cassettes/space/entry/entries.yml +498 -0
  165. data/spec/fixtures/vcr_cassettes/space/entry/find.yml +624 -0
  166. data/spec/fixtures/vcr_cassettes/space/find.yml +270 -0
  167. data/spec/fixtures/vcr_cassettes/space/find_not_found.yml +67 -0
  168. data/spec/fixtures/vcr_cassettes/space/locale/all.yml +690 -0
  169. data/spec/fixtures/vcr_cassettes/space/locale/create.yml +572 -0
  170. data/spec/fixtures/vcr_cassettes/space/locale/create_with_the_same_code.yml +585 -0
  171. data/spec/fixtures/vcr_cassettes/space/locale/find.yml +572 -0
  172. data/spec/fixtures/vcr_cassettes/space/locale/find_not_found.yml +580 -0
  173. data/spec/fixtures/vcr_cassettes/space/locale/locales.yml +480 -0
  174. data/spec/fixtures/vcr_cassettes/space/locale/update.yml +700 -0
  175. data/spec/fixtures/vcr_cassettes/space/save_new_space.yml +67 -0
  176. data/spec/fixtures/vcr_cassettes/space/save_update_space.yml +352 -0
  177. data/spec/fixtures/vcr_cassettes/space/update.yml +350 -0
  178. data/spec/fixtures/vcr_cassettes/space/update_with_the_same_data.yml +350 -0
  179. data/spec/lib/contentful/management/array_spec.rb +59 -0
  180. data/spec/lib/contentful/management/asset_spec.rb +321 -0
  181. data/spec/lib/contentful/management/client_spec.rb +80 -0
  182. data/spec/lib/contentful/management/content_type_spec.rb +455 -0
  183. data/spec/lib/contentful/management/entry_spec.rb +308 -0
  184. data/spec/lib/contentful/management/locale_spec.rb +53 -0
  185. data/spec/lib/contentful/management/space_spec.rb +317 -0
  186. data/spec/spec_helper.rb +10 -0
  187. data/spec/support/vcr.rb +17 -0
  188. metadata +554 -0
@@ -0,0 +1,62 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Contentful
3
+ module Management
4
+ # All errors raised by the contentful gem are either instances of Contentful::Error
5
+ # or inherit from Contentful::Error
6
+ class Error < StandardError
7
+ attr_reader :response
8
+
9
+ def initialize(response)
10
+ @response = response
11
+ super @response.error_message
12
+ end
13
+
14
+ # Shortcut for creating specialized error classes
15
+ # USAGE rescue Contentful::Error[404]
16
+ def self.[](error_status_code)
17
+ case error_status_code
18
+ when 404
19
+ NotFound
20
+ when 400
21
+ BadRequest
22
+ when 403
23
+ AccessDenied
24
+ when 401
25
+ Unauthorized
26
+ when 500
27
+ ServerError
28
+ else
29
+ Error
30
+ end
31
+ end
32
+ end
33
+
34
+ # 404
35
+ class NotFound < Error;
36
+ end
37
+
38
+ # 400
39
+ class BadRequest < Error;
40
+ end
41
+
42
+ # 403
43
+ class AccessDenied < Error;
44
+ end
45
+
46
+ # 401
47
+ class Unauthorized < Error;
48
+ end
49
+
50
+ # 500
51
+ class ServerError < Error;
52
+ end
53
+
54
+ # Raised when response is no valid json
55
+ class UnparsableJson < Error;
56
+ end
57
+
58
+ # Raised when response is not parsable as a Contentful::Resource
59
+ class UnparsableResource < Error;
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,34 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'resource'
3
+
4
+ module Contentful
5
+ module Management
6
+ class Field
7
+ include Contentful::Management::Resource
8
+
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
16
+
17
+ def deep_merge!(field)
18
+ properties.merge!(field.properties.select { |name, _type| name != :items })
19
+ items.properties.merge!(field.items.properties) if (items.respond_to?(:properties) && field.items.respond_to?(:properties))
20
+ end
21
+
22
+ def properties_to_hash
23
+ properties.each_with_object({}) do |(key, value), results|
24
+ if key == :items
25
+ results[key] = value.properties_to_hash if type == 'Array' && value.is_a?(Field)
26
+ else
27
+ results[key] = value if !value.nil? && (value.respond_to?(:empty?) && !value.empty? || !value.respond_to?(:empty?) && value)
28
+ end
29
+ end
30
+ end
31
+
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'resource'
3
+
4
+ module Contentful
5
+ module Management
6
+ class File
7
+ include Contentful::Management::Resource
8
+
9
+ property :fileName, :string
10
+ property :contentType, :string
11
+ property :details
12
+ property :url, :string
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Contentful
3
+ module Management
4
+ module HTTPClient
5
+ def get_http(url, query, headers = {})
6
+ HTTP[headers].get(url, params: query)
7
+ end
8
+
9
+ def post_http(url, params, headers = {})
10
+ HTTP[headers].post(url, json: params)
11
+ end
12
+
13
+ def delete_http(url, params, headers = {})
14
+ HTTP[headers].delete(url, params: params)
15
+ end
16
+
17
+ def put_http(url, params, headers = {})
18
+ HTTP[headers].put(url, json: params)
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'resource'
3
+
4
+ module Contentful
5
+ module Management
6
+ # Resource Class for Links
7
+ # https://www.contentful.com/developers/documentation/content-delivery-api/#links
8
+ class Link
9
+ include Contentful::Management::Resource
10
+ include Contentful::Management::Resource::SystemProperties
11
+
12
+ # Queries contentful for the Resource the Link is refering to
13
+ # Takes an optional query hash
14
+ def resolve(query = {})
15
+ id_and_query = [(id unless link_type == 'Space')].compact + [query]
16
+ client.public_send(
17
+ Contentful::Management::Support.snakify(link_type).to_sym,
18
+ *id_and_query
19
+ )
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,48 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'resource'
3
+
4
+ module Contentful
5
+
6
+ module Management
7
+
8
+ class Locale
9
+ include Contentful::Management::Resource
10
+ include Contentful::Management::Resource::SystemProperties
11
+ include Contentful::Management::Resource::Refresher
12
+
13
+ property :code, :string
14
+ property :name, :string
15
+ property :contentManagementApi, :boolean
16
+ property :contentDeliveryApi, :boolean
17
+ property :publish, :boolean
18
+
19
+ def self.all(space_id = nil)
20
+ request = Request.new("/#{ space_id }/locales")
21
+ response = request.get
22
+ result = ResourceBuilder.new(self, response, { 'Locale' => Locale }, {})
23
+ result.run
24
+ end
25
+
26
+ def self.create(space_id, attributes)
27
+ request = Request.new("/#{ space_id }/locales", { 'name' => attributes.fetch(:name), 'code' => attributes.fetch(:code) })
28
+ response = request.post
29
+ result = ResourceBuilder.new(self, response, { 'Locale' => Locale }, {})
30
+ result.run
31
+ end
32
+
33
+ def self.find(space_id, locale_id)
34
+ request = Request.new("/#{ space_id }/locales/#{ locale_id }")
35
+ response = request.get
36
+ result = ResourceBuilder.new(self, response, { 'Locale' => Locale }, {})
37
+ result.run
38
+ end
39
+
40
+ def update(attributes)
41
+ request = Request.new("/#{ space.id }/locales/#{ id }", { 'name' => attributes.fetch(:name) }, id = nil, version: sys[:version])
42
+ response = request.put
43
+ result = ResourceBuilder.new(self, response, { 'Locale' => Locale }, {})
44
+ refresh_data(result.run)
45
+ end
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,15 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'resource'
3
+
4
+ module Contentful
5
+ module Management
6
+ # Location Field Type
7
+ # You can directly query for them: https://www.contentful.com/developers/documentation/content-delivery-api/#search-filter-geo
8
+ class Location
9
+ include Contentful::Management::Resource
10
+
11
+ property :lat, :float
12
+ property :lon, :float
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,82 @@
1
+ # -*- encoding: utf-8 -*-
2
+ module Contentful
3
+ module Management
4
+ # This object represents a request that is to be made. It gets initialized by the client
5
+ # with domain specific logic. The client later uses the Request's #url and #query methods
6
+ # to execute the HTTP request.
7
+ class Request
8
+ attr_reader :client, :type, :query, :id
9
+
10
+ def initialize(endpoint, query = {}, id = nil, header = {})
11
+ @client = Contentful::Management::Client.shared_instance
12
+ @client.version = header[:version] if header[:version]
13
+ @client.organization_id = header[:organization_id] if header[:organization_id]
14
+ @client.content_type_id = header[:content_type_id] if header[:content_type_id]
15
+ @client.zero_length = query.empty?
16
+ @endpoint = endpoint
17
+ @absolute = true if @endpoint.start_with?('http')
18
+
19
+ @query = if query && !query.empty?
20
+ normalize_query(query)
21
+ end
22
+
23
+ if id
24
+ @type = :single
25
+ @id = URI.escape(id)
26
+ else
27
+ @type = :multi
28
+ @id = nil
29
+ end
30
+ end
31
+
32
+ # Returns the final URL, relative to a contentful space
33
+ def url
34
+ "#{@endpoint }#{ @type == :single ? "/#{ id }" : '' }"
35
+ end
36
+
37
+ # Delegates the actual HTTP work to the client
38
+ def get
39
+ client.get(self)
40
+ end
41
+
42
+ # Delegates the actual HTTP POST request to the client
43
+ def post
44
+ client.post(self)
45
+ end
46
+
47
+ # Delegates the actual HTTP PUT request to the client
48
+ def put
49
+ client.put(self)
50
+ end
51
+
52
+ def delete
53
+ client.delete(self)
54
+ end
55
+
56
+ # Returns true if endpoint is an absolute url
57
+ def absolute?
58
+ !!@absolute
59
+ end
60
+
61
+ # Returns a new Request object with the same data
62
+ def copy
63
+ Marshal.load(Marshal.dump(self))
64
+ end
65
+
66
+
67
+ private
68
+
69
+ def normalize_query(query)
70
+ Hash[
71
+ query.map do |key, value|
72
+ [
73
+ key.to_sym,
74
+ value
75
+ # TODO why there was this line? value.is_a?(::Array) ? value.join(',') : value
76
+ ]
77
+ end
78
+ ]
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,166 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require_relative 'resource/system_properties'
3
+ require_relative 'resource/refresher'
4
+ require 'date'
5
+
6
+ module Contentful
7
+ module Management
8
+ # Include this module to declare a class to be a contentful resource.
9
+ # This is done by the default in the existing resource classes
10
+ #
11
+ # You can define your own classes that behave like contentful resources:
12
+ # See examples/custom_classes.rb to see how.
13
+ #
14
+ # Take a look at examples/resource_mapping.rb on how to register them to be returned
15
+ # by the client by default
16
+ module Resource
17
+ COERCIONS = {
18
+ string: ->(v) { v.to_s },
19
+ integer: ->(v) { v.to_i },
20
+ float: ->(v) { v.to_f },
21
+ boolean: ->(v) { !!v },
22
+ date: ->(v) { !v.nil? ? DateTime.parse(v) : nil }
23
+ }
24
+
25
+ attr_reader :properties, :request, :client, :default_locale
26
+
27
+ def initialize(object = nil, request = nil, client = nil, nested_locale_fields = false, default_locale = Contentful::Management::Client::DEFAULT_CONFIGURATION[:default_locale])
28
+ self.class.update_coercions!
29
+ @nested_locale_fields = nested_locale_fields
30
+ @default_locale = default_locale
31
+
32
+ @properties = extract_from_object object, :property, self.class.property_coercions.keys
33
+ @request = request
34
+ @client = client
35
+ end
36
+
37
+ def inspect(info = nil)
38
+ properties_info = properties.empty? ? '' : " @properties=#{ properties.inspect }"
39
+ "#<#{ self.class }:#{ properties_info }#{ info }>"
40
+ end
41
+
42
+ # Returns true for resources that behave like an array
43
+ def array?
44
+ false
45
+ end
46
+
47
+ # By default, fields come flattened in the current locale. This is different for syncs
48
+ def nested_locale_fields?
49
+ !!@nested_locale_fields
50
+ end
51
+
52
+ # Resources that don't include SystemProperties return nil for #sys
53
+ def sys
54
+ nil
55
+ end
56
+
57
+ # Resources that don't include Fields or AssetFields return nil for #fields
58
+ def fields
59
+ nil
60
+ end
61
+
62
+ # Issues the request that was made to fetch this response again.
63
+ # Only works for top-level resources
64
+ def reload
65
+ if request
66
+ request.get
67
+ else
68
+ false
69
+ end
70
+ end
71
+
72
+ private
73
+
74
+ def extract_from_object(object, namespace, keys = nil)
75
+ if object
76
+ keys ||= object.keys
77
+ keys.each.with_object({}) do |name, res|
78
+ res[name.to_sym] = coerce_value_or_array(
79
+ object.is_a?(::Array) ? object : object[name.to_s],
80
+ self.class.public_send(:"#{ namespace }_coercions")[name.to_sym]
81
+ )
82
+ end
83
+ else
84
+ {}
85
+ end
86
+ end
87
+
88
+ def coerce_value_or_array(value, what = nil)
89
+ if value.is_a? ::Array
90
+ value.map { |v| coerce_or_create_class(v, what) }
91
+ else
92
+ coerce_or_create_class(value, what)
93
+ end
94
+ end
95
+
96
+ def coerce_or_create_class(value, what)
97
+ case what
98
+ when Symbol
99
+ COERCIONS[what] ? COERCIONS[what][value] : value
100
+ when Class
101
+ what.new(value, client)
102
+ else
103
+ value
104
+ end
105
+ end
106
+
107
+ # Register the resources properties on class level by using the #property method
108
+ module ClassMethods
109
+ # By default, fields come flattened in the current locale. This is different for sync
110
+ def nested_locale_fields?
111
+ false
112
+ end
113
+
114
+ def property_coercions
115
+ @property_coercions ||= {}
116
+ end
117
+
118
+ # Defines which properties of a resource your class expects
119
+ # Define them in :camelCase, they will be available as #snake_cased methods
120
+ #
121
+ # You can pass in a second "type" argument:
122
+ # - If it is a class, it will be initialized for the property
123
+ # - Symbols are looked up in the COERCION constant for a lambda that
124
+ # defines a type conversion to apply
125
+ #
126
+ # Note: This second argument is not meant for contentful sub-resources,
127
+ # but for structured objects (like locales in a space)
128
+ # Sub-resources are handled by the resource builder
129
+ def property(name, property_class = nil)
130
+ property_coercions[name.to_sym] = property_class
131
+ accessor_name = Contentful::Management::Support.snakify(name)
132
+ define_method accessor_name do
133
+ properties[name.to_sym]
134
+ end
135
+ define_method "#{ accessor_name }=" do |value|
136
+ properties[name.to_sym] = value
137
+ end
138
+ end
139
+
140
+ # Ensure inherited classes pick up coercions
141
+ def update_coercions!
142
+ return if @coercions_updated
143
+
144
+ if superclass.respond_to? :property_coercions
145
+ @property_coercions = superclass.property_coercions.dup.merge(@property_coercions || {})
146
+ end
147
+
148
+ if superclass.respond_to? :sys_coercions
149
+ @sys_coercions = superclass.sys_coercions.dup.merge(@sys_coercions || {})
150
+ end
151
+
152
+ if superclass.respond_to? :fields_coercions
153
+ @fields_coercions = superclass.fields_coercions.dup.merge(@fields_coercions || {})
154
+ end
155
+
156
+ @coercions_updated = true
157
+ end
158
+ end
159
+
160
+ def self.included(base)
161
+ base.extend(ClassMethods)
162
+ end
163
+
164
+ end
165
+ end
166
+ end