cache_crispies 1.1.1 → 1.3.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 50a80f969f0b9fc34f7c562df3ac6dc880503f1bc5aefd41ff1204b8b316bfb7
4
- data.tar.gz: 56474213e7cc52191ebc4a4083a7c82e998639c2ad90eb3bbe2bc0ab9a1701ed
3
+ metadata.gz: 61b89840db0deaa5b7ab40ee7df2a84709a851104aa7b82bb4f95b58faaaa3d3
4
+ data.tar.gz: 7b6ca695376f955ff0170795abb91b733c6521fb6827975f66f9086f2f7d6a11
5
5
  SHA512:
6
- metadata.gz: 3087ba57bb1db1bf7b27ae13d2e0ba9f11a31359218548b56c8e26555b6368b9f1c37bdd98529d56a9bc3d8b438fcaf97dea68734ebff9c6b25aac629346c463
7
- data.tar.gz: 223e0010500a5dc2bc9edef1db6f99804c3fce19ca08e28d516f789ee3980ff7a59ee8b4e85ebda00eb336c61b3c9b76ebcacdbd7f60dc14eb679226f4ff23d2
6
+ metadata.gz: 82c7a2f92695a8d304eecb276d6ed29d436dea85e46eaa6b1dc18f1139df7bc8594498f7352d5e14856c2bbb00007a2e5ccffff2bc4cbe21d815f4efb7964c27
7
+ data.tar.gz: 4781943a5e5845cd72f0c99237b855fe65cc87b57bbb0554d76951a8296449db922e67d09da8a26a68443e5fd55614cbf0b4a655b90f1eaa6961bdf8affcdb6b
@@ -19,6 +19,7 @@ module CacheCrispies
19
19
  autoload :Base, 'cache_crispies/base'
20
20
  autoload :Collection, 'cache_crispies/collection'
21
21
  autoload :Condition, 'cache_crispies/condition'
22
+ autoload :Optional, 'cache_crispies/optional'
22
23
  autoload :Configuration, 'cache_crispies/configuration'
23
24
  autoload :HashBuilder, 'cache_crispies/hash_builder'
24
25
  autoload :Memoizer, 'cache_crispies/memoizer'
@@ -15,6 +15,8 @@ module CacheCrispies
15
15
  # @param with [CacheCrispies::Base] a serializer to use to serialize the
16
16
  # @param to [Class, Symbol] the data type to coerce the value into
17
17
  # @param collection [Boolean] force rendering as single or collection
18
+ # @param optional [Boolean] render only if included in the option's
19
+ # `included` array
18
20
  # @param nesting [Array<Symbol>] the JSON keys this attribute will be
19
21
  # nested inside
20
22
  # @param conditions [Array<CacheCrispies::Condition>] the show_if condition
@@ -24,6 +26,7 @@ module CacheCrispies
24
26
  def initialize(
25
27
  key,
26
28
  from: nil, with: nil, through: nil, to: nil, collection: nil,
29
+ optional: nil,
27
30
  nesting: [], conditions: [],
28
31
  &block
29
32
  )
@@ -36,6 +39,8 @@ module CacheCrispies
36
39
  @nesting = Array(nesting)
37
40
  @conditions = Array(conditions)
38
41
  @block = block
42
+
43
+ @conditions << Optional.new(key) if optional
39
44
  end
40
45
 
