contentful 0.3.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.travis.yml CHANGED
@@ -1,5 +1,6 @@
1
1
  language: ruby
2
2
  rvm:
3
+ - 2.1.2
3
4
  - 2.1.1
4
5
  - 2.1
5
6
  - 2.0.0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,8 @@
1
+ ### 0.3.1
2
+ * return nil when a value is not supplied, fixes #18
3
+ * do not parse empty responses
4
+ * remove CGI dependency for http gem
5
+
1
6
  ### 0.3.0
2
7
 
3
8
  * Support Synchronization
data/README.md CHANGED
@@ -9,65 +9,78 @@ Ruby client for the [Contentful](https://www.contentful.com) Content Delivery AP
9
9
 
10
10
  Add to your Gemfile and bundle:
11
11
 
12
- gem 'contentful'
13
-
12
+ ```bash
13
+ gem 'contentful'
14
+ ```
14
15
 
15
16
  ## Usage
16
17
 
17
- client = Contentful::Client.new(
18
- access_token: 'b4c0n73n7fu1',
19
- space: 'cfexampleapi'
20
- )
18
+ ```ruby
19
+ client = Contentful::Client.new(
20
+ access_token: 'b4c0n73n7fu1',
21
+ space: 'cfexampleapi'
22
+ )
23
+ ```
21
24
 
22
25
  You can query for entries, assets, etc. very similar as described in the
23
26
  [Delivery API Documentation](https://www.contentful.com/developers/documentation/content-delivery-api/). Please note, that **all methods of the Ruby client library are snake_cased, instead of JavaScript's camelCase**:
24
27
 
25
- client.content_types
26
- client.entry 'nyancat'
28
+ ```ruby
29
+ client.content_types
30
+ client.entry 'nyancat'
31
+ ```
27
32
 
28
33
  You can pass the usual filter options to the query:
29
34
 
30
- client.entries('sys.id[ne]' => 'nyancat') # query for all entries except 'nyancat'
31
- client.entries(include: 1) # include one level of linked resources
32
-
35
+ ```ruby
36
+ client.entries('sys.id[ne]' => 'nyancat') # query for all entries except 'nyancat'
37
+ client.entries(include: 1) # include one level of linked resources
38
+ ```
33
39
 
34
40
  The results are returned as Contentful::Resource objects. Multiple results will be returned as Contentful::Array. The properties of a resource can be accessed through Ruby methods.
35
41
 
36
- content_type = client.content_type 'cat'
37
- content_type.description # "Meow."
38
-
42
+ ```ruby
43
+ content_type = client.content_type 'cat'
44
+ content_type.description # "Meow."
45
+ ```
39
46
 
40
47
  Alternatively, the data can be accessed as Ruby `Hash` with symbolized keys (and in camelCase):
41
48
 
42
- content_type.properties # { name: '...', description: '...' }
43
-
49
+ ```ruby
50
+ content_type.properties # { name: '...', description: '...' }
51
+ ```
44
52
 
45
53
  System Properties behave the same and can be accessed via the `#sys` method.
46
54
 
47
- content_type.id # => 'cat'
48
- entry.type # => 'Entry'
49
- asset.sys # { id: '...', type: '...' }
50
-
55
+ ```ruby
56
+ content_type.id # => 'cat'
57
+ entry.type # => 'Entry'
58
+ asset.sys # { id: '...', type: '...' }
59
+ ```
51
60
 
52
61
  Entry Fields usually don't have direct method accessors, since they are based on individual content types. These fields can be accessed through the `#fields` method:
53
62
 
54
- entry = client.entry 'nyancat'
55
- entry.fields[:color] # rainbow
63
+ ```ruby
64
+ entry = client.entry 'nyancat'
65
+ entry.fields[:color] # rainbow
66
+ ```
56
67
 
57
68
  Please note, that no field type conversions will be done for entries by default.
58
69
 
59
-
60
70
  ### Dynamic Entries
61
71
 
62
72
  However, you can (and should) set `:dynamic_entries` to `:auto` in your client configuration. When using this option, the client will fetch all available content types and use them to create dynamic entries on the fly.
63
73
 
64
- client = Contentful::Client.new(
65
- access_token: 'b4c0n73n7fu1',
66
- space: 'cfexampleapi',
67
- dynamic_entries: :auto,
68
- )
69
- entry = client.entry 'nyancat' # => #<Contentful::DynamicEntry[cat]: ...>
70
- entry.color # => 'rainbow'
74
+ ```ruby
75
+ client = Contentful::Client.new(
76
+ access_token: 'b4c0n73n7fu1',
77
+ space: 'cfexampleapi',
78
+ dynamic_entries: :auto,
79
+ )
80
+
81
+ entry = client.entry 'nyancat' # => #<Contentful::DynamicEntry[cat]: ...>
82
+ entry.color # => 'rainbow'
83
+ ```
71
84
 
72
85
  Dynamic entries will have getter classes for the fields and do type conversions properly.
73
86
 
@@ -85,32 +98,35 @@ Arrays also have a `#next_page` URL, which will rerun the request with a increas
85
98
 
86
99
  You can easily request a resource that is represented by a link by calling `#resolve`:
87
100
 
88
- happycat = client.entry 'happycat'
89
- happycat.fields[:image]
90
- # => #<Contentful::Link: @sys={:type=>"Link", :linkType=>"Asset", :id=>"happycat"}>
91
- happycat.fields[:image].resolve # => #<Contentful::Asset: @fields={ ...
92
-
101
+ ```ruby
102
+ happycat = client.entry 'happycat'
103
+ happycat.fields[:image]
104
+ # => #<Contentful::Link: @sys={:type=>"Link", :linkType=>"Asset", :id=>"happycat"}>
105
+ happycat.fields[:image].resolve # => #<Contentful::Asset: @fields={ ...
106
+ ```
93
107
 
94
108
  ### Assets
95
109
 
96
110
  There is a helpful method to add image resize options for an asset image:
97
111
 
98
- client.asset('happycat').image_url
99
- # => "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/
100
- # 382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg"
101
-
102
- client.asset('happycat').image_url width: 300, height: 200, format: 'jpg', quality: 100
103
- # => "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/
104
- # 382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg?w=300&h=200&fm=jpg&q=100"
112
+ ```ruby
113
+ client.asset('happycat').image_url
114
+ # => "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/
115
+ # 382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg"
105
116
 
117
+ client.asset('happycat').image_url width: 300, height: 200, format: 'jpg', quality: 100
118
+ # => "//images.contentful.com/cfexampleapi/3MZPnjZTIskAIIkuuosCss/
119
+ # 382a48dfa2cb16c47aa2c72f7b23bf09/happycatw.jpg?w=300&h=200&fm=jpg&q=100"
120
+ ```
106
121
 
107
122
  ### Resource Options
108
123
 
109
124
  Resources, that have been requested directly (i.e. no child resources), can be fetched from the server again by calling `#reload`:
110
125
 
111
- entries = client.entries
112
- entries.reload # Fetches the array of entries again
113
-
126
+ ```ruby
127
+ entries = client.entries
128
+ entries.reload # Fetches the array of entries again
129
+ ```
114
130
 
115
131
  ### Field Type "Object"
116
132
 
@@ -156,80 +172,95 @@ See next paragraph for explanation
156
172
 
157
173
  You can define your own classes that will be returned instead of the predefined ones. Consider, you want to build a better Asset class. One way to do this is:
158
174
 
159
- class MyBetterAsset < Contentful::Asset
160
- def https_image_url
161
- image_url.sub %r<\A//>, 'https://'
162
- end
163
- end
175
+ ```ruby
176
+ class MyBetterAsset < Contentful::Asset
177
+ def https_image_url
178
+ image_url.sub %r<\A//>, 'https://'
179
+ end
180
+ end
181
+ ```
164
182
 
165
183
  You can register your custom class on client initialization:
166
184
 
167
- client = Contentful::Client.new(
168
- space: 'cfexampleapi',
169
- access_token: 'b4c0n73n7fu1',
170
- resource_mapping: {
171
- 'Asset' => MyBetterAsset
172
- }
173
- )
185
+ ```ruby
186
+ client = Contentful::Client.new(
187
+ space: 'cfexampleapi',
188
+ access_token: 'b4c0n73n7fu1',
189
+ resource_mapping: {
190
+ 'Asset' => MyBetterAsset
191
+ }
192
+ )
193
+ ```
174
194
 
175
195
  More information on `:resource_mapping` can be found in examples/resource_mapping.rb and more on custom classes in examples/custom_classes.rb
176
196
 
177
197
  You can also register custom entry classes to be used based on the entry's content_type using the :entry_mapping configuration:
178
198
 
179
- class Cat < Contentful::Entry
180
- # define methods based on :fields, etc
181
- end
199
+ ```ruby
200
+ class Cat < Contentful::Entry
201
+ # define methods based on :fields, etc
202
+ end
182
203
 
183
- client = Contentful::Client.new(
184
- space: 'cfexampleapi',
185
- access_token: 'b4c0n73n7fu1',
186
- entry_mapping: {
187
- 'cat' => Cat
188
- }
189
- )
190
-
191
- client.entry('nyancat') # is instance of Cat
204
+ client = Contentful::Client.new(
205
+ space: 'cfexampleapi',
206
+ access_token: 'b4c0n73n7fu1',
207
+ entry_mapping: {
208
+ 'cat' => Cat
209
+ }
210
+ )
192
211
 
212
+ client.entry('nyancat') # is instance of Cat
213
+ ```
193
214
 
194
215
  ## Synchronization
195
216
 
196
217
  The client also includes a wrapper for the synchronization endpoint. You can initialize it with the options described in the [Delivery API Documentation](https://www.contentful.com/developers/documentation/content-delivery-api/#sync) or an URL you received from a previous sync:
197
218
 
198
- client = Contentful::Client.new(
199
- access_token: 'b4c0n73n7fu1',
200
- space: 'cfexampleapi',
201
- default_locale: 'en-US'
202
- )
203
- sync = client.sync(initial: true, type: 'Deletion') # Only returns deleted entries and assets
204
- sync = client.sync("https://cdn.contentful.com/spaces/cfexampleapi/sync?sync_token=w5ZGw6JFwqZmVcKsE8Kow4gr...sGPg") # Continues a sync
219
+ ```ruby
220
+ client = Contentful::Client.new(
221
+ access_token: 'b4c0n73n7fu1',
222
+ space: 'cfexampleapi',
223
+ default_locale: 'en-US'
224
+ )
225
+
226
+ sync = client.sync(initial: true, type: 'Deletion') # Only returns deleted entries and assets
227
+ sync = client.sync("https://cdn.contentful.com/spaces/cfexampleapi/sync?sync_token=w5ZGw6JFwqZmVcKsE8Kow4gr...sGPg") # Continues a sync
228
+ ```
205
229
 
206
230
  You can access the results either wrapped in `Contentful::SyncPage` objects:
207
231
 
208
- sync.each_page do |page|
209
- # Find resources at: page.items
210
- end
232
+ ```ruby
233
+ sync.each_page do |page|
234
+ # Find resources at: page.items
235
+ end
211
236
 
212
- # More explicit version:
213
- page = sync.first_page
214
- until sync.completed?
215
- page = s.next_page
216
- end
237
+ # More explicit version:
238
+ page = sync.first_page
239
+ until sync.completed?
240
+ page = sync.next_page
241
+ end
242
+ ```
217
243
 
218
244
  Or directly iterative over all resources:
219
245
 
220
- sync.each_item do |resource|
221
- # ...
222
- end
246
+ ```ruby
247
+ sync.each_item do |resource|
248
+ # ...
249
+ end
250
+ ```
223
251
 
224
252
  When a sync is completed, the next sync url can be read from the Sync or SyncPage object:
225
253
 
226
- sync.next_sync_url
254
+ ```ruby
255
+ sync.next_sync_url
256
+ ```
227
257
 
228
258
  **Please note** that synchronization entries come in all locales, so make sure, you supply a :default_locale property to the client configuration, when using the sync feature. This locale will be returned by default, when you call `Entry#fields`. The other localized data will also be saved and can be accessed by calling the fields method with a locale parameter:
229
259
 
230
- first_entry = client.sync(initial: true, type: 'Entry').first_page.items.first
231
- first_entry.fields('de-DE') # Returns German localizations
232
-
260
+ ```ruby
261
+ first_entry = client.sync(initial: true, type: 'Entry').first_page.items.first
262
+ first_entry.fields('de-DE') # Returns German localizations
263
+ ```
233
264
 
234
265
  ## License
235
266
 
@@ -4,8 +4,6 @@ require_relative 'resource_builder'
4
4
  require_relative 'sync'
5
5
 
6
6
  require 'http'
7
- # see: https://github.com/tarcieri/http/commit/6a2a9d22902572d672dfc7c7b250d022364c8e01#commitcomment-6192269
8
- require 'cgi'
9
7
 
10
8
  module Contentful
11
9
  # The client object is initialized with a space and a key and then used
@@ -8,8 +8,8 @@ module Contentful
8
8
  # You can define your own classes that behave like contentful resources:
9
9
  # See examples/custom_classes.rb to see how.
10
10
  #
11
- # Take a look at examples/resource_mapping.rb on how to register them to be returned
12
- # by the client by default
11
+ # Take a look at examples/resource_mapping.rb on how to register them
12
+ # to be returned by the client by default
13
13
  module Resource
14
14
  COERCIONS = {
15
15
  string: ->(v) { v.to_s },
@@ -26,7 +26,8 @@ module Contentful
26
26
  @nested_locale_fields = nested_locale_fields
27
27
  @default_locale = default_locale
28
28
 
29
- @properties = extract_from_object object, :property, self.class.property_coercions.keys
29
+ @properties = extract_from_object(object, :property,
30
+ self.class.property_coercions.keys)
30
31
  @request = request
31
32
  @client = client
32
33
  end
@@ -72,10 +73,9 @@ module Contentful
72
73
  if object
73
74
  keys ||= object.keys
74
75
  keys.each.with_object({}) do |name, res|
75
- res[name.to_sym] = coerce_value_or_array(
76
- object.is_a?(::Array) ? object : object[name.to_s],
77
- self.class.public_send(:"#{namespace}_coercions")[name.to_sym]
78
- )
76
+ value = object.is_a?(::Array) ? object : object[name.to_s]
77
+ kind = self.class.public_send(:"#{namespace}_coercions")[name.to_sym]
78
+ res[name.to_sym] = coerce_value_or_array(value, kind)
79
79
  end
80
80
  else
81
81
  {}
@@ -83,7 +83,9 @@ module Contentful
83
83
  end
84
84
 
85
85
  def coerce_value_or_array(value, what = nil)
86
- if value.is_a? ::Array
86
+ if value.nil?
87
+ nil
88
+ elsif value.is_a? ::Array
87
89
  value.map { |v| coerce_or_create_class(v, what) }
88
90
  else
89
91
  coerce_or_create_class(value, what)
@@ -27,14 +27,20 @@ module Contentful
27
27
  @request = request
28
28
  @status = :ok
29
29
 
30
- if parse_json!
30
+ if no_content_response?
31
+ @status = :no_content
32
+ @object = true
33
+ elsif parse_json!
31
34
  parse_contentful_error!
32
35
  end
33
36
  end
34
37
 
35
-
36
38
  private
37
39
 
40
+ def no_content_response?
41
+ @raw.to_s == '' && @raw.status == 204
42
+ end
43
+
38
44
  def parse_json!
39
45
  @object = MultiJson.load(raw.to_s)
40
46
  true
@@ -61,4 +67,4 @@ module Contentful
61
67
  end
62
68
 
63
69
  end
64
- end
70
+ end
@@ -1,3 +1,3 @@
1
1
  module Contentful
2
- VERSION = '0.3.0'
2
+ VERSION = '0.3.1'
3
3
  end
data/problem.rb ADDED
@@ -0,0 +1,39 @@
1
+ require 'pry'
2
+ module PlayboyContentful
3
+ class ContentType < Contentful::ContentType
4
+
5
+ def type_for_field_with_name(name)
6
+ fields.each do |field|
7
+ return field.type if field.id == name
8
+ end
9
+ return nil
10
+ end
11
+
12
+ # Depending on if the field supports full text search, the call needs may
13
+ # or may not need to append [eq] to the "fields.<field_name>" filter
14
+ def equality_string_for_field_with_name(name)
15
+ field_type = type_for_field_with_name(name)
16
+ raise "Could not build equality string for #{name} because field was not found." if field_type == nil
17
+ return "fields.#{name}" if field_type == "Symbol"
18
+ return "fields.#{name}[match]" if field_type == "Text"
19
+ "fields.#{name}[eq]"
20
+ end
21
+
22
+ end
23
+ end
24
+
25
+ CONTENTFUL_ACCESS_TOKEN="9b3b92d9929dc96744809e3b290bd1c6e6d9f10f7e4e7217ed50524fc0d9728d"
26
+ CONTENTFUL_SPACE="t8g5epyvf6nt"
27
+
28
+ client = Contentful::Client.new(
29
+ access_token: CONTENTFUL_ACCESS_TOKEN,
30
+ space: CONTENTFUL_SPACE,
31
+ dynamic_entries: :auto,
32
+ resource_mapping: {
33
+ 'ContentType' => PlayboyContentful::ContentType
34
+ }
35
+ )
36
+
37
+ client.entry('2ks0eTNWoMw0026sUgsMWW')
38
+
39
+ client.entries({"content_type"=>"3VZz9HnPy02usuACK08WUw", :limit=>1000})
@@ -35,6 +35,13 @@ describe Contentful::Response do
35
35
  it 'returns :unparsable_json for unparsable json responses' do
36
36
  expect( unparsable_response.status ).to eq :unparsable_json
37
37
  end
38
+
39
+ it 'returns :no_content for responses without content' do
40
+ raw_response = ''
41
+ mock(raw_response).status {204}
42
+ no_content_response = Contentful::Response.new raw_response
43
+ expect( no_content_response.status).to eq :no_content
44
+ end
38
45
  end
39
46
 
40
47
  describe "#error_message" do
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: contentful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-02 00:00:00.000000000 Z
12
+ date: 2014-07-16 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: http
@@ -211,6 +211,7 @@ files:
211
211
  - lib/contentful/version.rb
212
212
  - lib/contentful.rb
213
213
  - LICENSE.txt
214
+ - problem.rb
214
215
  - Rakefile
215
216
  - README.md
216
217
  - spec/array_spec.rb
@@ -288,7 +289,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
288
289
  version: '0'
289
290
  segments:
290
291
  - 0
291
- hash: -620049112391953740
292
+ hash: -2280169027525600462
292
293
  required_rubygems_version: !ruby/object:Gem::Requirement
293
294
  none: false
294
295
  requirements:
@@ -297,7 +298,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
297
298
  version: '0'
298
299
  segments:
299
300
  - 0
300
- hash: -620049112391953740
301
+ hash: -2280169027525600462
301
302
  requirements: []
302
303
  rubyforge_project:
303
304
  rubygems_version: 1.8.23.2