cache_crispies 1.1.1 → 1.3.0

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
  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: