contentful 2.10.1 → 2.11.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4411b6feaa1a20d23b04be5850b00c6bc4d3b97f009c94d5b3a2f647c49d08c5
4
- data.tar.gz: 4b8e2a124c217803421cf8fd4dedaaec8cb7fc0eba5d62b55610005dbb6f205a
3
+ metadata.gz: 4119a15a3968b909e9128d54c7a1daefe677940a9b9a4fb0665daba4717887c0
4
+ data.tar.gz: dce1c341f2e1826c5ef7116d4cbe81f03ceb833e925aaa452e844075a1586fdb
5
5
  SHA512:
6
- metadata.gz: 2c706107331d0135a2908945f9b7edc6d66e7aacf7746170a07ed2fb9c24a0d55ed72723660dfc3641a89402652d285d9f4506ab5ed936413787587f24579dc6
7
- data.tar.gz: bfe4e04fa103f7137e0e79dbadedf3778ac5efb27844dd3f2e658bdc2ed0ae96d0c4cfefd085ceb4424006ce66aa1ac7632e3d35f035cfe9a75ac29b498c8edd
6
+ metadata.gz: e18f6f53144ad186ca24fe6f8305bb1c432d3d691068e7181232ea7996bd6625048cbeae61fd931b2ce7948bc34b1b12c905fc93afe927f21f52c1005b0733e0
7
+ data.tar.gz: 69a2cf198c6ec8e1972c99cb887daa23d11338a2249a585c81cf52d3dacb263bbef8e58161532de933872e2b1d05328ea0b63e877b4bea6e585cd3229facf05e
@@ -2,6 +2,16 @@
2
2
 
3
3
  ## Unreleased
4
4
 
