mongoid-cached-json 1.5.1 → 1.5.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +21 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +6 -0
  5. data/.rubocop_todo.yml +80 -0
  6. data/.travis.yml +16 -0
  7. data/CHANGELOG.md +85 -0
  8. data/CONTRIBUTING.md +118 -0
  9. data/Gemfile +21 -0
  10. data/README.md +49 -52
  11. data/Rakefile +34 -0
  12. data/lib/mongoid-cached-json.rb +0 -1
  13. data/lib/mongoid-cached-json/array.rb +1 -3
  14. data/lib/mongoid-cached-json/cached_json.rb +52 -50
  15. data/lib/mongoid-cached-json/config.rb +20 -21
  16. data/lib/mongoid-cached-json/hash.rb +1 -3
  17. data/lib/mongoid-cached-json/key_references.rb +0 -3
  18. data/lib/mongoid-cached-json/mongoid_criteria.rb +1 -3
  19. data/lib/mongoid-cached-json/version.rb +1 -2
  20. data/mongoid-cached-json.gemspec +17 -0
  21. data/spec/array_spec.rb +48 -0
  22. data/spec/benchmark_spec.rb +115 -0
  23. data/spec/cached_json_spec.rb +501 -0
  24. data/spec/config_spec.rb +21 -0
  25. data/spec/dalli_spec.rb +37 -0
  26. data/spec/hash_spec.rb +66 -0
  27. data/spec/mongoid_criteria_spec.rb +78 -0
  28. data/spec/spec_helper.rb +20 -0
  29. data/spec/support/awesome_artwork.rb +11 -0
  30. data/spec/support/awesome_image.rb +14 -0
  31. data/spec/support/fast_json_artwork.rb +15 -0
  32. data/spec/support/fast_json_image.rb +12 -0
  33. data/spec/support/fast_json_url.rb +12 -0
  34. data/spec/support/json_embedded_foobar.rb +5 -0
  35. data/spec/support/json_employee.rb +12 -0
  36. data/spec/support/json_foobar.rb +19 -0
  37. data/spec/support/json_manager.rb +14 -0
  38. data/spec/support/json_math.rb +9 -0
  39. data/spec/support/json_parent_foobar.rb +11 -0
  40. data/spec/support/json_polymorphic_embedded_foobar.rb +9 -0
  41. data/spec/support/json_polymorphic_referenced_foobar.rb +9 -0
  42. data/spec/support/json_referenced_foobar.rb +5 -0
  43. data/spec/support/json_supervisor.rb +13 -0
  44. data/spec/support/json_transform.rb +13 -0
  45. data/spec/support/matchers/invalidate.rb +22 -0
  46. data/spec/support/person.rb +20 -0
  47. data/spec/support/poly_company.rb +10 -0
  48. data/spec/support/poly_person.rb +10 -0
  49. data/spec/support/poly_post.rb +9 -0
  50. data/spec/support/prison_cell.rb +11 -0
  51. data/spec/support/prison_inmate.rb +12 -0
  52. data/spec/support/secret_parent.rb +11 -0
  53. data/spec/support/sometimes_secret.rb +11 -0
  54. data/spec/support/tool.rb +11 -0
  55. data/spec/support/tool_box.rb +10 -0
  56. metadata +62 -137
