wcc-contentful 1.2.0 → 1.2.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.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/app/controllers/wcc/contentful/webhook_controller.rb +2 -0
  3. data/lib/tasks/download_schema.rake +1 -1
  4. data/lib/wcc/contentful/configuration.rb +31 -18
  5. data/lib/wcc/contentful/downloads_schema.rb +5 -4
  6. data/lib/wcc/contentful/engine.rb +2 -4
  7. data/lib/wcc/contentful/event.rb +2 -3
  8. data/lib/wcc/contentful/exceptions.rb +2 -3
  9. data/lib/wcc/contentful/indexed_representation.rb +2 -6
  10. data/lib/wcc/contentful/instrumentation.rb +2 -1
  11. data/lib/wcc/contentful/link.rb +1 -3
  12. data/lib/wcc/contentful/link_visitor.rb +2 -4
  13. data/lib/wcc/contentful/middleware/store/caching_middleware.rb +4 -8
  14. data/lib/wcc/contentful/middleware/store.rb +4 -6
  15. data/lib/wcc/contentful/model_api.rb +1 -3
  16. data/lib/wcc/contentful/model_builder.rb +5 -4
  17. data/lib/wcc/contentful/model_methods.rb +10 -12
  18. data/lib/wcc/contentful/model_singleton_methods.rb +1 -1
  19. data/lib/wcc/contentful/rich_text/node.rb +1 -3
  20. data/lib/wcc/contentful/rich_text.rb +1 -1
  21. data/lib/wcc/contentful/rspec.rb +1 -3
  22. data/lib/wcc/contentful/simple_client/response.rb +3 -5
  23. data/lib/wcc/contentful/simple_client.rb +11 -14
  24. data/lib/wcc/contentful/store/base.rb +5 -5
  25. data/lib/wcc/contentful/store/cdn_adapter.rb +1 -1
  26. data/lib/wcc/contentful/store/factory.rb +1 -1
  27. data/lib/wcc/contentful/store/memory_store.rb +2 -2
  28. data/lib/wcc/contentful/store/postgres_store.rb +15 -22
  29. data/lib/wcc/contentful/store/query.rb +2 -2
  30. data/lib/wcc/contentful/store/rspec_examples/include_param.rb +6 -4
  31. data/lib/wcc/contentful/store/rspec_examples/operators.rb +1 -1
  32. data/lib/wcc/contentful/sync_engine.rb +31 -15
  33. data/lib/wcc/contentful/sys.rb +2 -1
  34. data/lib/wcc/contentful/test/double.rb +3 -5
  35. data/lib/wcc/contentful/test/factory.rb +4 -6
  36. data/lib/wcc/contentful/version.rb +1 -1
  37. data/lib/wcc/contentful.rb +5 -7
  38. data/wcc-contentful.gemspec +5 -5
  39. metadata +8 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f05ea585d54f7ca83c96e018021f88776ebb148cc40b7d719d6199b3a3cd9d0c
4
- data.tar.gz: 0da490d12beb9938ec51c0ac40e140420966667b72afebc5c9895cf197308ea8
3
+ metadata.gz: 476f7c65f705c14e012e8c2cbb36f68e29782607377b0a4aa9d0c10fb93458da
4
+ data.tar.gz: 01aeff71919acef51c8d498c63bc42e822ed3c598e7c636f5faf74baeb74c552
5
5
  SHA512:
6
- metadata.gz: 979360a35356b041dbe0f8bbd4f0e5bfcaf91909ccc567322ceef8493de25300ea09a081e755142fe23bf9cfd5ea86ca7f919d3218d5dec44a98bcab5921af7d
7
- data.tar.gz: 9e5f29e70fdcbccffd72aeb8b896e3518d2236cd699704289e8a3fdf1392201dc49671bab0eb83948e79ee079366de90b46add4ce2027e065db2da28b2be4e85
6
+ metadata.gz: '0383a5fe8ef8b042d0a9aca04c964051fc5201b89e702a80b616e5c3b36fd6fa7590d768d178e96f3353c998923fc87458697f5b1112bdd000e6e273fdb07f56'
7
+ data.tar.gz: 776a6ec463edbcd209d28dd2033d6378ac45e44dd9bca790aefe81ea529c4fa4d0cf6725bd3f67e5c4054f41bd930e9905165f8ccd42f2a9f01b3bc0ac1deaf6
@@ -36,6 +36,7 @@ module WCC::Contentful
36
36
  def authorize_contentful
37
37
  config = WCC::Contentful.configuration
38
38
 
39
+ # rubocop:disable Style/SoleNestedConditional
39
40
  if config.webhook_username.present? && config.webhook_password.present?
40
41
  unless authenticate_with_http_basic do |u, p|
41
42
  u == config.webhook_username &&
@@ -45,6 +46,7 @@ module WCC::Contentful
45
46
  return
46
47
  end
47
48
  end
49
+ # rubocop:enable Style/SoleNestedConditional
48
50
 
49
51
  # 'application/vnd.contentful.management.v1+json' is an alias for the 'application/json'
50
52
  # content-type, so 'request.content_type' will give 'application/json'
@@ -5,7 +5,7 @@ require 'wcc/contentful/downloads_schema'
5
5
 
6
6
  namespace :wcc_contentful do
7
7
  desc 'Downloads the schema from the currently configured space and stores it in ' \
8
- 'db/contentful-schema.json'
8
+ 'db/contentful-schema.json'
9
9
  task download_schema: :environment do
10
10
  WCC::Contentful::DownloadsSchema.call
11
11
  end
@@ -3,22 +3,24 @@
3
3
  # This object contains all the configuration options for the `wcc-contentful` gem.
4
4
  class WCC::Contentful::Configuration
5
5
  ATTRIBUTES = %i[
6
- space
7
6
  access_token
8
7
  app_url
9
- management_token
10
- environment
11
- default_locale
12
- preview_token
13
- webhook_username
14
- webhook_password
15
- webhook_jobs
16
8
  connection
17
9
  connection_options
18
- update_schema_file
10
+ default_locale
11
+ environment
12
+ instrumentation_adapter
13
+ management_token
14
+ preview_token
19
15
  schema_file
16
+ space
20
17
  store
21
- instrumentation_adapter
18
+ sync_retry_limit
19
+ sync_retry_wait
20
+ update_schema_file
21
+ webhook_jobs
22
+ webhook_password
23
+ webhook_username
22
24
  ].freeze
23
25
 
24
26
  # (required) Sets the Contentful Space ID.
@@ -57,6 +59,17 @@ class WCC::Contentful::Configuration
57
59
  # to implement a webhook job.
58
60
  attr_accessor :webhook_jobs
59
61
 
