contentful-management 0.0.1.pre

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