41
46
  attr_reader(
@@ -221,9 +221,11 @@ module CacheCrispies
221
221
  def self.serialize(
222
222
  *attribute_names,
223
223
  from: nil, with: nil, through: nil, to: nil, collection: nil,
224
+ optional: nil,
224
225
  &block
225
226
  )
226
- attribute_names.flatten.map { |att| att&.to_sym }.map do |attrib|
227
+ attribute_names.flat_map do |attrib|
228
+ attrib = attrib&.to_sym
227
229
  current_nesting = Array(@nesting).dup
228
230
  current_conditions = Array(@conditions).dup
229
231
 
@@ -235,6 +237,7 @@ module CacheCrispies
235
237
  through: through,
236
238
  to: to,
237
239
  collection: collection,
240
+ optional: optional,
238
241
  nesting: current_nesting,
239
242
  conditions: current_conditions,
240
243
  &block
@@ -19,24 +19,29 @@ module CacheCrispies
19
19
  block.object_id
20
20
  end
21
21
 
22
- # Test the truthiness of the condition against a model and options
22
+ # Test the truthiness of the condition against the serializer instance
23
23
  #
24
- # @param model [Object] typically ActiveRecord::Base, but could be anything
25
- # @param options [Hash] any optional values from the serializer instance
24
+ # @param serializer [Object] CacheCrispies::Base serializer instance
26
25
  # @return [Boolean] the condition's truthiness
27
- def true_for?(model, options = {})
28
- !!case block.arity
29
- when 0
30
- block.call
31
- when 1
32
- block.call(model)
33
- else
34
- block.call(model, options)
35
- end
26
+ def true_for?(serializer)
27
+ return !!serializer.public_send(block) if block.is_a?(Symbol)
28
+
29
+ !!execute_block(serializer.model, serializer.options)
36
30
  end
37
31
 
38
32
  private
39
33
 
40
34
  attr_reader :block
35
+
36
+ def execute_block(model, options)
37
+ case block.arity
38
+ when 0
39
+ block.call
40
+ when 1
41
+ block.call(model)
42
+ else
43
+ block.call(model, options)
44
+ end
45
+ end
41
46
  end
42
47
  end
@@ -6,7 +6,8 @@ module CacheCrispies
6
6
  class Configuration
7
7
  SETTINGS = [
8
8
  :cache_store,
9
- :etags
9
+ :etags,
10
+ :cache_key_method
10
11
  ].freeze
11
12
 
12
13
  SETTINGS.each do |setting|
@@ -18,11 +19,13 @@ module CacheCrispies
18
19
  end
19
20
 
20
21
  alias etags? etags
22
+ alias cache_key_method? cache_key_method
21
23
 
22
24
  # Resets all values to their defaults. Useful for testing.
23
25
  def reset!
24
26
  @cache_store = Rails.cache || ActiveSupport::Cache::NullStore.new
25
27
  @etags = false
28
+ @cache_key_method = :cache_key
26
29
  end
27
30
  end
28
31
  end
@@ -16,18 +16,20 @@ module CacheCrispies
16
16
  #
17
17
  # @return [Hash]
18
18
  def call
19
+ return unless @serializer.model
20
+
19
21
  hash = {}
20
22
 
21
23
  serializer.attributes.each do |attrib|
22
24
  deepest_hash = hash
23
25
 
26
+ next unless show?(attrib)
27
+
24
28
  attrib.nesting.each do |key|
25
29
  deepest_hash[key] ||= {}
26
30
  deepest_hash = deepest_hash[key]
27
31
  end
28
32
 
29
- next unless show?(attrib)
30
-
31
33
  value = value_for(attrib)
32
34
 
33
35
  if attrib.key
@@ -49,7 +51,7 @@ module CacheCrispies
49
51
  # show_if block
50
52
  attribute.conditions.all? do |cond|
51
53
  condition_results.fetch(cond.uid) do
52
- cond.true_for?(serializer.model, serializer.options)
54
+ cond.true_for?(serializer)
53
55
  end
54
56
  end
55
57
  end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module CacheCrispies
4
+ # Represents an optional condition
5
+ class Optional
6
+ # Returns a new instance of Optional
7
+ #
8
+ # @param block [Proc] the key of the attribute to include
9
+ def initialize(key)
10
+ @key = key
11
+ end
12
+
13
+ # A system-wide unique ID used for memoizaiton
14
+ #
15
+ # @eturn [Integer] the unique ID for this condition
16
+ def uid
17
+ # Just reusing the key seems to make sense
18
+ key
19
+ end
20
+
21
+ # Test the truthiness of the optional condition against a model and options
22
+ #
23
+ # @param model [Object] typically ActiveRecord::Base, but could be anything
24
+ # @param options [Hash] any optional values from the serializer instance
25
+ # @return [Boolean] the condition's truthiness
26
+ def true_for?(serializer)
27
+ included = Array(serializer.options.fetch(:include, [])).map(&:to_sym)
28
+
29
+ included.include?(key) || included.include?(:*)
30
+ end
31
+
32
+ private
33
+
34
+ attr_reader :key
35
+ end
36
+ end
@@ -58,7 +58,7 @@ module CacheCrispies
58
58
  serializer.cache_key_base,
59
59
  serializer.dependency_key,
60
60
  addons_key,
61
- cacheable.cache_key
61
+ cacheable_cache_key
62
62
  ].flatten.compact.join(CACHE_KEY_SEPARATOR)
63
63
  end
64
64
 
@@ -101,7 +101,11 @@ module CacheCrispies
101
101
  end
102
102
 
103
103
  def cache?
104
- serializer.do_caching? && cacheable.respond_to?(:cache_key)
104
+ serializer.do_caching? && cacheable.respond_to?(CacheCrispies.config.cache_key_method)
105
+ end
106
+
107
+ def cacheable_cache_key
108
+ cacheable.public_send(CacheCrispies.config.cache_key_method)
105
109
  end
106
110
 
107
111
  def addons_key
@@ -2,5 +2,5 @@
2
2
 
3
3
  module CacheCrispies
4
4
  # The version of the gem
5
- VERSION = '1.1.1'
5
+ VERSION = '1.3.0'
6
6
  end
@@ -11,7 +11,7 @@ describe CacheCrispies::Base do
11
11
 
12
12
  show_if -> { true } do
13
13
  show_if -> { true } do
14
- show_if -> { true } do
14
+ show_if :visible? do
15
15
  serialize :name, from: :brand
16
16
  end
17
17
  end
@@ -33,6 +33,10 @@ describe CacheCrispies::Base do
33
33
  def id
34
34
  model.id.to_s
35
35
  end
36
+
37
+ def visible?
38
+ true
39
+ end
36
40
  end
37
41
 
38
42
  let(:model) do
@@ -69,6 +73,26 @@ describe CacheCrispies::Base do
69
73
  parent_company: 'Disney probably'
70
74
  )
71
75
  end
76
+
77
+ context 'when nutrition_info is nil' do
78
+ before { model.nutrition_info = nil }
79
+
80
+ it 'serializes to a hash' do
81
+ expect(subject.as_json).to eq(
82
+ id: '42',
83
+ name: 'Cookie Crisp',
84
+ company: 'General Mills',
85
+ nested: {
86
+ nested_again: {
87
+ deeply_nested: 'TRUE'
88
+ }
89
+ },
90
+ nutrition_info: nil,
91
+ organic: true,
92
+ parent_company: 'Disney probably'
93
+ )
94
+ end
95
+ end
72
96
  end
73
97
 
74
98
  describe '.key' do
@@ -1,7 +1,18 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe CacheCrispies::Condition do
4
+ class TestSerializer < CacheCrispies::Base
5
+ show_if :boolean_method? do
6
+ serialize :name
7
+ end
8
+
9
+ def boolean_method?
10
+ end
11
+ end
12
+
4
13
  let(:block) { -> {} }
14
+ let(:model) { OpenStruct.new(name: 'Name') }
15
+ let(:serializer) { TestSerializer.new(model) }
5
16
  subject { described_class.new(block) }
6
17
 
7
18
  describe '#uid' do
@@ -17,7 +28,7 @@ describe CacheCrispies::Condition do
17
28
 
18
29
  it 'calls the block with model and options arguments' do
19
30
  expect(block).to receive(:call).with(model, options)
20
- subject.true_for? model, options
31
+ subject.true_for? serializer
21
32
  end
22
33
 
23
34
  context 'when the block has one argument' do
@@ -25,7 +36,7 @@ describe CacheCrispies::Condition do
25
36
 
26
37
  it 'calls the block with the model only' do
27
38
  expect(block).to receive(:call).with(model)
28
- subject.true_for? model, options
39
+ subject.true_for? serializer
29
40
  end
30
41
  end
31
42
 
@@ -34,12 +45,21 @@ describe CacheCrispies::Condition do
34
45
 
35
46
  it 'calls the block with no arguments' do
36
47
  expect(block).to receive(:call).with(no_args)
37
- subject.true_for? model, options
48
+ subject.true_for? serializer
49
+ end
50
+ end
51
+
52
+ context 'when the block is a symbol' do
53
+ let(:block) { :boolean_method? }
54
+
55
+ it 'calls the method on serializer instance' do
56
+ expect(serializer).to receive(block).with(no_args)
57
+ subject.true_for? serializer
38
58
  end
39
59
  end
40
60
 
41
61
  it 'returns a boolean' do
42
- expect(subject.true_for?(model, options)).to be true
62
+ expect(subject.true_for?(serializer)).to be true
43
63
  end
44
64
  end
45
65
  end
@@ -39,4 +39,16 @@ describe CacheCrispies::Configuration do
39
39
  }.to change { subject.etags }.to true
40
40
  end
41
41
  end
42
+
43
+ describe '#cache_key_method' do
44
+ it 'is cache_key by default' do
45
+ expect(subject.cache_key_method).to eq :cache_key
46
+ end
47
+
48
+ it 'can be changed' do
49
+ expect {
50
+ subject.cache_key_method = :other_cache_key
51
+ }.to change { subject.cache_key_method }.to eq :other_cache_key
52
+ end
53
+ end
42
54
  end