62
+ # Sets the maximum number of times that the SyncEngine will retry synchronization
63
+ # when it detects that the Contentful CDN's cache has not been updated after a webhook.
64
+ # Default: 2
65
+ attr_accessor :sync_retry_limit
66
+
67
+ # Sets the base ActiveSupport::Duration that the SyncEngine will wait before retrying.
68
+ # Each subsequent retry uses an exponential backoff, so the second retry will be
69
+ # after (2 * sync_retry_wait), the third after (4 * sync_retry_wait), etc.
70
+ # Default: 2.seconds
71
+ attr_accessor :sync_retry_wait
72
+
60
73
  # Returns true if the currently configured environment is pointing at `master`.
61
74
  def master?
62
75
  !environment.present?
@@ -145,9 +158,7 @@ class WCC::Contentful::Configuration
145
158
  # WCC::Contentful::InitializationError if the API cannot be reached.
146
159
  def update_schema_file=(sym)
147
160
  valid_syms = %i[never if_possible if_missing always]
148
- unless valid_syms.include?(sym)
149
- raise ArgumentError, "update_schema_file must be one of #{valid_syms}"
150
- end
161
+ raise ArgumentError, "update_schema_file must be one of #{valid_syms}" unless valid_syms.include?(sym)
151
162
 
152
163
  @update_schema_file = sym
153
164
  end
@@ -172,22 +183,24 @@ class WCC::Contentful::Configuration
172
183
  attr_accessor :instrumentation_adapter
173
184
 
174
185
  def initialize
175
- @access_token = ENV['CONTENTFUL_ACCESS_TOKEN']
176
- @app_url = ENV['APP_URL']
186
+ @access_token = ENV.fetch('CONTENTFUL_ACCESS_TOKEN', nil)
187
+ @app_url = ENV.fetch('APP_URL', nil)
177
188
  @connection_options = {
178
189
  api_url: 'https://cdn.contentful.com/',
179
190
  preview_api_url: 'https://preview.contentful.com/',
180
191
  management_api_url: 'https://api.contentful.com'
181
192
  }
182
- @management_token = ENV['CONTENTFUL_MANAGEMENT_TOKEN']
183
- @preview_token = ENV['CONTENTFUL_PREVIEW_TOKEN']
184
- @space = ENV['CONTENTFUL_SPACE_ID']
193
+ @management_token = ENV.fetch('CONTENTFUL_MANAGEMENT_TOKEN', nil)
194
+ @preview_token = ENV.fetch('CONTENTFUL_PREVIEW_TOKEN', nil)
195
+ @space = ENV.fetch('CONTENTFUL_SPACE_ID', nil)
185
196
  @default_locale = nil
186
197
  @middleware = []
187
198
  @update_schema_file = :if_possible
188
199
  @schema_file = 'db/contentful-schema.json'
189
200
  @webhook_jobs = []
190
201
  @store_factory = WCC::Contentful::Store::Factory.new(self, :direct)
202
+ @sync_retry_limit = 3
203
+ @sync_retry_wait = 1.second
191
204
  end
192
205
 
193
206
  # Validates the configuration, raising ArgumentError if anything is wrong. This
@@ -36,7 +36,7 @@ class WCC::Contentful::DownloadsSchema
36
36
  begin
37
37
  JSON.parse(File.read(@file))
38
38
  rescue JSON::ParserError
39
- return true
39
+ return true # rubocop:disable Lint/NoReturnInBeginEndBlocks
40
40
  end
41
41
 
42
42
  existing_cts = contents['contentTypes'].sort_by { |ct| ct.dig('sys', 'id') }
@@ -83,13 +83,14 @@ class WCC::Contentful::DownloadsSchema
83
83
  end
84
84
 
85
85
  def deep_contains_all(expected, actual)
86
- if expected.is_a? Array
86
+ case expected
87
+ when Array
87
88
  expected.each_with_index do |val, i|
88
89
  return false unless actual[i]
89
90
  return false unless deep_contains_all(val, actual[i])
90
91
  end
91
92
  true
92
- elsif expected.is_a? Hash
93
+ when Hash
93
94
  expected.each do |(key, val)|
94
95
  return false unless actual.key?(key)
95
96
  return false unless deep_contains_all(val, actual[key])
@@ -107,6 +108,6 @@ class WCC::Contentful::DownloadsSchema
107
108
  # only in its treatment of empty arrays in the "validations" field.
108
109
  json_string = json_string.gsub(/\[\n\n\s+\]/, '[]')
109
110
  # contentful-shell also adds a newline at the end.
110
- json_string + "\n"
111
+ "#{json_string}\n"
111
112
  end
112
113
  end
@@ -6,9 +6,7 @@ module WCC::Contentful
6
6
  config = WCC::Contentful.configuration
7
7
 
8
8
  jobs = []
9
- if WCC::Contentful::Services.instance.sync_engine&.should_sync?
10
- jobs << WCC::Contentful::SyncEngine::Job
11
- end
9
+ jobs << WCC::Contentful::SyncEngine::Job if WCC::Contentful::Services.instance.sync_engine&.should_sync?
12
10
  jobs.push(*WCC::Contentful.configuration.webhook_jobs)
13
11
 
14
12
  jobs.each do |job|
@@ -19,7 +17,7 @@ module WCC::Contentful
19
17
  job.perform_later(event.to_h)
20
18
  else
21
19
  Rails.logger.error "Misconfigured webhook job: #{job} does not respond to " \
22
- ':perform_later'
20
+ ':perform_later'
23
21
  end
24
22
  rescue StandardError => e
25
23
  warn "Error in job #{job}: #{e}"
@@ -23,9 +23,7 @@ module WCC::Contentful::Event
23
23
 
24
24
  def register(constant)
25
25
  name = constant.try(:type) || constant.name.demodulize
26
- unless constant.respond_to?(:new)
27
- raise ArgumentError, "Constant #{constant} does not define 'new'"
28
- end
26
+ raise ArgumentError, "Constant #{constant} does not define 'new'" unless constant.respond_to?(:new)
29
27
 
30
28
  @event_types ||= {}
31
29
  @event_types[name] = constant
@@ -58,6 +56,7 @@ module WCC::Contentful::Event
58
56
  attr_reader :sys
59
57
  attr_reader :raw
60
58
  attr_reader :source
59
+
61
60
  delegate :id, to: :sys
62
61
  delegate :type, to: :sys
63
62
  delegate :created_at, to: :sys
@@ -12,8 +12,7 @@ module WCC::Contentful
12
12
  # Raised when an entry contains a circular reference and cannot be represented
13
13
  # as a flat tree.
14
14
  class CircularReferenceError < StandardError