5
+ ## 2.11.0
6
+ ### Added
7
+ * Added `:raise_for_empty_fields` configuration option. [#190](https://github.com/contentful/contentful.rb/issues/190)
8
+
9
+ ### Fixed
10
+ * Links in `RichText` fields, that are published but unreachable, due to not having enough include depth on the request, are now returned as `Link` objects.
11
+
12
+ ### Changed
13
+ * Included resources for embedded entries and assets in Rich Text fields are now properly serialized to `data.target` instead of the top level `data`.
14
+
5
15
  ## 2.10.1
6
16
  ### Fixed
7
17
  * Fixed `Marshal.load` for entries with unpublished related entries.
data/README.md CHANGED
@@ -229,6 +229,11 @@ client = Contentful::Client.new(
229
229
  <td><code>true</code></td>
230
230
  <td>Determines whether errors are raised or returned.</td>
231
231
  </tr>
232
+ <tr>
233
+ <td><code>raise_for_empty_fields</code></td>
234
+ <td><code>true</code></td>
235
+ <td>Determines whether <code>EmptyFieldError</code> is raised when empty fields are requested on an entry or <code>nil</code> is returned.</td>
236
+ </tr>
232
237
  <tr>
233
238
  <td><code>dynamic_entries</code></td>
234
239
  <td><code>:manual</code></td>
@@ -21,7 +21,7 @@ Gem::Specification.new do |gem|
21
21
  gem.add_development_dependency'term-ansicolor', '~> 1.3.0'
22
22
  gem.add_development_dependency 'public_suffix', '< 1.5'
23
23
  else
24
- gem.add_dependency 'http', '> 0.8', '< 3.0'
24
+ gem.add_dependency 'http', '> 0.8', '< 4.0'
25
25
  end
26
26
 
27
27
  gem.add_dependency 'multi_json', '~> 1'
@@ -39,6 +39,6 @@ Gem::Specification.new do |gem|
39
39
  gem.add_development_dependency 'rr'
40
40
  gem.add_development_dependency 'vcr'
41
41
  gem.add_development_dependency 'simplecov'
42
- gem.add_development_dependency 'webmock', '~> 1', '>= 1.17.3'
42
+ gem.add_development_dependency 'webmock'
43
43
  gem.add_development_dependency 'tins', '~> 1.6.0'
44
44
  end
@@ -17,6 +17,7 @@ module Contentful
17
17
  DEFAULT_CONFIGURATION = {
18
18
  secure: true,
19
19
  raise_errors: true,
20
+ raise_for_empty_fields: true,
20
21
  dynamic_entries: :manual,
21
22
  api_url: 'cdn.contentful.com',
22
23
  api_version: 1,
@@ -76,6 +77,7 @@ module Contentful
76
77
  # @option given_configuration [false, ::Logger] :logger
77
78
  # @option given_configuration [::Logger::DEBUG, ::Logger::INFO, ::Logger::WARN, ::Logger::ERROR] :log_level
78
79
  # @option given_configuration [Boolean] :raise_errors
80
+ # @option given_configuration [Boolean] :raise_for_empty_fields
79
81
  # @option given_configuration [::Array<String>] :dynamic_entries
80
82
  # @option given_configuration [::Hash<String, Contentful::Resource>] :resource_mapping
81
83
  # @option given_configuration [::Hash<String, Contentful::Resource>] :entry_mapping
@@ -1,4 +1,5 @@
1
1
  require_relative 'location'
2
+ require_relative 'link'
2
3
 
3
4
  module Contentful
4
5
  # Basic Coercion
@@ -127,7 +128,7 @@ module Contentful
127
128
  link = coerce_link(node, configuration)
128
129
 
129
130
  if !link.nil?
130
- node['data'] = link
131
+ node['data']['target'] = link
131
132
  else
132
133
  invalid_nodes << index
133
134
  end
@@ -158,6 +159,9 @@ module Contentful
158
159
  configuration[:includes_for_single]
159
160
  )
160
161
 
162
+ # Resource is valid but unreachable
163
+ return Link.new(node['data']['target'], configuration) if resource.nil?
164
+
161
165
  ResourceBuilder.new(
162
166
  resource,
163
167
  configuration,
@@ -1,3 +1,4 @@
1
+ require_relative 'error'
1
2
  require_relative 'fields_resource'
2
3
  require_relative 'content_type_cache'
3
4
  require_relative 'resource_references'
@@ -89,8 +90,34 @@ module Contentful
89
90
  (object.is_a?(Contentful::Entry) || object.is_a?(Contentful::Asset))
90
91
  end
91
92
 
93
+ def method_missing(name, *args, &block)
94
+ return empty_field_error(name) if content_type_field?(name)
95
+
96
+ super
97
+ end
98
+
99
+ def respond_to_missing?(name, include_private = false)
100
+ content_type_field?(name) || super
101
+ end
102
+
92
103
  protected
93
104
 
105
+ def content_type_field?(name)
106
+ content_type = ContentTypeCache.cache_get(
107
+ sys[:space].id,
108
+ sys[:content_type].id
109
+ )
110
+
111
+ return false if content_type.nil?
112
+
113
+ !content_type.field_for(name).nil?
114
+ end
115
+
116
+ def empty_field_error(name)
117
+ return nil unless @configuration[:raise_for_empty_fields]
118
+ fail EmptyFieldError, name
119
+ end
120
+
94
121
  def repr_name
95
122
  content_type_key = Support.snakify('contentType', @configuration[:use_camel_case]).to_sym
96
123
  "#{super}[#{sys[content_type_key].id}]"
@@ -201,4 +201,11 @@ module Contentful
201
201
 
202
202
  # Raised when response is not parsable as a Contentful::Resource
203
203
  class UnparsableResource < StandardError; end
204
+
205
+ # Raised when an undefined field is requested
206
+ class EmptyFieldError < StandardError
207
+ def initialize(name)
208
+ super("The field '#{name}' is empty and unavailable in the response")
209
+ end
210
+ end
204
211
  end
@@ -1,5 +1,5 @@
1
1
  # Contentful Namespace
2
2
  module Contentful
3
3
  # Gem Version
4
- VERSION = '2.10.1'
4
+ VERSION = '2.11.0'
5
5
  end
@@ -540,6 +540,45 @@ describe Contentful::Entry do
540
540
  end
541
541
  end
542
542
 
543
+ describe 'empty fields' do
544
+ it 'raises an exception by default' do
545
+ vcr('entries/empty_fields') {
546
+ entry = create_client(
547
+ space: 'z4ssexir3p93',
548
+ access_token: 'e157fdaf7b325b71d07a94b7502807d4cfbbb1a34e69b7856838e25b92777bc6',
549
+ dynamic_entries: :auto
550
+ ).entry('2t1x77MgUA4SM2gMiaUcsy')
551
+
552
+ expect { entry.title }.to raise_error Contentful::EmptyFieldError
553
+ }
554
+ end
555
+
556
+ it 'returns nil if raise_for_empty_fields is false' do
557
+ vcr('entries/empty_fields') {
558
+ entry = create_client(
559
+ space: 'z4ssexir3p93',
560
+ access_token: 'e157fdaf7b325b71d07a94b7502807d4cfbbb1a34e69b7856838e25b92777bc6',
561
+ dynamic_entries: :auto,
562
+ raise_for_empty_fields: false
563
+ ).entry('2t1x77MgUA4SM2gMiaUcsy')
564
+
565
+ expect(entry.title).to be_nil
566
+ }
567
+ end
568
+
569
+ it 'will properly raise NoMethodError for non-fields' do
570
+ vcr('entries/empty_fields') {
571
+ entry = create_client(
572
+ space: 'z4ssexir3p93',
573
+ access_token: 'e157fdaf7b325b71d07a94b7502807d4cfbbb1a34e69b7856838e25b92777bc6',
574
+ dynamic_entries: :auto
575
+ ).entry('2t1x77MgUA4SM2gMiaUcsy')
576
+
577
+ expect { entry.unexisting_field }.to raise_error NoMethodError
578
+ }
579
+ end
580
+ end
581
+
543
582
  describe 'rich text support' do
544
583
  it 'properly serializes and resolves includes' do
545
584
  vcr('entries/rich_text') {
@@ -555,8 +594,8 @@ describe Contentful::Entry do
555
594
  embedded_entry_index = 1
556
595
  entry.body['content'].each do |content|
557
596
  if content['nodeType'] == 'embedded-entry-block'
558
- expect(content['data']).to be_a Contentful::Entry
559
- expect(content['data'].body).to eq "Embedded #{embedded_entry_index}"
597
+ expect(content['data']['target']).to be_a Contentful::Entry
598
+ expect(content['data']['target'].body).to eq "Embedded #{embedded_entry_index}"
560
599
  expected_entry_occurrances -= 1
561
600
  embedded_entry_index += 1
562
601
  end
@@ -605,10 +644,25 @@ describe Contentful::Entry do
605
644
  ).entry('6NGLswCREsGA28kGouScyY')
606
645
 
607
646
  expect(entry.body['content'][3]['nodeType']).to eq('unordered-list')
608
- expect(entry.body['content'][3]['content'][2]['content'][0]['data'].is_a?(Contentful::Entry)).to be_truthy
647
+ expect(entry.body['content'][3]['content'][2]['content'][0]['data']['target'].is_a?(Contentful::Entry)).to be_truthy
609
648
 
610
649
  expect(entry.body['content'][4]['nodeType']).to eq('ordered-list')
611
- expect(entry.body['content'][4]['content'][2]['content'][0]['data'].is_a?(Contentful::Entry)).to be_truthy
650
+ expect(entry.body['content'][4]['content'][2]['content'][0]['data']['target'].is_a?(Contentful::Entry)).to be_truthy
651
+ }
652
+ end
653
+
654
+ it 'returns a link when resource is valid but unreachable' do
655
+ vcr('entries/rich_text_unresolved_relationships') {
656
+ parent = create_client(
657
+ space: 'jd7yc4wnatx3',
658
+ access_token: '6256b8ef7d66805ca41f2728271daf27e8fa6055873b802a813941a0fe696248',
659
+ raise_errors: true,
660
+ dynamic_entries: :auto,
661
+ gzip_encoded: false
662
+ ).entry('4fvSwl5Ob6UEWKg6MQicuC')
663
+
664
+ entry = parent.rich_text_child
665
+ expect(entry.body['content'][19]['data']['target'].is_a?(Contentful::Link)).to be_truthy
612
666
  }
613
667
  end
614
668
  end
@@ -0,0 +1,246 @@
1
+ ---
2
+ http_interactions:
3
+ - request:
4
+ method: get
5
+ uri: https://cdn.contentful.com/spaces/z4ssexir3p93/environments/master/content_types?limit=1000
6
+ body:
7
+ encoding: US-ASCII
8
+ string: ''
9
+ headers:
10
+ X-Contentful-User-Agent:
11
+ - sdk contentful.rb/2.10.1; platform ruby/2.5.1; os macOS/16;
12
+ Authorization:
13
+ - Bearer e157fdaf7b325b71d07a94b7502807d4cfbbb1a34e69b7856838e25b92777bc6
14
+ Content-Type:
15
+ - application/vnd.contentful.delivery.v1+json
16
+ Accept-Encoding:
17
+ - gzip
18
+ Connection:
19
+ - close
20
+ Host:
21
+ - cdn.contentful.com
22
+ User-Agent:
23
+ - http.rb/2.2.2
24
+ response:
25
+ status:
26
+ code: 200
27
+ message: OK
28
+ headers:
29
+ Access-Control-Allow-Headers:
30
+ - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent,X-Contentful-Enable-Alpha-Feature
31
+ Access-Control-Allow-Methods:
32
+ - GET,HEAD,OPTIONS
33
+ Access-Control-Allow-Origin:
34
+ - "*"
35
+ Access-Control-Expose-Headers:
36
+ - Etag
37
+ Access-Control-Max-Age:
38
+ - '86400'
39
+ Cache-Control:
40
+ - max-age=0
41
+ Content-Type:
42
+ - application/vnd.contentful.delivery.v1+json
43
+ Contentful-Api:
44
+ - cda_cached
45
+ Etag:
46
+ - '"736965822f777aebb01c9ee4ac6d1b2a"'
47
+ Server:
48
+ - Contentful
49
+ X-Content-Type-Options:
50
+ - nosniff
51
+ X-Contentful-Region:
52
+ - us-east-1
53
+ X-Contentful-Request-Id:
54
+ - 43dd26ec0162d8b206895bf92ec3cb7c
55
+ Content-Length:
56
+ - '945'
57
+ Accept-Ranges:
58
+ - bytes
59
+ Date:
60
+ - Thu, 08 Nov 2018 13:19:20 GMT
61
+ Via:
62
+ - 1.1 varnish
63
+ Age:
64
+ - '11024'
65
+ Connection:
66
+ - close
67
+ X-Served-By:
68
+ - cache-fra19123-FRA
69
+ X-Cache:
70
+ - HIT
71
+ X-Cache-Hits:
72
+ - '1'
73
+ Vary:
74
+ - Accept-Encoding
75
+ body:
76
+ encoding: ASCII-8BIT
77
+ string: |
78
+ {
79
+ "sys": {
80
+ "type": "Array"
81
+ },
82
+ "total": 1,
83
+ "skip": 0,
84
+ "limit": 1000,
85
+ "items": [
86
+ {
87
+ "sys": {
88
+ "space": {
89
+ "sys": {
90
+ "type": "Link",
91
+ "linkType": "Space",
92
+ "id": "z4ssexir3p93"
93
+ }
94
+ },
95
+ "id": "test",
96
+ "type": "ContentType",
97
+ "createdAt": "2018-11-08T10:14:31.609Z",
98
+ "updatedAt": "2018-11-08T10:14:31.609Z",
99
+ "environment": {
100
+ "sys": {
101
+ "id": "master",
102
+ "type": "Link",
103
+ "linkType": "Environment"
104
+ }
105
+ },
106
+ "revision": 1
107
+ },
108
+ "displayField": "title",
109
+ "name": "Test",
110
+ "description": "",
111
+ "fields": [
112
+ {
113
+ "id": "title",
114
+ "name": "Title",
115
+ "type": "Symbol",
116
+ "localized": false,
117
+ "required": false,
118
+ "disabled": false,
119
+ "omitted": false
120
+ }
121
+ ]
122
+ }
123
+ ]
124
+ }
125
+ http_version:
126
+ recorded_at: Thu, 08 Nov 2018 13:19:20 GMT
127
+ - request:
128
+ method: get
129
+ uri: https://cdn.contentful.com/spaces/z4ssexir3p93/environments/master/entries?sys.id=2t1x77MgUA4SM2gMiaUcsy
130
+ body:
131
+ encoding: US-ASCII
132
+ string: ''
133
+ headers:
134
+ X-Contentful-User-Agent:
135
+ - sdk contentful.rb/2.10.1; platform ruby/2.5.1; os macOS/16;
136
+ Authorization:
137
+ - Bearer e157fdaf7b325b71d07a94b7502807d4cfbbb1a34e69b7856838e25b92777bc6
138
+ Content-Type:
139
+ - application/vnd.contentful.delivery.v1+json
140
+ Accept-Encoding:
141
+ - gzip
142
+ Connection:
143
+ - close
144
+ Host:
145
+ - cdn.contentful.com
146
+ User-Agent:
147
+ - http.rb/2.2.2
148
+ response:
149
+ status:
150
+ code: 200
151
+ message: OK
152
+ headers:
153
+ Access-Control-Allow-Headers:
154
+ - Accept,Accept-Language,Authorization,Cache-Control,Content-Length,Content-Range,Content-Type,DNT,Destination,Expires,If-Match,If-Modified-Since,If-None-Match,Keep-Alive,Last-Modified,Origin,Pragma,Range,User-Agent,X-Http-Method-Override,X-Mx-ReqToken,X-Requested-With,X-Contentful-Version,X-Contentful-Content-Type,X-Contentful-Organization,X-Contentful-Skip-Transformation,X-Contentful-User-Agent,X-Contentful-Enable-Alpha-Feature
155
+ Access-Control-Allow-Methods:
156
+ - GET,HEAD,OPTIONS
157
+ Access-Control-Allow-Origin:
158
+ - "*"
159
+ Access-Control-Expose-Headers:
160
+ - Etag
161
+ Access-Control-Max-Age:
162
+ - '86400'
163
+ Cache-Control:
164
+ - max-age=0
165
+ Content-Type:
166
+ - application/vnd.contentful.delivery.v1+json
167
+ Contentful-Api:
168
+ - cda_cached
169
+ Etag:
170
+ - '"08908121582750c6cc9ba9d71bfd6e0f"'
171
+ Server:
172
+ - Contentful
173
+ X-Content-Type-Options:
174
+ - nosniff
175
+ X-Contentful-Region:
176
+ - us-east-1
177
+ X-Contentful-Request-Id:
178
+ - 0e4aaa81032e63c7a619be69843ff267
179
+ Content-Length:
180
+ - '842'
181
+ Accept-Ranges:
182
+ - bytes
183
+ Date:
184
+ - Thu, 08 Nov 2018 13:19:20 GMT
185
+ Via:
186
+ - 1.1 varnish
187
+ Age:
188
+ - '0'
189
+ Connection:
190
+ - close
191
+ X-Served-By:
192
+ - cache-fra19146-FRA
193
+ X-Cache:
194
+ - MISS
195
+ X-Cache-Hits:
196
+ - '0'
197
+ Vary:
198
+ - Accept-Encoding
199
+ body:
200
+ encoding: ASCII-8BIT
201
+ string: |
202
+ {
203
+ "sys": {
204
+ "type": "Array"
205
+ },
206
+ "total": 1,
207
+ "skip": 0,
208
+ "limit": 100,
209
+ "items": [
210
+ {
211
+ "sys": {
212
+ "space": {
213
+ "sys": {
214
+ "type": "Link",
215
+ "linkType": "Space",
216
+ "id": "z4ssexir3p93"
217
+ }
218
+ },
219
+ "id": "2t1x77MgUA4SM2gMiaUcsy",
220
+ "type": "Entry",
221
+ "createdAt": "2018-11-08T10:14:42.223Z",
222
+ "updatedAt": "2018-11-08T10:14:42.223Z",
223
+ "environment": {
224
+ "sys": {
225
+ "id": "master",
226
+ "type": "Link",
227
+ "linkType": "Environment"
228
+ }
229
+ },
230
+ "revision": 1,
231
+ "contentType": {
232
+ "sys": {
233
+ "type": "Link",
234
+ "linkType": "ContentType",
235
+ "id": "test"
236
+ }
237
+ },
238
+ "locale": "en-US"
239
+ },
240
+ "fields": {}
241
+ }
242
+ ]
243
+ }
244
+ http_version:
245
+ recorded_at: Thu, 08 Nov 2018 13:19:21 GMT
246
+ recorded_with: VCR 4.0.0