data/Rakefile ADDED
@@ -0,0 +1,34 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+
4
+ require File.expand_path('../lib/mongoid-cached-json/version', __FILE__)
5
+
6
+ Bundler.setup(:default, :development)
7
+ Bundler::GemHelper.install_tasks
8
+
9
+ require 'rake'
10
+
11
+ require 'rspec/core'
12
+ require 'rspec/core/rake_task'
13
+
14
+ RSpec::Core::RakeTask.new(:spec) do |spec|
15
+ files = FileList['spec/**/*_spec.rb']
16
+ files = files.exclude 'spec/benchmark_spec.rb'
17
+ spec.pattern = files
18
+ end
19
+
20
+ require 'rdoc/task'
21
+ Rake::RDocTask.new do |rdoc|
22
+ version = File.exist?('VERSION') ? File.read('VERSION') : ''
23
+
24
+ rdoc.rdoc_dir = 'rdoc'
25
+ rdoc.title = "mongoid-cached-json #{version}"
26
+ rdoc.rdoc_files.include('README*')
27
+ rdoc.rdoc_files.include('LICENSE*')
28
+ rdoc.rdoc_files.include('lib/**/*.rb')
29
+ end
30
+
31
+ require 'rubocop/rake_task'
32
+ RuboCop::RakeTask.new
33
+
34
+ task default: [:rubocop, :spec]
@@ -8,4 +8,3 @@ require 'mongoid-cached-json/mongoid_criteria'
8
8
  require 'mongoid-cached-json/version'
9
9
  require 'mongoid-cached-json/config'
10
10
  require 'mongoid-cached-json/cached_json'
11
-
@@ -1,5 +1,4 @@
1
1
  class Array
2
-
3
2
  def as_json_partial(options = {})
4
3
  json_keys = nil
5
4
  json = map do |i|
@@ -11,12 +10,11 @@ class Array
11
10
  i.as_json(options)
12
11
  end
13
12
  end
14
- [ json_keys, json ]
13
+ [json_keys, json]
15
14
  end
16
15
 
17
16
  def as_json(options = {})
18
17
  json_keys, json = as_json_partial(options)
19
18
  Mongoid::CachedJson.materialize_json_references_with_read_multi(json_keys, json)
20
19
  end
21
-
22
20
  end
@@ -12,33 +12,32 @@ module Mongoid
12
12
  end
13
13
 
14
14
  module ClassMethods
15
-
16
15
  # Define JSON fields for a class.
17
16
  #
18
17
  # @param [ hash ] defs JSON field definition.
19
18
  #
20
19
  # @since 1.0
21
20
  def json_fields(defs)
22
- self.hide_as_child_json_when = defs.delete(:hide_as_child_json_when) || lambda { |a| false }
23
- self.all_json_properties = [ :short, :public, :all ]
24
- cached_json_defs = Hash[defs.map { |k,v| [k, { :type => :callable, :properties => :short, :definition => k }.merge(v)] }]
21
+ self.hide_as_child_json_when = defs.delete(:hide_as_child_json_when) || lambda { |_a| false }
22
+ self.all_json_properties = [:short, :public, :all]
23
+ cached_json_defs = Hash[defs.map { |k, v| [k, { type: :callable, properties: :short, definition: k }.merge(v)] }]
25
24
  self.cached_json_field_defs = {}
26
25
  self.cached_json_reference_defs = {}
27
26
  # Collect all versions for clearing cache
28
- self.all_json_versions = cached_json_defs.map do |field, definition|
29
- [ :unspecified, definition[:version], Array(definition[:versions]) ]
27
+ self.all_json_versions = cached_json_defs.map do |_field, definition|
28
+ [:unspecified, definition[:version], Array(definition[:versions])]
30
29
  end.flatten.compact.uniq