@@ -8,6 +8,10 @@ describe CacheCrispies::HashBuilder do
8
8
  serialize :name
9
9
  end
10
10
 
11
+ class AllergySerializer < CacheCrispies::Base
12
+ serialize :name
13
+ end
14
+
11
15
  class MarketingBsSerializer < CacheCrispies::Base
12
16
  serialize :tagline, :small_print
13
17
 
@@ -29,6 +33,8 @@ describe CacheCrispies::HashBuilder do
29
33
  nest_in :nutritional_information do
30
34
  serialize :calories
31
35
  serialize :ingredients, with: IngredientSerializer
36
+
37
+ serialize :allergies, with: AllergySerializer, optional: true
32
38
  end
33
39
  end
34
40
 
@@ -54,6 +60,12 @@ describe CacheCrispies::HashBuilder do
54
60
  OpenStruct.new(name: 'Other Kind of Sugar')
55
61
  ]
56
62
  }
63
+ let(:allergies) {
64
+ [
65
+ OpenStruct.new(name: 'Peanuts'),
66
+ OpenStruct.new(name: 'Lactose')
67
+ ]
68
+ }
57
69
  let(:model) {
58
70
  OpenStruct.new(
59
71
  id: 42,
@@ -62,7 +74,8 @@ describe CacheCrispies::HashBuilder do
62
74
  calories: 1_000,
63
75
  organic: organic,
64
76
  tagline: "Part of a balanced breakfast",
65
- ingredients: ingredients
77
+ ingredients: ingredients,
78
+ allergies: allergies
66
79
  )
67
80
  }
68
81
  let(:options) { { footnote_marker: '*' } }
@@ -85,8 +98,7 @@ describe CacheCrispies::HashBuilder do
85
98
  { name: 'Other Kind of Sugar' },
86
99
  ]
87
100
  }
88
- },
89
- health: {}
101
+ }
90
102
  })
91
103
  end
92
104
 
@@ -142,5 +154,59 @@ describe CacheCrispies::HashBuilder do
142
154
  end
143
155
  end
144
156
  end
157
+
158
+ context 'when allergies are included' do
159
+ let(:options) { { footnote_marker: '*', include: :allergies } }
160
+
161
+ it 'includes the allergies' do
162
+ expect(subject.call).to eq ({
163
+ uid: '42',
164
+ name: 'Lucky Charms',
165
+ company: 'General Mills',
166
+ tagline: 'Part of a balanced breakfast*',
167
+ small_print: "*this doesn't mean jack-squat",
168
+ about: {
169
+ nutritional_information: {
170
+ calories: 1000,
171
+ ingredients: [
172
+ { name: 'Sugar' },
173
+ { name: 'Other Kind of Sugar' },
174
+ ],
175
+ allergies: [
176
+ { name: 'Peanuts' },
177
+ { name: 'Lactose' },
178
+ ]
179
+ }
180
+ }
181
+ })
182
+ end
183
+ end
184
+
185
+ context 'when everything is included' do
186
+ let(:options) { { footnote_marker: '*', include: '*' } }
187
+
188
+ it 'includes the allergies' do
189
+ expect(subject.call).to eq ({
190
+ uid: '42',
191
+ name: 'Lucky Charms',
192
+ company: 'General Mills',
193
+ tagline: 'Part of a balanced breakfast*',
194
+ small_print: "*this doesn't mean jack-squat",
195
+ about: {
196
+ nutritional_information: {
197
+ calories: 1000,
198
+ ingredients: [
199
+ { name: 'Sugar' },
200
+ { name: 'Other Kind of Sugar' },
201
+ ],
202
+ allergies: [
203
+ { name: 'Peanuts' },
204
+ { name: 'Lactose' },
205
+ ]
206
+ }
207
+ }
208
+ })
209
+ end
210
+ end
145
211
  end
146
212
  end
@@ -20,7 +20,7 @@ describe CacheCrispies::Plan do
20
20
  let(:model) { OpenStruct.new(name: 'Sugar Smacks', cache_key: model_cache_key) }
21
21
  let(:cacheable) { model }
22
22
  let(:options) { {} }
23
- let(:instance) { described_class.new(serializer, cacheable, options) }
23
+ let(:instance) { described_class.new(serializer, cacheable, **options) }
24
24
  subject { instance }
25
25
 
26
26
  before do
@@ -125,6 +125,17 @@ describe CacheCrispies::Plan do
125
125
  )
126
126
  end
127
127
  end