15
- attr_reader :stack
16
- attr_reader :id
15
+ attr_reader :stack, :id
17
16
 
18
17
  def initialize(stack, id)
19
18
  @id = id
@@ -25,7 +24,7 @@ module WCC::Contentful
25
24
  return super unless stack
26
25
 
27
26
  super + "\n " \
28
- "#{stack.last} points to #{id} which is also it's ancestor\n " +
27
+ "#{stack.last} points to #{id} which is also it's ancestor\n " +
29
28
  stack.join('->')
30
29
  end
31
30
  end
@@ -109,9 +109,7 @@ module WCC::Contentful
109
109
  ].freeze
110
110
 
111
111
  def type=(raw_type)
112
- unless TYPES.include?(raw_type)
113
- raise ArgumentError, "Unknown type #{raw_type}, expected one of: #{TYPES}"
114
- end
112
+ raise ArgumentError, "Unknown type #{raw_type}, expected one of: #{TYPES}" unless TYPES.include?(raw_type)
115
113
 
116
114
  @type = raw_type
117
115
  end
@@ -131,9 +129,7 @@ module WCC::Contentful
131
129
 
132
130
  if raw_type = hash_or_id.delete('type')
133
131
  raw_type = raw_type.to_sym
134
- unless TYPES.include?(raw_type)
135
- raise ArgumentError, "Unknown type #{raw_type}, expected one of: #{TYPES}"
136
- end
132
+ raise ArgumentError, "Unknown type #{raw_type}, expected one of: #{TYPES}" unless TYPES.include?(raw_type)
137
133
 
138
134
  @type = raw_type
139
135
  end
@@ -7,11 +7,12 @@ module WCC::Contentful
7
7
  def _instrumentation_event_prefix
8
8
  @_instrumentation_event_prefix ||=
9
9
  # WCC::Contentful => contentful.wcc
10
- '.' + (is_a?(Class) || is_a?(Module) ? self : self.class)
10
+ '.' + (is_a?(Class) || is_a?(Module) ? self : self.class) # rubocop:disable Style/StringConcatenation
11
11
  .name.parameterize.split('-').reverse.join('.')
12
12
  end
13
13
 
14
14
  attr_writer :_instrumentation
15
+
15
16
  def _instrumentation
16
17
  # look for per-instance instrumentation then try class level
17
18
  @_instrumentation || self.class._instrumentation
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class WCC::Contentful::Link
4
- attr_reader :id
5
- attr_reader :link_type
6
- attr_reader :raw
4
+ attr_reader :id, :link_type, :raw
7
5
 
8
6
  LINK_TYPES = {
9
7
  Asset: 'Asset',
@@ -4,9 +4,7 @@
4
4
  # It is used internally by the Store layer to compose the resulting resolved hashes.
5
5
  # But you can use it too!
6
6
  class WCC::Contentful::LinkVisitor
7
- attr_reader :entry
8
- attr_reader :fields
9
- attr_reader :depth
7
+ attr_reader :entry, :fields, :depth
10
8
 
11
9
  # @param [Hash] entry The entry hash (resolved or unresolved) to walk
12
10
  # @param [Array<Symbol>] The type of fields to select from the entry tree.
@@ -66,7 +64,7 @@ class WCC::Contentful::LinkVisitor
66
64
 
67
65
  def each_field(field)
68
66
  each_locale(field) do |val, locale|
69
- if val&.is_a?(Array)
67
+ if val.is_a?(Array)
70
68
  val.each_with_index do |v, index|
71
69
  yield(v, field, locale, index) unless v.nil?
72
70
  end
@@ -36,12 +36,8 @@ module WCC::Contentful::Middleware::Store
36
36
  # figure out how to cache the results of a find_by query, ex:
37
37
  # `find_by('slug' => '/about')`
38
38
  def find_by(content_type:, filter: nil, options: nil)
39
- if filter&.keys == ['sys.id']
40
- # Direct ID lookup, like what we do in `WCC::Contentful::ModelMethods.resolve`
41
- # We can return just this item. Stores are not required to implement :include option.
42
- if found = @cache.read(filter['sys.id'])
43
- return found
44
- end
39
+ if filter&.keys == ['sys.id'] && found = @cache.read(filter['sys.id'])
40
+ return found
45
41
  end
46
42
 
47
43
  store.find_by(content_type: content_type, filter: filter, options: options)
@@ -79,8 +75,8 @@ module WCC::Contentful::Middleware::Store
79
75
  prev = @cache.read(id)
80
76
  return if prev.nil? && LAZILY_CACHEABLE_TYPES.include?(type)
81
77
 
82
- if (prev_rev = prev&.dig('sys', 'revision')) && (next_rev = json.dig('sys', 'revision'))
83
- return prev if next_rev < prev_rev
78
+ if (prev_rev = prev&.dig('sys', 'revision')) && (next_rev = json.dig('sys', 'revision')) && (next_rev < prev_rev)
79
+ return prev
84
80
  end
85
81
 
86
82
  # we also set DeletedEntry objects in the cache - no need to go hit the API when we know
@@ -96,9 +96,9 @@ module WCC::Contentful::Middleware::Store
96
96
 
97
97
  def count
98
98
  if middleware.has_select?
99
- raise NameError, "Count cannot be determined because the middleware '#{middleware}'" \
100
- " implements the #select? method. Please use '.to_a.count' to count entries that" \
101
- ' pass the #select? method.'
99
+ raise NameError, "Count cannot be determined because the middleware '#{middleware}' " \
100
+ "implements the #select? method. Please use '.to_a.count' to count entries that " \
101
+ 'pass the #select? method.'
102
102
  end
103
103
 
104
104
  # The wrapped query may get count from the "Total" field in the response,
@@ -112,9 +112,7 @@ module WCC::Contentful::Middleware::Store
112
112
  result = wrapped_query.to_enum
113
113
  result = result.select { |x| middleware.select?(x) } if middleware.has_select?
114
114
 
115
- if options && options[:include]
116
- result = result.map { |x| middleware.resolve_includes(x, options[:include]) }
117
- end
115
+ result = result.map { |x| middleware.resolve_includes(x, options[:include]) } if options && options[:include]
118
116
 
119
117
  result.map { |x| middleware.transform(x) }
120
118
  end
@@ -51,9 +51,7 @@ module WCC::Contentful::ModelAPI
51
51
 
52
52
  file = configuration.schema_file
53
53
  schema_json = JSON.parse(File.read(file))['contentTypes']
54
- unless schema_json
55
- raise ArgumentError, 'Please give either a JSON array of content types or file to load from'
56
- end
54
+ raise ArgumentError, 'Please give either a JSON array of content types or file to load from' unless schema_json
57
55
 
58
56
  @schema = WCC::Contentful::ContentTypeIndexer.from_json_schema(schema_json).types
59
57
  end
@@ -61,7 +61,7 @@ module WCC::Contentful
61
61
  ct = content_type_from_raw(raw)
62
62
  if ct != typedef.content_type
63
63
  raise ArgumentError, 'Wrong Content Type - ' \
64
- "'#{raw.dig('sys', 'id')}' is a #{ct}, expected #{typedef.content_type}"
64
+ "'#{raw.dig('sys', 'id')}' is a #{ct}, expected #{typedef.content_type}"
65
65
  end
66
66
  @raw = raw.freeze
67
67
 
@@ -107,12 +107,13 @@ module WCC::Contentful
107
107
  # array fields need to resolve to an empty array when nothing is there
108
108
  raw_value = []
109
109
  end
110
- instance_variable_set('@' + f.name, raw_value)
110
+ instance_variable_set("@#{f.name}", raw_value)
111
111
  end
112
112
  end
113
113
 
114
114
  attr_reader :sys
115
115
  attr_reader :raw
116
+
116
117
  delegate :id, to: :sys
117
118
  delegate :created_at, to: :sys
118
119
  delegate :updated_at, to: :sys
@@ -122,11 +123,11 @@ module WCC::Contentful
122
123
  # Make a field for each column:
123
124
  typedef.fields.each_value do |f|
124
125
  name = f.name
125
- var_name = '@' + name
126
+ var_name = "@#{name}"
126
127
  case f.type
127
128
  when :Asset, :Link
128
129
  define_method(name) do
129
- val = instance_variable_get(var_name + '_resolved')
130
+ val = instance_variable_get("#{var_name}_resolved")
130
131
  return val if val.present?
131
132
 
132
133
  _resolve_field(name)
@@ -54,17 +54,15 @@ module WCC::Contentful::ModelMethods
54
54
  _instrument 'resolve', id: id, depth: depth, backlinks: backlinked_ids do
55
55
  # use include param to do resolution
56
56
  store.find_by(content_type: self.class.content_type,
57
- filter: { 'sys.id' => id },
58
- options: context.except(*MODEL_LAYER_CONTEXT_KEYS).merge!({
59
- include: [depth, 10].min
60
- }))
57
+ filter: { 'sys.id' => id },
58
+ options: context.except(*MODEL_LAYER_CONTEXT_KEYS).merge!({
59
+ include: [depth, 10].min
60
+ }))
61
61
  end