31
- self.all_json_properties.each_with_index do |property, i|
32
- self.cached_json_field_defs[property] = Hash[cached_json_defs.find_all do |field, definition|
33
- self.all_json_properties.find_index(definition[:properties]) <= i && definition[:type] == :callable
30
+ all_json_properties.each_with_index do |property, i|
31
+ cached_json_field_defs[property] = Hash[cached_json_defs.find_all do |_field, definition|
32
+ all_json_properties.find_index(definition[:properties]) <= i && definition[:type] == :callable
34
33
  end]
35
- self.cached_json_reference_defs[property] = Hash[cached_json_defs.find_all do |field, definition|
36
- self.all_json_properties.find_index(definition[:properties]) <= i && definition[:type] == :reference
34
+ cached_json_reference_defs[property] = Hash[cached_json_defs.find_all do |_field, definition|
35
+ all_json_properties.find_index(definition[:properties]) <= i && definition[:type] == :reference
37
36
  end]
38
37
  # If the field is a reference and is just specified as a symbol, reflect on it to get metadata
39
- self.cached_json_reference_defs[property].to_a.each do |field, definition|
38
+ cached_json_reference_defs[property].to_a.each do |field, definition|
40
39
  if definition[:definition].is_a?(Symbol)
41
- self.cached_json_reference_defs[property][field][:metadata] = self.reflect_on_association(definition[:definition])
40
+ cached_json_reference_defs[property][field][:metadata] = reflect_on_association(definition[:definition])
42
41
  end
43
42
  end
44
43
  end
@@ -49,20 +48,20 @@ module Mongoid
49
48
  # Materialize a cached JSON within a cache block.
50
49
  def materialize_cached_json(clazz, id, object_reference, options)
51
50
  is_top_level_json = options[:is_top_level_json] || false
52
- object_reference = clazz.where({ :_id => id }).first if !object_reference
51
+ object_reference = clazz.where(_id: id).first unless object_reference
53
52
  if !object_reference || (!is_top_level_json && options[:properties] != :all && clazz.hide_as_child_json_when.call(object_reference))
54
53
  nil
55
54
  else
56
55
  Hash[clazz.cached_json_field_defs[options[:properties]].map do |field, definition|
57
56
  # version match
58
- versions = ([definition[:version] ] | Array(definition[:versions])).compact
59
- next unless versions.empty? or versions.include?(options[:version])
57
+ versions = ([definition[:version]] | Array(definition[:versions])).compact
58
+ next unless versions.empty? || versions.include?(options[:version])
60
59
  json_value = (definition[:definition].is_a?(Symbol) ? object_reference.send(definition[:definition]) : definition[:definition].call(object_reference))
61
60
  Mongoid::CachedJson.config.transform.each do |t|
62
61
  json_value = t.call(field, definition, json_value)
63
62
  end
64
63
  [field, json_value]
65
- end]
64
+ end.compact]
66
65
  end
67
66
  end
68
67
 
@@ -73,7 +72,7 @@ module Mongoid
73
72
  # the JSON by calling resolve_json_reference on each of them (which may, in turn,
74
73
  # call materialize_json)
75
74
  def materialize_json(options, object_def)
76
- return nil if !object_def[:object] and !object_def[:id]
75
+ return nil if !object_def[:object] && !object_def[:id]
77
76
  is_top_level_json = options[:is_top_level_json] || false
78
77
  if object_def[:object]
79
78
  object_reference = object_def[:object]
@@ -82,18 +81,18 @@ module Mongoid
82
81
  object_reference = nil
83
82
  clazz, id = object_def[:clazz], object_def[:id]
84
83
  end
85
- key = self.cached_json_key(options, clazz, id)
86
- json = { :_ref => { :_clazz => self, :_key => key, :_materialize_cached_json => [ clazz, id, object_reference, options ] }}
84
+ key = cached_json_key(options, clazz, id)
85
+ json = { _ref: { _clazz: self, _key: key, _materialize_cached_json: [clazz, id, object_reference, options] } }
87
86
  keys = KeyReferences.new
88
87
  keys.set_and_add(key, json)
89
88
  reference_defs = clazz.cached_json_reference_defs[options[:properties]]
90
- if !reference_defs.empty?
91
- object_reference = clazz.where({ :_id => id }).first if !object_reference
89
+ unless reference_defs.empty?
90
+ object_reference = clazz.where(_id: id).first unless object_reference
92
91
  if object_reference && (is_top_level_json || options[:properties] == :all || !clazz.hide_as_child_json_when.call(object_reference))
93
92
  json.merge!(Hash[reference_defs.map do |field, definition|
94
93
  json_properties_type = definition[:reference_properties] || ((options[:properties] == :all) ? :all : :short)
95
- reference_keys, reference = clazz.resolve_json_reference(options.merge({ :properties => json_properties_type, :is_top_level_json => false}), object_reference, field, definition)
96
- if (reference.is_a?(Hash) && ref = reference[:_ref])
94
+ reference_keys, reference = clazz.resolve_json_reference(options.merge(properties: json_properties_type, is_top_level_json: false), object_reference, field, definition)
95
+ if reference.is_a?(Hash) && ref = reference[:_ref]
97
96
  ref[:_parent] = json
98
97
  ref[:_field] = field
99
98
  end
@@ -102,7 +101,7 @@ module Mongoid
102
101
  end])
103
102
  end
104
103
  end
105
- [ keys, json ]
104
+ [keys, json]
106
105
  end
107
106
 
108
107
  # Cache key.
@@ -115,7 +114,7 @@ module Mongoid
115
114
  # representation by the (class, id) pair definition of the reference. That is, we may
116
115
  # be able to load the as_json representation from the cache without even getting the
117
116
  # model from the database and materializing it through Mongoid. We'll try to do this first.
118
- def resolve_json_reference(options, object, field, reference_def)
117
+ def resolve_json_reference(options, object, _field, reference_def)
119
118
  keys = nil
120
119
  reference_json = nil
121
120
  if reference_def[:metadata]
@@ -127,16 +126,20 @@ module Mongoid
127
126
  end
128
127
  if reference_def[:metadata].relation == Mongoid::Relations::Referenced::ManyToMany
129
128
  object_ids = object.send(key)
130
- reference_json = object_ids ? object_ids.map do |id|
131
- materialize_keys, json = materialize_json(options, { :clazz => clazz, :id => id })
132
- keys = keys ? keys.merge_set(materialize_keys) : materialize_keys
133
- json
134
- end.compact : []
129
+ if object_ids
130
+ reference_json = object_ids.map do |id|
131
+ materialize_keys, json = materialize_json(options, clazz: clazz, id: id)
132
+ keys = keys ? keys.merge_set(materialize_keys) : materialize_keys
133
+ json
134
+ end.compact
135
+ else
136
+ object_ids = []
137
+ end
135
138
  end
136
139
  end
137
140
  # If we get to this point and reference_json is still nil, there's no chance we can
138
141
  # load the JSON from cache so we go ahead and call as_json on the object.
139
- if ! reference_json
142
+ unless reference_json
140
143
  reference_def_definition = reference_def[:definition]
141
144
  reference = reference_def_definition.is_a?(Symbol) ? object.send(reference_def_definition) : reference_def_definition.call(object)
142
145
  reference_json = nil
@@ -149,9 +152,8 @@ module Mongoid
149
152
  end
150
153
  end
151
154
  end
152
- [ keys, reference_json ]
155
+ [keys, reference_json]
153
156
  end
154
-
155
157
  end
156
158
 
157
159
  # Check whether the cache supports :read_multi and prefetch the data if it does.
@@ -169,15 +171,15 @@ module Mongoid
169
171
  refs.each do |ref|
170
172
  _ref = ref.delete(:_ref)
171
173
  key = _ref[:_key]
172
- fetched_json = local_cache[key] if local_cache.has_key?(key)
173
- if ! fetched_json
174
+ fetched_json = local_cache[key] if local_cache.key?(key)
175
+ unless fetched_json
174
176
  if read_multi
175
177
  # no value in cache, materialize and write
176
178
  fetched_json = (local_cache[key] = _ref[:_clazz].materialize_cached_json(* _ref[:_materialize_cached_json]))
177
- Mongoid::CachedJson.config.cache.write(key, fetched_json) unless !! Mongoid::CachedJson.config.disable_caching
179
+ Mongoid::CachedJson.config.cache.write(key, fetched_json) unless Mongoid::CachedJson.config.disable_caching
178
180
  else
179
181
  # fetch/write from cache
180
- fetched_json = (local_cache[key] = Mongoid::CachedJson.config.cache.fetch(key, { :force => !! Mongoid::CachedJson.config.disable_caching }) do
182
+ fetched_json = (local_cache[key] = Mongoid::CachedJson.config.cache.fetch(key, force: !!Mongoid::CachedJson.config.disable_caching) do
181
183
  _ref[:_clazz].materialize_cached_json(* _ref[:_materialize_cached_json])
182
184
  end)
183
185
  end
@@ -195,14 +197,14 @@ module Mongoid
195
197
  # Return a partial JSON without resolved references and all the keys.
196
198
  def as_json_partial(options = {})
197
199
  options ||= {}
198
- if options[:properties] and ! self.all_json_properties.member?(options[:properties])
199
- raise ArgumentError.new("Unknown properties option: #{options[:properties]}")
200
+ if options[:properties] && !all_json_properties.member?(options[:properties])
201
+ fail ArgumentError.new("Unknown properties option: #{options[:properties]}")
200
202
  end
201
203
  # partial, unmaterialized JSON
202
204
  keys, partial_json = self.class.materialize_json({
203
- :properties => :short, :is_top_level_json => true, :version => Mongoid::CachedJson.config.default_version
204
- }.merge(options), { :object => self })
205
- [ keys, partial_json ]
205
+ properties: :short, is_top_level_json: true, version: Mongoid::CachedJson.config.default_version
206
+ }.merge(options), object: self)
207
+ [keys, partial_json]
206
208
  end
207
209
 
208
210
  # Fetch the partial JSON and materialize all JSON references.
@@ -218,19 +220,20 @@ module Mongoid
218
220
 
219
221
  # Expire all JSON entries for this class.
220
222
  def expire_cached_json
221
- self.all_json_properties.each do |properties|
223
+ all_json_properties.each do |properties|
222
224
  [true, false].each do |is_top_level_json|
223
- self.all_json_versions.each do |version|
225
+ all_json_versions.each do |version|
224
226
  Mongoid::CachedJson.config.cache.delete(self.class.cached_json_key({
225
- :properties => properties, :is_top_level_json => is_top_level_json, :version => version
226
- }, self.class, self.id))
227
+ properties: properties,
228
+ is_top_level_json: is_top_level_json,
229
+ version: version
230
+ }, self.class, id))
227
231
  end
228
232
  end
229
233
  end
230
234
  end
231
235
 
232
236
  class << self
233
-
234
237
  # Set the configuration options. Best used by passing a block.
235
238
  #
236
239
  # @example Set up configuration options.
@@ -242,8 +245,7 @@ module Mongoid
242
245
  def configure
243
246
  block_given? ? yield(Mongoid::CachedJson::Config) : Mongoid::CachedJson::Config
244
247
  end
245
- alias :config :configure
248
+ alias_method :config, :configure
246
249
  end
