contentful 0.3.0 → 0.3.1

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