wcc-contentful 0.4.0.pre.alpha → 0.4.0.pre.beta

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
  SHA1:
3
- metadata.gz: c54cd88861b87469555e71fe1a83ee70cbfe6dfe
4
- data.tar.gz: e0fbecf29c3dde28acf284ecce0973a0ceca9669
3
+ metadata.gz: ff6f351c2042a4a584360d284e9079944fb3345f
4
+ data.tar.gz: 511988b09e647cf69c7b6c9accf4098fce140d08
5
5
  SHA512:
6
- metadata.gz: 21d1522d8f7655123eebba0f2a768c279fdb8907f8333445255113dbf78b45ec64479f92c15053622bda2e222724be7ce903d350c5f677bbd94d9ee2bb2e753d
7
- data.tar.gz: a84363867c283dea04e32120b71cbb0fe5fa15d58f4e2da242f28144ee59976740b5f78f9e52988ee15738aa9242113bf0fc4d9ae22ae9f73debd2721258ccd9
6
+ metadata.gz: b3fac31b5af8c0f24e9bb91139946819134f5f68d38dfa2b90c70e30aacd6d9933bee1a716f5717b1d1769118875af4eb0f7ca6657fc6b09b736141c6cf4640d
7
+ data.tar.gz: 30141b535a65ade870b48573efee983310ad4c3ff704332f0cee15ceaf8e033e94d4cfa3bda4f42f36e3812fa7be49bf2d807375fa695231cf50b925cdfd92f8
data/README.md CHANGED
@@ -211,6 +211,66 @@ class MyJob < ApplicationJob
211
211
  end
212
212
  ```
213
213
 
214
+ ## Test Helpers
215
+
216
+ To use the test helpers, include the following in your rails_helper.rb:
217
+
218
+ ```ruby
219
+ require 'wcc/contentful/rspec'
220
+ ```
221
+
222
+ This adds the following helpers to all your specs:
223
+
224
+ ```ruby
225
+ ##
226
+ # Builds a in-memory instance of the Contentful model for the given content_type.
227
+ # All attributes that are known to be required fields on the content type
228
+ # will return a default value based on the field type.
229
+ instance = contentful_create('my-content-type', my_field: 'some-value')
230
+ # => #<WCC::Contentful::Model::MyContentType:0x0000000005c71a78 @created_at=2018-04-16 18:41:17 UTC...>
231
+
232
+ instance.my_field
233
+ # => "some-value"
234
+
235
+ instance.other_required_field
236
+ # => "default-value"
237
+
238
+ instance.other_optional_field
239
+ # => nil
240
+
241
+ instance.not_a_field
242
+ # NoMethodError: undefined method `not_a_field' for #<Menu:0x00007fbac81ee490>
243
+
244
+ ##
245
+ # Builds a rspec double of the Contentful model for the given content_type.
246
+ # All attributes that are known to be required fields on the content type
247
+ # will return a default value based on the field type.
248
+ dbl = contentful_double('my-content-type', my_field: 'other-value')
249
+ # => #<Double (anonymous)>
250
+
251
+ dbl.my_field
252
+ # => "other-value"
253
+
254
+ dbl.not_a_field
255
+ # => #<Double (anonymous)> received unexpected message :not_a_field with (no args)
256
+
257
+ ##
258
+ # Builds out a fake Contentful entry for the given content type, and then
259
+ # stubs the Model API to return that content type for `.find` and `.find_by`
260
+ # query methods.
261
+ stubbed = contentful_stub('my-content-type', id: '1234', my_field: 'test')
262
+
263
+ WCC::Contentful::Model.find('1234') == stubbed
264
+ # => true
265
+
266
+ MyContentType.find('1234') == stubbed
267
+ # => true
268
+
269
+ MyContentType.find_by(my_field: 'test') == stubbed
270
+ # => true
271
+ ```
272
+
273
+
214
274
  ## Development
215
275
 
216
276
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'wcc/contentful'
4
+
5
+ require_relative './test'
6
+
7
+ module WCC::Contentful::RSpec
8
+ include WCC::Contentful::Test::Double
9
+ include WCC::Contentful::Test::Factory
10
+
11
+ ##
12
+ # Builds out a fake Contentful entry for the given content type, and then
13
+ # stubs the Model API to return that content type for `.find` and `.find_by`
14
+ # query methods.
15
+ def contentful_stub(content_type, **attrs)
16
+ const = WCC::Contentful::Model.resolve_constant(content_type.to_s)
17
+ instance = contentful_create(content_type, **attrs)
18
+
19
+ allow(WCC::Contentful::Model).to receive(:find)
20
+ .with(instance.id)
21
+ .and_return(instance)
22
+ allow(WCC::Contentful::Model).to receive(:find)
23
+ .with(instance.id, anything)
24
+ .and_return(instance)
25
+ allow(const).to receive(:find) { |id, options| WCC::Contentful::Model.find(id, options) }
26
+
27
+ attrs.each do |k, v|
28
+ allow(const).to receive(:find_by)
29
+ .with(hash_including(k => v))
30
+ .and_return(instance)
31
+ end
32
+
33
+ instance
34
+ end
35
+ end
36
+
37
+ if defined?(RSpec)
38
+ RSpec.configure do |config|
39
+ config.include WCC::Contentful::RSpec
40
+ end
41
+ end
@@ -1,20 +1,25 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  gem 'pg', '~> 1.0'
4
+ gem 'connection_pool', '~> 2.2'
4
5
  require 'pg'
6
+ require 'connection_pool'
5
7
 
6
8
  module WCC::Contentful::Store
7
9
  class PostgresStore < Base
8
- def initialize(_config = nil, connection_options = nil)
10
+ attr_reader :connection_pool
11
+
12
+ def initialize(_config = nil, connection_options = nil, pool_options = nil)
9
13
  super()
14
+ @schema_ensured = false
10
15
  connection_options ||= { dbname: 'postgres' }
11
- @conn = PG.connect(connection_options)
12
- PostgresStore.ensure_schema(@conn)
16
+ pool_options ||= {}
17
+ @connection_pool = build_connection_pool(connection_options, pool_options)
13
18
  end
14
19
 
15
20
  def set(key, value)
16
21
  ensure_hash value
17
- result = @conn.exec_prepared('upsert_entry', [key, value.to_json])
22
+ result = @connection_pool.with { |conn| conn.exec_prepared('upsert_entry', [key, value.to_json]) }
18
23
  return if result.num_tuples == 0
19
24
 
20
25
  val = result.getvalue(0, 0)
@@ -22,21 +27,21 @@ module WCC::Contentful::Store
22
27
  end
23
28
 
24
29
  def keys
25
- result = @conn.exec_prepared('select_ids')
30
+ result = @connection_pool.with { |conn| conn.exec_prepared('select_ids') }
26
31
  arr = []
27
32
  result.each { |r| arr << r['id'].strip }
28
33
  arr
29
34
  end
30
35
 
31
36
  def delete(key)
32
- result = @conn.exec_prepared('delete_by_id', [key])
37
+ result = @connection_pool.with { |conn| conn.exec_prepared('delete_by_id', [key]) }
33
38
  return if result.num_tuples == 0
34
39
 
35
40
  JSON.parse(result.getvalue(0, 1))
36
41
  end
37
42
 
38
43
  def find(key, **_options)
39
- result = @conn.exec_prepared('select_entry', [key])
44
+ result = @connection_pool.with { |conn| conn.exec_prepared('select_entry', [key]) }
40
45
  return if result.num_tuples == 0
41
46
 
42
47
  JSON.parse(result.getvalue(0, 1))
@@ -46,7 +51,7 @@ module WCC::Contentful::Store
46
51
  statement = "WHERE data->'sys'->'contentType'->'sys'->>'id' = $1"
47
52
  Query.new(
48
53
  self,
49
- @conn,
54
+ @connection_pool,
50
55
  statement,
51
56
  [content_type],
52
57
  options
@@ -54,9 +59,9 @@ module WCC::Contentful::Store
54
59
  end
55
60
 
56
61
  class Query < Base::Query
57
- def initialize(store, conn, statement = nil, params = nil, options = nil)
62
+ def initialize(store, connection_pool, statement = nil, params = nil, options = nil)
58
63
  super(store)
59
- @conn = conn
64
+ @connection_pool = connection_pool
60
65
  @statement = statement ||
61
66
  "WHERE data->'sys'->>'id' IS NOT NULL"
62
67
  @params = params || []
@@ -74,7 +79,7 @@ module WCC::Contentful::Store
74
79
 
75
80
  Query.new(
76
81
  @store,
77
- @conn,
82
+ @connection_pool,
78
83
  statement,
79
84
  params,
80
85
  @options
@@ -85,7 +90,7 @@ module WCC::Contentful::Store
85
90
  return @count if @count
86
91
 
87
92
  statement = 'SELECT count(*) FROM contentful_raw ' + @statement
88
- result = @conn.exec(statement, @params)
93
+ result = @connection_pool.with { |conn| conn.exec(statement, @params) }
89
94
  @count = result.getvalue(0, 0).to_i
90
95
  end
91
96
 
@@ -93,7 +98,7 @@ module WCC::Contentful::Store
93
98
  return @first if @first
94
99
 
95
100
  statement = 'SELECT * FROM contentful_raw ' + @statement + ' LIMIT 1'
96
- result = @conn.exec(statement, @params)
101
+ result = @connection_pool.with { |conn| conn.exec(statement, @params) }
97
102
  return if result.num_tuples == 0
98
103
 
99
104
  resolve_includes(
@@ -135,7 +140,7 @@ module WCC::Contentful::Store
135
140
  return @resolved if @resolved
136
141
 
137
142
  statement = 'SELECT * FROM contentful_raw ' + @statement
138
- @resolved = @conn.exec(statement, @params)
143
+ @resolved = @connection_pool.with { |conn| conn.exec(statement, @params) }
139
144
  end
140
145
 
141
146
  def push_param(param, params)
@@ -168,11 +173,27 @@ module WCC::Contentful::Store
168
173
  $$ LANGUAGE 'plpgsql';
169
174
  HEREDOC
170
175
  )
176
+ end
171
177
 
178
+ def self.prepare_statements(conn)
172
179
  conn.prepare('upsert_entry', 'SELECT * FROM upsert_entry($1,$2)')
173
180
  conn.prepare('select_entry', 'SELECT * FROM contentful_raw WHERE id = $1')
174
181
  conn.prepare('select_ids', 'SELECT id FROM contentful_raw')
175
182
  conn.prepare('delete_by_id', 'DELETE FROM contentful_raw WHERE id = $1 RETURNING *')
176
183
  end
184
+
185
+ private
186
+
187
+ def build_connection_pool(connection_options, pool_options)
188
+ ConnectionPool.new(pool_options) do
189
+ PG.connect(connection_options).tap do |conn|
190
+ unless @schema_ensured
191
+ PostgresStore.ensure_schema(conn)
192
+ @schema_ensured = true
193
+ end
194
+ PostgresStore.prepare_statements(conn)
195
+ end
196
+ end
197
+ end
177
198
  end
178
199
  end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WCC::Contentful::Test
4
+ end
5
+
6
+ require_relative 'test/double'
7
+ require_relative 'test/factory'
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module WCC::Contentful::Test::Attributes
4
+ DEFAULTS = {
5
+ String: 'test',
6
+ Int: 0,
7
+ Float: 0.0,
8
+ DateTime: Time.at(0),
9
+ Boolean: false,
10
+ Json: -> { OpenStruct.new },
11
+ Coordinates: -> { OpenStruct.new }
12
+ }.freeze
13
+
14
+ class << self
15
+ def [](key)
16
+ DEFAULTS[key]
17
+ end
18
+
19
+ ##
20
+ # Get a hash of default values for all attributes unique to the given Contentful model.
21
+ def defaults(const)
22
+ unless const < WCC::Contentful::Model
23
+ raise ArgumentError, "#{const} is not a subclass of WCC::Contentful::Model"
24
+ end
25
+
26
+ const.content_type_definition.fields.each_with_object({}) do |(name, f), h|
27
+ h[name.to_sym] = h[name.underscore.to_sym] = default_value(f)
28
+ end
29
+ end
30
+
31
+ ##
32
+ # Gets the default value for a contentful IndexedRepresentation::Field.
33
+ # This comes from the 'content_type_definition' of a contentful model class.
34
+ def default_value(field)
35
+ return [] if field.array
36
+ return unless field.required
37
+
38
+ val = DEFAULTS[field]
39
+ return val.call if val.respond_to?(:call)
40
+
41
+ val
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './attributes'
4
+
5
+ module WCC::Contentful::Test::Double
6
+ ##
7
+ # Builds a rspec double of the Contentful model for the given content_type.
8
+ # All attributes that are known to be required fields on the content type
9
+ # will return a default value based on the field type.
10
+ def contentful_double(content_type, **attrs)
11
+ const = WCC::Contentful::Model.resolve_constant(content_type)
12
+ attrs.symbolize_keys!
13
+
14
+ bad_attrs = attrs.reject { |a| const.instance_methods.include?(a) }
15
+ raise ArgumentError, "Attribute(s) do not exist on #{const}: #{bad_attrs.keys}" if bad_attrs.any?
16
+
17
+ double(attrs[:name] || attrs[:id] || nil, defaults(const).merge(attrs))
18
+ end
19
+
20
+ ##
21
+ # Builds an rspec double of a Contentful image asset, including the file
22
+ # URL and details. These fields can be overridden.
23
+ def contentful_image_double(**attrs)
24
+ attrs = {
25
+ title: WCC::Contentful::Test::Attributes[:String],
26
+ description: WCC::Contentful::Test::Attributes[:String],
27
+ file: {
28
+ url: '//images.ctfassets.net/7yx6/2rak/test.jpg',
29
+ details: {
30
+ image: {
31
+ width: 0,
32
+ height: 0
33
+ }
34
+ }
35
+ }
36
+ }.deep_merge!(attrs)
37
+
38
+ attrs[:file] = OpenStruct.new(attrs[:file]) if attrs[:file]
39
+
40
+ attrs[:raw] = {
41
+ sys: {
42
+ space: {
43
+ sys: {
44
+ type: 'Link',
45
+ linkType: 'Space',
46
+ id: ENV['CONTENTFUL_SPACE_ID']
47
+ }
48
+ },
49
+ id: SecureRandom.urlsafe_base64,
50
+ type: 'Asset',
51
+ createdAt: Time.now.to_s(:iso8601),
52
+ updatedAt: Time.now.to_s(:iso8601),
53
+ environment: {
54
+ sys: {
55
+ id: 'master',
56
+ type: 'Link',
57
+ linkType: 'Environment'
58
+ }
59
+ },
60
+ revision: rand(100),
61
+ locale: 'en-US'
62
+ },
63
+ fields: attrs.each_with_object({}) { |(k, v), h| h[k] = { 'en-US' => v } }
64
+ }
65
+
66
+ double(attrs)
67
+ end
68
+
69
+ private
70
+
71
+ def defaults(model)
72
+ attributes = WCC::Contentful::Test::Attributes.defaults(model)
73
+ methods = model.instance_methods - WCC::Contentful::Model.instance_methods
74
+ methods.each_with_object(attributes) { |f, h| h[f] ||= nil }
75
+ end
76
+ end
@@ -0,0 +1,125 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative './attributes'
4
+
5
+ module WCC::Contentful::Test::Factory
6
+ ##
7
+ # Builds a in-memory instance of the Contentful model for the given content_type.
8
+ # All attributes that are known to be required fields on the content type
9
+ # will return a default value based on the field type.
10
+ def contentful_create(content_type, **attrs)
11
+ const = WCC::Contentful::Model.resolve_constant(content_type.to_s)
12
+ attrs = attrs.transform_keys { |a| a.to_s.camelize(:lower) }
13
+
14
+ id = attrs.delete('id')
15
+ bad_attrs = attrs.reject { |a| const.content_type_definition.fields.key?(a) }
16
+ raise ArgumentError, "Attribute(s) do not exist on #{const}: #{bad_attrs.keys}" if bad_attrs.any?
17
+
18
+ default_instance(const, id).tap do |instance|
19
+ attrs.each do |k, v|
20
+ field = const.content_type_definition.fields[k]
21
+
22
+ raw = v
23
+ if %i[Asset Link].include?(field.type)
24
+ raw = to_raw(v, field.type)
25
+
26
+ unless field.array ? v.any? { |i| i.is_a?(String) } : v.is_a?(String)
27
+ instance.instance_variable_set("@#{field.name}_resolved", v)
28
+ end
29
+ end
30
+
31
+ instance.raw['fields'][field.name][instance.sys.locale] = raw
32
+ instance.instance_variable_set("@#{field.name}", raw)
33
+ end
34
+
35
+ def instance.to_s
36
+ "#<#{self.class.name} id=\"#{id}\">"
37
+ end
38
+ end
39
+ end
40
+
41
+ class Link
42
+ attr_reader :id
43
+ attr_reader :link_type
44
+ attr_reader :raw
45
+
46
+ LINK_TYPES = {
47
+ Asset: 'Asset',
48
+ Link: 'Entry'
49
+ }.freeze
50
+
51
+ def initialize(model, link_type = nil)
52
+ @id = model.try(:id) || model
53
+ @link_type = link_type
54
+ @link_type ||= model.is_a?(WCC::Contentful::Model::Asset) ? :Asset : :Link
55
+ @raw =
56
+ {
57
+ 'sys' => {
58
+ 'type' => 'Link',
59
+ 'linkType' => LINK_TYPES[@link_type],
60
+ 'id' => @id
61
+ }
62
+ }
63
+ end
64
+
65
+ alias_method :to_h, :raw
66
+ end
67
+
68
+ private
69
+
70
+ def default_instance(model, id = nil)
71
+ model.new(default_raw(model, id))
72
+ end
73
+
74
+ def default_raw(model, id = nil)
75
+ { sys: sys(model, id), fields: fields(model) }.as_json
76
+ end
77
+
78
+ def sys(model, id = nil)
79
+ {
80
+ space: {
81
+ sys: {
82
+ type: 'Link',
83
+ linkType: 'Space',
84
+ id: ENV['CONTENTFUL_SPACE_ID']
85
+ }
86
+ },
87
+ id: id || SecureRandom.urlsafe_base64,
88
+ type: 'Entry',
89
+ createdAt: Time.now.to_s(:iso8601),
90
+ updatedAt: Time.now.to_s(:iso8601),
91
+ environment: {
92
+ sys: {
93
+ id: 'master',
94
+ type: 'Link',
95
+ linkType: 'Environment'
96
+ }
97
+ },
98
+ revision: rand(100),
99
+ contentType: {
100
+ sys: {
101
+ type: 'Link',
102
+ linkType: 'ContentType',
103
+ id: model.content_type
104
+ }
105
+ },
106
+ locale: 'en-US'
107
+ }
108
+ end
109
+
110
+ def fields(model)
111
+ WCC::Contentful::Test::Attributes.defaults(model).each_with_object({}) do |(k, v), h|
112
+ h[k] = { 'en-US' => v }
113
+ end
114
+ end
115
+
116
+ def to_raw(val, field_type)
117
+ if val.is_a? Array
118
+ val.map { |i| to_raw(i, field_type) }
119
+ elsif val.is_a? String
120
+ Link.new(val, field_type).raw
121
+ elsif val
122
+ val.raw
123
+ end
124
+ end
125
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module WCC
4
4
  module Contentful
5
- VERSION = '0.4.0-alpha'
5
+ VERSION = '0.4.0-beta'
6
6
  end
7
7
  end
@@ -48,6 +48,7 @@ Gem::Specification.new do |spec|
48
48
  spec.add_development_dependency 'timecop', '~> 0.9.1'
49
49
 
50
50
  # optional dependencies
51
+ spec.add_development_dependency 'connection_pool', '~> 2.2'
51
52
  spec.add_development_dependency 'contentful', '2.6.0'
52
53
  spec.add_development_dependency 'contentful-management', '2.0.2'
53
54
  spec.add_development_dependency 'graphql', '~> 1.7'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wcc-contentful
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0.pre.alpha
4
+ version: 0.4.0.pre.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - Watermark Dev
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2018-10-17 00:00:00.000000000 Z
11
+ date: 2018-10-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coveralls
@@ -262,6 +262,20 @@ dependencies:
262
262
  - - "~>"
263
263
  - !ruby/object:Gem::Version
264
264
  version: 0.9.1
265
+ - !ruby/object:Gem::Dependency
266
+ name: connection_pool
267
+ requirement: !ruby/object:Gem::Requirement
268
+ requirements:
269
+ - - "~>"
270
+ - !ruby/object:Gem::Version
271
+ version: '2.2'
272
+ type: :development
273
+ prerelease: false
274
+ version_requirements: !ruby/object:Gem::Requirement
275
+ requirements:
276
+ - - "~>"
277
+ - !ruby/object:Gem::Version
278
+ version: '2.2'
265
279
  - !ruby/object:Gem::Dependency
266
280
  name: contentful
267
281
  requirement: !ruby/object:Gem::Requirement
@@ -431,6 +445,7 @@ files:
431
445
  - lib/wcc/contentful/model_methods.rb
432
446
  - lib/wcc/contentful/model_singleton_methods.rb
433
447
  - lib/wcc/contentful/rails.rb
448
+ - lib/wcc/contentful/rspec.rb
434
449
  - lib/wcc/contentful/services.rb
435
450
  - lib/wcc/contentful/simple_client.rb
436
451
  - lib/wcc/contentful/simple_client/http_adapter.rb
@@ -444,6 +459,10 @@ files:
444
459
  - lib/wcc/contentful/store/memory_store.rb
445
460
  - lib/wcc/contentful/store/postgres_store.rb
446
461
  - lib/wcc/contentful/sys.rb
462
+ - lib/wcc/contentful/test.rb
463
+ - lib/wcc/contentful/test/attributes.rb
464
+ - lib/wcc/contentful/test/double.rb
465
+ - lib/wcc/contentful/test/factory.rb
447
466
  - lib/wcc/contentful/version.rb
448
467
  - wcc-contentful.gemspec
449
468
  homepage: https://github.com/watermarkchurch/wcc-contentful/wcc-contentful
@@ -536,14 +555,33 @@ summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://
536
555
  You can also include the {WCC::Contentful::ServiceAccessors} concern to define these
537
556
  services as attributes in a class. ```ruby class MyJob < ApplicationJob include
538
557
  WCC::Contentful::ServiceAccessors def perform Page.find(...) store.find(...) client.entries(...)
539
- end end ``` ## Development After checking out the repo, run `bin/setup` to install
540
- dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console`
541
- for an interactive prompt that will allow you to experiment. To install this gem
542
- onto your local machine, run `bundle exec rake install`. To release a new version,
543
- update the version number in `version.rb`, and then run `bundle exec rake release`,
544
- which will create a git tag for the version, push git commits and tags, and push
545
- the `.gem` file to [rubygems.org](https://rubygems.org). ## Contributing Bug reports
546
- and pull requests are welcome on GitHub at https://github.com/watermarkchurch/wcc-contentful.
558
+ end end ``` ## Test Helpers To use the test helpers, include the following in
559
+ your rails_helper.rb: ```ruby require ''wcc/contentful/rspec'' ``` This adds the
560
+ following helpers to all your specs: ```ruby ## # Builds a in-memory instance of
561
+ the Contentful model for the given content_type. # All attributes that are known
562
+ to be required fields on the content type # will return a default value based on
563
+ the field type. instance = contentful_create(''my-content-type'', my_field: ''some-value'')
564
+ # => #<WCC::Contentful::Model::MyContentType:0x0000000005c71a78 @created_at=2018-04-16
565
+ 18:41:17 UTC...> instance.my_field # => "some-value" instance.other_required_field
566
+ # => "default-value" instance.other_optional_field # => nil instance.not_a_field
567
+ # NoMethodError: undefined method `not_a_field'' for #<Menu:0x00007fbac81ee490> ##
568
+ # Builds a rspec double of the Contentful model for the given content_type. # All
569
+ attributes that are known to be required fields on the content type # will return
570
+ a default value based on the field type. dbl = contentful_double(''my-content-type'',
571
+ my_field: ''other-value'') # => #<Double (anonymous)> dbl.my_field # => "other-value" dbl.not_a_field
572
+ # => #<Double (anonymous)> received unexpected message :not_a_field with (no args) ##
573
+ # Builds out a fake Contentful entry for the given content type, and then # stubs
574
+ the Model API to return that content type for `.find` and `.find_by` # query methods.
575
+ stubbed = contentful_stub(''my-content-type'', id: ''1234'', my_field: ''test'') WCC::Contentful::Model.find(''1234'')
576
+ == stubbed # => true MyContentType.find(''1234'') == stubbed # => true MyContentType.find_by(my_field:
577
+ ''test'') == stubbed # => true ``` ## Development After checking out the repo,
578
+ run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests.
579
+ You can also run `bin/console` for an interactive prompt that will allow you to
580
+ experiment. To install this gem onto your local machine, run `bundle exec rake
581
+ install`. To release a new version, update the version number in `version.rb`, and
582
+ then run `bundle exec rake release`, which will create a git tag for the version,
583
+ push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). ##
584
+ Contributing Bug reports and pull requests are welcome on GitHub at https://github.com/watermarkchurch/wcc-contentful.
547
585
  This project is intended to be a safe, welcoming space for collaboration, and contributors
548
586
  are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org)
549
587
  code of conduct. ## License The gem is available as open source under the terms