247
-
248
250
  end
249
251
  end
@@ -1,19 +1,19 @@
1
1
  # encoding: utf-8
2
- module Mongoid
3
- module CachedJson
2
+ module Mongoid
3
+ module CachedJson
4
4
  module Config
5
5
  extend self
6
6
  include ActiveSupport::Callbacks
7
-
7
+
8
8
  # Current configuration settings.
9
9
  attr_accessor :settings
10
-
10
+
11
11
  # Default configuration settings.
12
12
  attr_accessor :defaults
13
-
13
+
14
14
  @settings = {}
15
15
  @defaults = {}
16
-
16
+
17
17
  # Define a configuration option with a default.
18
18
  #
19
19
  # @example Define the option.
@@ -25,25 +25,25 @@ module Mongoid
25
25
  # @option options [ Object ] :default The default value.
26
26
  def option(name, options = {})
27
27
  defaults[name] = settings[name] = options[:default]
28
-
28
+
29
29
  class_eval <<-RUBY
30
30
  def #{name}
31
31
  settings[#{name.inspect}]
32
32
  end
33
-
33
+
34
34
  def #{name}=(value)
35
35
  settings[#{name.inspect}] = value
36
36
  end
37
-
37
+
38
38
  def #{name}?
39
39
  #{name}
40
40
  end
41
41
  RUBY
42
42
  end
43
-
43
+
44
44
  # Disable caching.
45
- option :disable_caching, { :default => false }
46
-
45
+ option :disable_caching, default: false
46
+
47
47
  # Returns the default JSON version
48
48
  #
49
49
  # @example Get the default JSON version
@@ -51,7 +51,7 @@ module Mongoid
51
51
  #
52
52
  # @return [ Version ] The default JSON version.
53
53
  def default_version
54
- settings[:default_version] = :unspecified unless settings.has_key?(:default_version)
54
+ settings[:default_version] = :unspecified unless settings.key?(:default_version)
55
55
  settings[:default_version]
56
56
  end
57
57
 
@@ -64,7 +64,7 @@ module Mongoid
64
64
  def default_version=(default_version)
65
65
  settings[:default_version] = default_version
66
66
  end
67
-
67
+
68
68
  # Returns the default cache store, for example Rails cache or an instance of ActiveSupport::Cache::MemoryStore.
69
69
  #
70
70
  # @example Get the default cache store
@@ -74,7 +74,7 @@ module Mongoid
74
74
  def default_cache
75
75
  defined?(Rails) && Rails.respond_to?(:cache) ? Rails.cache : ::ActiveSupport::Cache::MemoryStore.new
76
76
  end
77
-
77
+
78
78
  # Returns the cache, or defaults to Rails cache when running under Rails or ActiveSupport::Cache::MemoryStore.
79
79
  #
80
80
  # @example Get the cache.
@@ -82,10 +82,10 @@ module Mongoid
82
82
  #
83
83
  # @return [ Cache ] The configured cache or a default cache instance.
84
84
  def cache
85
- settings[:cache] = default_cache unless settings.has_key?(:cache)
85
+ settings[:cache] = default_cache unless settings.key?(:cache)
86
86
  settings[:cache]
87
87
  end
88
-
88
+
89
89
  # Sets the cache to use.
90
90
  #
91
91
  # @example Set the cache.
@@ -95,7 +95,7 @@ module Mongoid
95
95
  def cache=(cache)
96
96
  settings[:cache] = cache
97
97
  end
98
-
98
+
99
99
  # Reset the configuration options to the defaults.
100
100
  #
101
101
  # @example Reset the configuration options.
@@ -103,7 +103,7 @@ module Mongoid
103
103
  def reset!
104
104
  settings.replace(defaults)
105
105
  end
106
-
106
+
107
107
  # Define a transformation on JSON data.
108
108
  #
109
109
  # @example Convert every string in materialized JSON to upper-case.
@@ -111,11 +111,10 @@ module Mongoid
111
111
  # value.upcase
112
112
  # end
113
113
  def transform(& block)
114
- settings[:transform] = [] unless settings.has_key?(:transform)
114
+ settings[:transform] = [] unless settings.key?(:transform)
115
115
  settings[:transform] << block if block_given?
116
116
  settings[:transform]
117
117
  end
118
-
119
118
  end
120
119
  end
121
120
  end
@@ -1,5 +1,4 @@
1
1
  class Hash
2
-
3
2
  def as_json_partial(options = {})
4
3
  json_keys = nil
5
4
  json = inject({}) do |h, (k, v)|
@@ -12,12 +11,11 @@ class Hash
12
11
  end
13
12
  h
14
13
  end
15
- [ json_keys, json ]
14
+ [json_keys, json]
16
15
  end
17
16
 
18
17
  def as_json(options = {})
19
18
  json_keys, json = as_json_partial(options)
20
19
  Mongoid::CachedJson.materialize_json_references_with_read_multi(json_keys, json)
21
20
  end
22
-
23
21
  end
@@ -3,7 +3,6 @@
3
3
  module Mongoid
4
4
  module CachedJson
5
5
  class KeyReferences < Hash
6
-
7
6
  def merge_set(keys)
8
7
  if keys
9
8
  keys.each_pair do |k, jsons|
@@ -19,8 +18,6 @@ module Mongoid
19
18
  self[key] << json
20
19
  self
21
20
  end
22
-
23
21
  end
24
22
  end
25
23
  end
26
-