62
- unless raw
63
- raise WCC::Contentful::ResolveError, "Cannot find #{self.class.content_type} with ID #{id}"
64
- end
62
+ raise WCC::Contentful::ResolveError, "Cannot find #{self.class.content_type} with ID #{id}" unless raw
65
63
 
66
64
  @raw = raw.freeze
67
- links.each { |f| instance_variable_set('@' + f, raw.dig('fields', f, sys.locale)) }
65
+ links.each { |f| instance_variable_set("@#{f}", raw.dig('fields', f, sys.locale)) }
68
66
  end
69
67
 
70
68
  links.each { |f| _resolve_field(f, depth, context, options) }
@@ -142,7 +140,7 @@ module WCC::Contentful::ModelMethods
142
140
  def _resolve_field(field_name, depth = 1, context = {}, options = {})
143
141
  return if depth <= 0
144
142
 
145
- var_name = '@' + field_name
143
+ var_name = "@#{field_name}"
146
144
  return unless val = instance_variable_get(var_name)
147
145
 
148
146
  context = sys.context.to_h.merge(context)
@@ -182,17 +180,17 @@ module WCC::Contentful::ModelMethods
182
180
  val = _try_map(val) { |v| load.call(v) }
183
181
  val = val.compact if val.is_a? Array
184
182
 
185
- instance_variable_set(var_name + '_resolved', val)
183
+ instance_variable_set("#{var_name}_resolved", val)
186
184
  rescue WCC::Contentful::CircularReferenceError
187
185
  raise unless options[:circular_reference] == :ignore
188
186
  end
189
187
  end
190
188
 
191
189
  def _resolved_field?(field_name, depth = 1)
192
- var_name = '@' + field_name
190
+ var_name = "@#{field_name}"
193
191
  raw = instance_variable_get(var_name)
194
192
  return true if raw.nil? || (raw.is_a?(Array) && raw.all?(&:nil?))
195
- return false unless val = instance_variable_get(var_name + '_resolved')
193
+ return false unless val = instance_variable_get("#{var_name}_resolved")
196
194
  return true if depth <= 1
197
195
 
198
196
  return val.resolved?(depth: depth - 1) unless val.is_a? Array
@@ -66,7 +66,7 @@ module WCC::Contentful::ModelSingletonMethods
66
66
  new(result, options) if result
67
67
  end
68
68
 
69
- def inherited(subclass)
69
+ def inherited(subclass) # rubocop:disable Lint/MissingSuper
70
70
  # If another different class is already registered for this content type,
71
71
  # don't auto-register this one.
72
72
  return if model_namespace.registered?(content_type)
@@ -37,9 +37,7 @@ module WCC::Contentful::RichText
37
37
  end
38
38
 
39
39
  def tokenize(raw, context = nil)
40
- unless raw['nodeType'] == node_type
41
- raise ArgumentError, "Expected '#{node_type}', got '#{raw['nodeType']}'"
42
- end
40
+ raise ArgumentError, "Expected '#{node_type}', got '#{raw['nodeType']}'" unless raw['nodeType'] == node_type
43
41
 
44
42
  values =
45
43
  members.map do |symbol|
@@ -43,7 +43,7 @@ module WCC::Contentful::RichText
43
43
  EmbeddedEntryBlock
44
44
  when 'embedded-asset-block'
45
45
  EmbeddedAssetBlock
46
- when /heading\-(\d+)/
46
+ when /heading-(\d+)/
47
47
  size = Regexp.last_match(1)
48
48
  const_get("Heading#{size}")
49
49
  else
@@ -13,9 +13,7 @@ module WCC::Contentful::RSpec
13
13
  # stubs the Model API to return that content type for `.find` and `.find_by`
14
14
  # query methods.
15
15
  def contentful_stub(const, **attrs)
16
- unless const.respond_to?(:content_type_definition)
17
- const = WCC::Contentful::Model.resolve_constant(const.to_s)
18
- end
16
+ const = WCC::Contentful::Model.resolve_constant(const.to_s) unless const.respond_to?(:content_type_definition)
19
17
  instance = contentful_create(const, **attrs)
20
18
 
21
19
  # mimic what's going on inside model_singleton_methods.rb
@@ -6,9 +6,7 @@ class WCC::Contentful::SimpleClient
6
6
  class Response
7
7
  include ::WCC::Contentful::Instrumentation
8
8
 
9
- attr_reader :raw_response
10
- attr_reader :client
11
- attr_reader :request
9
+ attr_reader :raw_response, :client, :request
12
10
 
13
11
  delegate :status, to: :raw_response
14
12
  alias_method :code, :status
@@ -26,7 +24,7 @@ class WCC::Contentful::SimpleClient
26
24
  def error_message
27
25
  parsed_message =
28
26
  begin
29
- raw.dig('message')
27
+ raw['message']
30
28
  rescue JSON::ParserError
31
29
  nil
32
30
  end
@@ -105,7 +103,7 @@ class WCC::Contentful::SimpleClient
105
103
 
106
104
  def includes
107
105
  @includes ||=
108
- raw.dig('includes')&.each_with_object({}) do |(_t, entries), h|
106
+ raw['includes']&.each_with_object({}) do |(_t, entries), h|
109
107
  entries.each { |e| h[e.dig('sys', 'id')] = e }
110
108
  end || {}
111
109
  end
@@ -24,8 +24,7 @@ module WCC::Contentful
24
24
  class SimpleClient
25
25
  include WCC::Contentful::Instrumentation
26
26
 
27
- attr_reader :api_url
28
- attr_reader :space
27
+ attr_reader :api_url, :space
29
28
 
30
29
  # Creates a new SimpleClient with the given configuration.
31
30
  #
@@ -41,7 +40,7 @@ module WCC::Contentful
41
40
  # @option options [Number] rate_limit_wait_timeout The maximum time to block the thread waiting
42
41
  # on a rate limit response. By default will wait for one 429 and then fail on the second 429.
43
42
  def initialize(api_url:, space:, access_token:, **options)
44
- @api_url = URI.join(api_url, '/spaces/', space + '/')
43
+ @api_url = URI.join(api_url, '/spaces/', "#{space}/")
45
44
  @space = space
46
45
  @access_token = access_token
47
46
 
@@ -57,7 +56,7 @@ module WCC::Contentful
57
56
 
58
57
  return unless options[:environment].present?
59
58
 
60
- @api_url = URI.join(@api_url, 'environments/', options[:environment] + '/')
59
+ @api_url = URI.join(@api_url, 'environments/', "#{options[:environment]}/")
61
60
  end
62
61
 
63
62
  # performs an HTTP GET request to the specified path within the configured
@@ -84,15 +83,13 @@ module WCC::Contentful
84
83
  case adapter
85
84
  when nil
86
85
  ADAPTERS.each do |a, spec|
87
- begin
88
- gem(*spec)
89
- return load_adapter(a)
90
- rescue Gem::LoadError
91
- next
92
- end
86
+ gem(*spec)
87
+ return load_adapter(a)
88
+ rescue Gem::LoadError
89
+ next
93
90
  end
94
- raise ArgumentError, 'Unable to load adapter! Please install one of '\
95
- "#{ADAPTERS.values.map(&:join).join(',')}"
91
+ raise ArgumentError, 'Unable to load adapter! Please install one of ' \
92
+ "#{ADAPTERS.values.map(&:join).join(',')}"
96
93
  when :faraday
97
94
  require 'faraday'
98
95
  ::Faraday.new do |faraday|
@@ -104,8 +101,8 @@ module WCC::Contentful
104
101
  TyphoeusAdapter.new
105
102
  else
106
103
  unless adapter.respond_to?(:get)
107
- raise ArgumentError, "Adapter #{adapter} is not invokeable! Please "\
108
- "pass use one of #{ADAPTERS.keys} or create a Faraday-compatible adapter"
104
+ raise ArgumentError, "Adapter #{adapter} is not invokeable! Please " \
105
+ "pass use one of #{ADAPTERS.keys} or create a Faraday-compatible adapter"
109
106
  end
110
107
  adapter
111
108
  end
@@ -61,11 +61,11 @@ module WCC::Contentful::Store
61
61
  set(json.dig('sys', 'id'), json)
62
62
  end
63
63
 
64
- if (prev_rev = prev&.dig('sys', 'revision')) && (next_rev = json.dig('sys', 'revision'))
65
- if next_rev < prev_rev
66
- # Uh oh! we overwrote an entry with a prior revision. Put the previous back.
67
- return index(prev)
68
- end
64
+ if (prev_rev = prev&.dig('sys', 'revision')) &&
65
+ (next_rev = json.dig('sys', 'revision')) &&
66
+ (next_rev < prev_rev)
67
+ # Uh oh! we overwrote an entry with a prior revision. Put the previous back.
68
+ return index(prev)
69
69
  end
70
70
 
71
71
  case type
@@ -3,7 +3,7 @@
3
3
  module WCC::Contentful::Store
4
4
  class CDNAdapter
5
5
  include WCC::Contentful::Store::Interface
6
- # Note: CDNAdapter should not instrument store events cause it's not a store.
6
+ # NOTE: CDNAdapter should not instrument store events cause it's not a store.
7
7
 
8
8
  attr_writer :client, :preview_client
9
9
 
@@ -90,7 +90,7 @@ module WCC::Contentful::Store
90
90
  next if m[0].respond_to?(:call)
91
91
 
92
92
  raise ArgumentError, "The middleware '#{m[0]&.try(:name) || m[0]}' cannot be applied! " \
93
- 'It must respond to :call'
93
+ 'It must respond to :call'
94
94
  end
95
95
 
96
96
  validate_store!(store)
@@ -41,8 +41,8 @@ module WCC::Contentful::Store
41
41
  SUPPORTED_OPS = %i[eq ne in nin].freeze
42
42
 
43
43
  def execute(query)
44
- (query.conditions.map(&:op) - SUPPORTED_OPS).each do |op|
45
- raise ArgumentError, "Operator :#{op} not supported"
44
+ if bad_op = (query.conditions.map(&:op) - SUPPORTED_OPS).first
45
+ raise ArgumentError, "Operator :#{bad_op} not supported"
46
46
  end
47
47
 
48
48
  relation = mutex.with_read_lock { @hash.values }
@@ -45,12 +45,9 @@ module WCC::Contentful::Store
45
45
  JSON.parse(val) if val
46
46
  end
47
47
 
48
- if views_need_update?(value, previous_value)
49
- # mark dirty - we need to refresh the materialized view
50
- unless mutex.with_read_lock { @dirty }
51
- _instrument 'mark_dirty'
52
- mutex.with_write_lock { @dirty = true }
53
- end
48
+ if views_need_update?(value, previous_value) && !mutex.with_read_lock { @dirty }
49
+ _instrument 'mark_dirty'
50
+ mutex.with_write_lock { @dirty = true }
54
51
  end
55
52
 
56
53
  previous_value
@@ -105,7 +102,7 @@ module WCC::Contentful::Store
105
102
  end
106
103
  end
107
104
 
108
- logger&.debug('[PostgresStore] ' + statement + "\n" + params.inspect)
105
+ logger&.debug("[PostgresStore] #{statement}\n#{params.inspect}")
109
106
  _instrument 'exec' do
110
107
  @connection_pool.with { |conn| conn.exec(statement, params) }
111
108
  end
@@ -231,16 +228,12 @@ module WCC::Contentful::Store
231
228
  end
232
229
 
233
230
  statement =
234
- select_statement +
235
- " FROM #{table} AS t \n" +
236
- joins.join("\n") + "\n" +
237
- statement +
238
- (limit_statement || '')
231
+ "#{select_statement} FROM #{table} AS t \n#{joins.join("\n")}\n#{statement}#{limit_statement || ''}"
239
232
 
240
233
  [statement, params]
241
234
  end
242
235
 
243
- def _eq(path, expected, params)
236
+ def _eq(path, expected, params) # rubocop:disable Layout/LineContinuationLeadingSpace
244
237
  return " AND t.id = $#{push_param(expected, params)}" if path == %w[sys id]
245
238
 
246
239
  if path[3] == 'sys'
@@ -248,12 +241,12 @@ module WCC::Contentful::Store
248
241
  # into it to detect whether it contains `{ "sys": { "id" => expected } }`
249
242
  expected = { 'sys' => { path[4] => expected } }.to_json
250
243
  return ' AND fn_contentful_jsonb_any_to_jsonb_array(t.data->' \
251
- "#{quote_parameter_path(path.take(3))}) @> " \
252
- "jsonb_build_array($#{push_param(expected, params)}::jsonb)"
244
+ "#{quote_parameter_path(path.take(3))}) @> " \
245
+ "jsonb_build_array($#{push_param(expected, params)}::jsonb)"
253
246
  end
254
247
 
255
- " AND t.data->#{quote_parameter_path(path)}" \
256
- " @> to_jsonb($#{push_param(expected, params)})"
248
+ " AND t.data->#{quote_parameter_path(path)} " \
249
+ "@> to_jsonb($#{push_param(expected, params)})"
257
250
  end
258
251
 
259
252
  PARAM_TYPES = {
@@ -292,7 +285,7 @@ module WCC::Contentful::Store
292
285
  def push_join(_path, joins)
293
286
  table_alias = "s#{joins.length}"
294
287
  joins << "JOIN contentful_raw AS #{table_alias} ON " \
295
- "#{table_alias}.id=ANY(t.links)"
288
+ "#{table_alias}.id=ANY(t.links)"
296
289
  table_alias
297
290
  end
298
291
  end
@@ -326,8 +319,8 @@ module WCC::Contentful::Store
326
319
  end
327
320
 
328
321
  def schema_ensured?(conn)
329
- result = conn.exec('SELECT version FROM wcc_contentful_schema_version' \
330
- ' ORDER BY version DESC LIMIT 1')
322
+ result = conn.exec('SELECT version FROM wcc_contentful_schema_version ' \
323
+ 'ORDER BY version DESC LIMIT 1')
331
324
  return false if result.num_tuples == 0
332
325
 
333
326
  result[0]['version'].to_i >= EXPECTED_VERSION
@@ -339,8 +332,8 @@ module WCC::Contentful::Store
339
332
  def ensure_schema(conn)
340
333
  result =
341
334
  begin
342
- conn.exec('SELECT version FROM wcc_contentful_schema_version' \
343
- ' ORDER BY version DESC')
335
+ conn.exec('SELECT version FROM wcc_contentful_schema_version ' \
336
+ 'ORDER BY version DESC')
344
337
  rescue PG::UndefinedTable
345
338
  []
346
339
  end
@@ -36,7 +36,7 @@ module WCC::Contentful::Store
36
36
 
37
37
  FALSE_VALUES = [
38
38
  false, 0,
39
- '0', :"0",
39
+ '0', :'0',
40
40
  'f', :f,
41
41
  'F', :F,
42
42
  'false', :false, # rubocop:disable Lint/BooleanSymbol
@@ -237,7 +237,7 @@ module WCC::Contentful::Store
237
237
 
238
238
  Condition =
239
239
  Struct.new(:path, :op, :expected) do
240
- LINK_KEYS = %w[id type linkType].freeze
240
+ LINK_KEYS = %w[id type linkType].freeze # rubocop:disable Lint/ConstantDefinitionInBlock
241
241
 
242
242
  def path_tuples
243
243
  @path_tuples ||=
@@ -15,10 +15,12 @@ RSpec.shared_examples 'supports include param' do |feature_set|
15
15
  'fields' => {
16
16
  'name' => { 'en-US' => 'root' },
17
17
  'link' => { 'en-US' => make_link_to('deep1') },
18
- 'links' => { 'en-US' => [
19
- make_link_to('shallow3'),
20
- make_link_to('deep2')
21
- ] }
18
+ 'links' => {
19
+ 'en-US' => [
20
+ make_link_to('shallow3'),
21
+ make_link_to('deep2')
22
+ ]
23
+ }
22
24
  }
23
25
  }
24
26
  end
@@ -40,7 +40,7 @@ RSpec.shared_examples 'operators' do |feature_set|
40
40
  end
41
41
  end
42
42
 
43
- supported_operators.each do |op, value|
43
+ supported_operators.each do |op, value| # rubocop:disable Style/CombinableLoops
44
44
  next unless value
45
45
 
46
46
  it_behaves_like "supports :#{op} operator" do
@@ -31,15 +31,18 @@ module WCC::Contentful
31
31
  (@state&.dup || token_wrapper_factory(nil)).freeze
32
32
  end
33
33
 
34
- attr_reader :store
35
- attr_reader :client
34
+ attr_reader :store, :client, :options
36
35
 
37
36
  def should_sync?
38
37
  store&.index?
39
38
  end
40
39
 
41
- def initialize(state: nil, store: nil, client: nil, key: nil)
42
- @state_key = key || "sync:#{object_id}"
40
+ def initialize(client: nil, store: nil, state: nil, **options)
41
+ @options = {
42
+ key: "sync:#{object_id}"
43
+ }.merge!(options).freeze
44
+
45
+ @state_key = @options[:key] || "sync:#{object_id}"
43
46
  @client = client || WCC::Contentful::Services.instance.client
44
47
  @mutex = Mutex.new
45
48
 
@@ -53,9 +56,7 @@ module WCC::Contentful
53
56
  if state
54
57
  @state = token_wrapper_factory(state)
55
58
  raise ArgumentError, ':state param must be a String or Hash' unless @state.is_a? Hash
56
- unless @state.dig('sys', 'type') == 'token'
57
- raise ArgumentError, ':state param must be of sys.type = "token"'
58
- end
59
+ raise ArgumentError, ':state param must be of sys.type = "token"' unless @state.dig('sys', 'type') == 'token'
59
60
  end
60
61
  raise ArgumentError, 'either :state or :store must be provided' unless @state || @store
61
62
  end
@@ -144,8 +145,12 @@ module WCC::Contentful
144
145
  return unless sync_engine&.should_sync?
145
146
 
146
147
  up_to_id = nil
147
- up_to_id = event[:up_to_id] || event.dig('sys', 'id') if event
148
- sync!(up_to_id: up_to_id)
148
+ retry_count = 0
149
+ if event
150
+ up_to_id = event[:up_to_id] || event.dig('sys', 'id')
151
+ retry_count = event[:retry_count] if event[:retry_count]
152
+ end
153
+ sync!(up_to_id: up_to_id, retry_count: retry_count)
149
154
  end
150
155
 
151
156
  # Calls the Contentful Sync API and updates the configured store with the returned
@@ -156,21 +161,32 @@ module WCC::Contentful
156
161
  # If we don't find this ID in the sync data, then drop a job to try
157
162
  # the sync again after a few minutes.
158
163
  #
159
- def sync!(up_to_id: nil)
164
+ def sync!(up_to_id: nil, retry_count: 0)
160
165
  id_found, count = sync_engine.next(up_to_id: up_to_id)
161
166
 
162
167
  next_sync_token = sync_engine.state['token']
163
168
 
164
169
  logger.info "Synced #{count} entries. Next sync token:\n #{next_sync_token}"
165
- logger.info "Should enqueue again? [#{!id_found}]"
166
- # Passing nil to only enqueue the job 1 more time
167
- sync_later!(up_to_id: nil) unless id_found
170
+ unless id_found
171
+ if retry_count >= configuration.sync_retry_limit
172
+ logger.error "Unable to find item with id '#{up_to_id}' on the Sync API. " \
173
+ "Abandoning after #{retry_count} retries."
174
+ else
175
+ wait = (2**retry_count) * configuration.sync_retry_wait.seconds
176
+ logger.info "Unable to find item with id '#{up_to_id}' on the Sync API. " \
177
+ "Retrying after #{wait.inspect} " \
178
+ "(#{configuration.sync_retry_limit - retry_count} retries remaining)"
179
+
180
+ self.class.set(wait: wait)
181
+ .perform_later(up_to_id: up_to_id, retry_count: retry_count + 1)
182
+ end
183
+ end
168
184
  next_sync_token
169
185
  end
170
186
 
171
- # Drops an ActiveJob job to invoke WCC::Contentful.sync! after a given amount
187
+ # Enqueues an ActiveJob job to invoke WCC::Contentful.sync! after a given amount
172
188
  # of time.
173
- def sync_later!(up_to_id: nil, wait: 10.minutes)
189
+ def sync_later!(up_to_id: nil, wait: 10.seconds)
174
190
  self.class.set(wait: wait)
175
191
  .perform_later(up_to_id: up_to_id)
176
192
  end
@@ -11,7 +11,7 @@ WCC::Contentful::Sys =
11
11
  :revision,
12
12
  :context
13
13
  ) do
14
-
14
+ # rubocop:disable Lint/ConstantDefinitionInBlock
15
15
  ATTRIBUTES = %i[
16
16
  id
17
17
  type
@@ -22,6 +22,7 @@ WCC::Contentful::Sys =
22
22
  revision
23
23
  context
24
24
  ].freeze
25
+ # rubocop:enable Lint/ConstantDefinitionInBlock
25
26
 
26
27
  undef []=
27
28
  ATTRIBUTES.each { |a| __send__(:undef_method, "#{a}=") }
@@ -8,9 +8,7 @@ module WCC::Contentful::Test::Double
8
8
  # All attributes that are known to be required fields on the content type
9
9
  # will return a default value based on the field type.
10
10
  def contentful_double(const, **attrs)
11
- unless const.respond_to?(:content_type_definition)
12
- const = WCC::Contentful::Model.resolve_constant(const.to_s)
13
- end
11
+ const = WCC::Contentful::Model.resolve_constant(const.to_s) unless const.respond_to?(:content_type_definition)
14
12
  attrs.symbolize_keys!
15
13
 
16
14
  bad_attrs = attrs.reject { |a| const.instance_methods.include?(a) }
@@ -45,7 +43,7 @@ module WCC::Contentful::Test::Double
45
43
  sys: {
46
44
  type: 'Link',
47
45
  linkType: 'Space',
48
- id: ENV['CONTENTFUL_SPACE_ID']
46
+ id: ENV.fetch('CONTENTFUL_SPACE_ID', nil)
49
47
  }
50
48
  },
51
49
  id: SecureRandom.urlsafe_base64,
@@ -62,7 +60,7 @@ module WCC::Contentful::Test::Double
62
60
  revision: rand(100),
63
61
  locale: 'en-US'
64
62
  },
65
- fields: attrs.each_with_object({}) { |(k, v), h| h[k] = { 'en-US' => v } }
63
+ fields: attrs.transform_values { |v| { 'en-US' => v } }
66
64
  }
67
65
 
68
66
  double(attrs)
@@ -8,9 +8,7 @@ module WCC::Contentful::Test::Factory
8
8
  # All attributes that are known to be required fields on the content type
9
9
  # will return a default value based on the field type.
10
10
  def contentful_create(const, context = nil, **attrs)
11
- unless const.respond_to?(:content_type_definition)
12
- const = WCC::Contentful::Model.resolve_constant(const.to_s)
13
- end
11
+ const = WCC::Contentful::Model.resolve_constant(const.to_s) unless const.respond_to?(:content_type_definition)
14
12
  attrs = attrs.transform_keys { |a| a.to_s.camelize(:lower) }
15
13
 
16
14
  id = attrs.delete('id')
@@ -59,7 +57,7 @@ module WCC::Contentful::Test::Factory
59
57
  sys: {
60
58
  type: 'Link',
61
59
  linkType: 'Space',
62
- id: ENV['CONTENTFUL_SPACE_ID']
60
+ id: ENV.fetch('CONTENTFUL_SPACE_ID', nil)
63
61
  }
64
62
  },
65
63
  id: id || SecureRandom.urlsafe_base64,
@@ -86,8 +84,8 @@ module WCC::Contentful::Test::Factory
86
84
  end
87
85
 
88
86
  def contentful_fields(model)
89
- WCC::Contentful::Test::Attributes.defaults(model).each_with_object({}) do |(k, v), h|
90
- h[k] = { 'en-US' => v }
87
+ WCC::Contentful::Test::Attributes.defaults(model).transform_values do |v|
88
+ { 'en-US' => v }
91
89
  end
92
90
  end
93
91
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module WCC
4
4
  module Contentful
5
- VERSION = '1.2.0'
5
+ VERSION = '1.2.1'
6
6
  end
7
7
  end
@@ -48,7 +48,7 @@ module WCC::Contentful
48
48
  def logger
49
49
  return Rails.logger if defined?(Rails)
50
50
 
51
- @logger ||= Logger.new(STDERR)
51
+ @logger ||= Logger.new($stderr)
52
52
  end
53
53
  end
54
54
 
@@ -82,7 +82,7 @@ module WCC::Contentful
82
82
 
83
83
  if configuration.update_schema_file == :always ||
84
84
  (configuration.update_schema_file == :if_possible && Services.instance.management_client) ||
85
- configuration.update_schema_file == :if_missing && !File.exist?(configuration.schema_file)
85
+ (configuration.update_schema_file == :if_missing && !File.exist?(configuration.schema_file))
86
86
 
87
87
  begin
88
88
  downloader = WCC::Contentful::DownloadsSchema.new
@@ -96,9 +96,7 @@ module WCC::Contentful
96
96
 
97
97
  content_types =
98
98
  begin
99
- if File.exist?(configuration.schema_file)
100
- JSON.parse(File.read(configuration.schema_file))['contentTypes']
101
- end
99
+ JSON.parse(File.read(configuration.schema_file))['contentTypes'] if File.exist?(configuration.schema_file)
102
100
  rescue JSON::ParserError
103
101
  WCC::Contentful.logger.warn("Schema file invalid, ignoring it: #{configuration.schema_file}")
104
102
  nil
@@ -119,8 +117,8 @@ module WCC::Contentful
119
117
  end
120
118
 
121
119
  unless content_types
122
- raise InitializationError, 'Unable to load content types from schema file or API!' \
123
- ' Check your access token and space ID.'
120
+ raise InitializationError, 'Unable to load content types from schema file or API! ' \
121
+ 'Check your access token and space ID.'
124
122
  end
125
123
 
126
124
  # Set the schema on the default WCC::Contentful::Model
@@ -6,7 +6,7 @@ require 'wcc/contentful/version'
6
6
 
7
7
  doc_version = Gem::Version.new(WCC::Contentful::VERSION).release.to_s.sub(/\.\d+$/, '')
8
8
 
9
- # rubocop:disable Metrics/LineLength
9
+ # rubocop:disable Layout/LineLength
10
10
  Gem::Specification.new do |spec|
11
11
  spec.name = 'wcc-contentful'
12
12
  spec.version = WCC::Contentful::VERSION
@@ -19,10 +19,11 @@ Gem::Specification.new do |spec|
19
19
  spec.license = 'MIT'
20
20
 
21
21
  spec.metadata = {
22
- 'documentation_uri' => "https://watermarkchurch.github.io/wcc-contentful/#{doc_version}/wcc-contentful"
22
+ 'documentation_uri' => "https://watermarkchurch.github.io/wcc-contentful/#{doc_version}/wcc-contentful",
23
+ 'rubygems_mfa_required' => 'true'
23
24
  }
24
25
 
25
- spec.required_ruby_version = '>= 2.3'
26
+ spec.required_ruby_version = '>= 2.7'
26
27
 
27
28
  spec.files = Dir['app/**/*', 'config/**/*', 'lib/**/*'] +
28
29
  %w[Rakefile README.md wcc-contentful.gemspec]
@@ -38,7 +39,6 @@ Gem::Specification.new do |spec|
38
39
  spec.add_development_dependency 'rspec', '~> 3.0'
39
40
  spec.add_development_dependency 'rspec-instrumentation-matcher'
40
41
  spec.add_development_dependency 'rspec_junit_formatter', '~> 0.4.1'
41
- spec.add_development_dependency 'rubocop', '0.68'
42
42
  spec.add_development_dependency 'simplecov', '~> 0.16.1'
43
43
  spec.add_development_dependency 'vcr', '~> 5.0'
44
44
  spec.add_development_dependency 'webmock', '~> 3.0'
@@ -68,4 +68,4 @@ Gem::Specification.new do |spec|
68
68
  spec.add_dependency 'wcc-base', '~> 0.3.1'
69
69
  spec.add_dependency 'wisper', '~> 2.0.0'
70
70
  end
71
- # rubocop:enable Metrics/LineLength
71
+ # rubocop:enable Layout/LineLength
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: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Watermark Dev
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-30 00:00:00.000000000 Z
11
+ date: 2022-08-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: byebug
@@ -136,20 +136,6 @@ dependencies:
136
136
  - - "~>"
137
137
  - !ruby/object:Gem::Version
138
138
  version: 0.4.1
139
- - !ruby/object:Gem::Dependency
140
- name: rubocop
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - '='
144
- - !ruby/object:Gem::Version
145
- version: '0.68'
146
- type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
150
- - - '='
151
- - !ruby/object:Gem::Version
152
- version: '0.68'
153
139
  - !ruby/object:Gem::Dependency
154
140
  name: simplecov
155
141
  requirement: !ruby/object:Gem::Requirement
@@ -504,7 +490,8 @@ licenses:
504
490
  - MIT
505
491
  metadata:
506
492
  documentation_uri: https://watermarkchurch.github.io/wcc-contentful/1.2/wcc-contentful
507
- post_install_message:
493
+ rubygems_mfa_required: 'true'
494
+ post_install_message:
508
495
  rdoc_options: []
509
496
  require_paths:
510
497
  - lib
@@ -512,15 +499,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
512
499
  requirements:
513
500
  - - ">="
514
501
  - !ruby/object:Gem::Version
515
- version: '2.3'
502
+ version: '2.7'
516
503
  required_rubygems_version: !ruby/object:Gem::Requirement
517
504
  requirements:
518
505
  - - ">="
519
506
  - !ruby/object:Gem::Version
520
507
  version: '0'
521
508
  requirements: []
522
- rubygems_version: 3.3.7
523
- signing_key:
509
+ rubygems_version: 3.1.6
510
+ signing_key:
524
511
  specification_version: 4
525
512
  summary: '[![Gem Version](https://badge.fury.io/rb/wcc-contentful.svg)](https://rubygems.org/gems/wcc-contentful)
526
513
  [![Build Status](https://circleci.com/gh/watermarkchurch/wcc-contentful.svg?style=svg)](https://circleci.com/gh/watermarkchurch/wcc-contentful)