128
+
129
+ context 'with a configured cache_key_method' do
130
+ let(:custom_cache_key) { 'custom-cache-key' }
131
+ let(:model) { OpenStruct.new(name: 'Sugar Smacks', custom_cache_key: custom_cache_key) }
132
+
133
+ it "includes the cacheable #custom_cache_key" do
134
+ expect(CacheCrispies.config).to receive(:cache_key_method).and_return :custom_cache_key
135
+
136
+ expect(subject.cache_key).to include custom_cache_key
137
+ end
138
+ end
128
139
  end
129
140
 
130
141
  describe '#cache' do
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cache_crispies
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adam Crownoble
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-10 00:00:00.000000000 Z
11
+ date: 2021-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -19,7 +19,7 @@ dependencies:
19
19
  version: 5.0.0
20
20
  - - "<"
21
21
  - !ruby/object:Gem::Version
22
- version: '6.1'
22
+ version: '6.2'
23
23
  type: :runtime
24
24
  prerelease: false
25
25
  version_requirements: !ruby/object:Gem::Requirement
@@ -29,7 +29,7 @@ dependencies:
29
29
  version: 5.0.0
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
- version: '6.1'
32
+ version: '6.2'
33
33
  - !ruby/object:Gem::Dependency
34
34
  name: oj
35
35
  requirement: !ruby/object:Gem::Requirement
@@ -53,7 +53,7 @@ dependencies:
53
53
  version: 5.0.0
54
54
  - - "<"
55
55
  - !ruby/object:Gem::Version
56
- version: '6.1'
56
+ version: '6.2'
57
57
  type: :development
58
58
  prerelease: false
59
59
  version_requirements: !ruby/object:Gem::Requirement
@@ -63,7 +63,7 @@ dependencies:
63
63
  version: 5.0.0
64
64
  - - "<"
65
65
  - !ruby/object:Gem::Version
66
- version: '6.1'
66
+ version: '6.2'
67
67
  - !ruby/object:Gem::Dependency
68
68
  name: appraisal
69
69
  requirement: !ruby/object:Gem::Requirement
@@ -121,20 +121,34 @@ dependencies:
121
121
  - !ruby/object:Gem::Version
122
122
  version: 3.8.0
123
123
  - !ruby/object:Gem::Dependency
124
- name: simplecov
124
+ name: rspec_junit_formatter
125
125
  requirement: !ruby/object:Gem::Requirement
126
126
  requirements:
127
127
  - - "~>"
128
128
  - !ruby/object:Gem::Version
129
- version: '0.17'
129
+ version: '0.4'
130
130
  type: :development
131
131
  prerelease: false
132
132
  version_requirements: !ruby/object:Gem::Requirement
133
133
  requirements:
134
134
  - - "~>"
135
+ - !ruby/object:Gem::Version
136
+ version: '0.4'
137
+ - !ruby/object:Gem::Dependency
138
+ name: simplecov
139
+ requirement: !ruby/object:Gem::Requirement
140
+ requirements:
141
+ - - '='
142
+ - !ruby/object:Gem::Version
143
+ version: '0.17'
144
+ type: :development
145
+ prerelease: false
146
+ version_requirements: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '='
135
149
  - !ruby/object:Gem::Version
136
150
  version: '0.17'
137
- description:
151
+ description:
138
152
  email: adam@codenoble.com
139
153
  executables: []
140
154
  extensions: []
@@ -150,6 +164,7 @@ files:
150
164
  - lib/cache_crispies/controller.rb
151
165
  - lib/cache_crispies/hash_builder.rb
152
166
  - lib/cache_crispies/memoizer.rb
167
+ - lib/cache_crispies/optional.rb
153
168
  - lib/cache_crispies/plan.rb
154
169
  - lib/cache_crispies/version.rb
155
170
  - spec/cache_crispies/attribute_spec.rb
@@ -168,7 +183,7 @@ homepage: https://github.com/codenoble/cache-crispies
168
183
  licenses:
169
184
  - MIT
170
185
  metadata: {}
171
- post_install_message:
186
+ post_install_message:
172
187
  rdoc_options: []
173
188
  require_paths:
174
189
  - lib
@@ -183,8 +198,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
183
198
  - !ruby/object:Gem::Version
184
199
  version: '0'
185
200
  requirements: []
186
- rubygems_version: 3.0.3
187
- signing_key:
201
+ rubygems_version: 3.2.15
202
+ signing_key:
188
203
  specification_version: 4
189
204
  summary: Fast Rails serializer with built-in caching
190
205
  test_files: