mongoid-cached-json 1.5.1 → 1.5.2
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 +7 -0
- data/.gitignore +21 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/.rubocop_todo.yml +80 -0
- data/.travis.yml +16 -0
- data/CHANGELOG.md +85 -0
- data/CONTRIBUTING.md +118 -0
- data/Gemfile +21 -0
- data/README.md +49 -52
- data/Rakefile +34 -0
- data/lib/mongoid-cached-json.rb +0 -1
- data/lib/mongoid-cached-json/array.rb +1 -3
- data/lib/mongoid-cached-json/cached_json.rb +52 -50
- data/lib/mongoid-cached-json/config.rb +20 -21
- data/lib/mongoid-cached-json/hash.rb +1 -3
- data/lib/mongoid-cached-json/key_references.rb +0 -3
- data/lib/mongoid-cached-json/mongoid_criteria.rb +1 -3
- data/lib/mongoid-cached-json/version.rb +1 -2
- data/mongoid-cached-json.gemspec +17 -0
- data/spec/array_spec.rb +48 -0
- data/spec/benchmark_spec.rb +115 -0
- data/spec/cached_json_spec.rb +501 -0
- data/spec/config_spec.rb +21 -0
- data/spec/dalli_spec.rb +37 -0
- data/spec/hash_spec.rb +66 -0
- data/spec/mongoid_criteria_spec.rb +78 -0
- data/spec/spec_helper.rb +20 -0
- data/spec/support/awesome_artwork.rb +11 -0
- data/spec/support/awesome_image.rb +14 -0
- data/spec/support/fast_json_artwork.rb +15 -0
- data/spec/support/fast_json_image.rb +12 -0
- data/spec/support/fast_json_url.rb +12 -0
- data/spec/support/json_embedded_foobar.rb +5 -0
- data/spec/support/json_employee.rb +12 -0
- data/spec/support/json_foobar.rb +19 -0
- data/spec/support/json_manager.rb +14 -0
- data/spec/support/json_math.rb +9 -0
- data/spec/support/json_parent_foobar.rb +11 -0
- data/spec/support/json_polymorphic_embedded_foobar.rb +9 -0
- data/spec/support/json_polymorphic_referenced_foobar.rb +9 -0
- data/spec/support/json_referenced_foobar.rb +5 -0
- data/spec/support/json_supervisor.rb +13 -0
- data/spec/support/json_transform.rb +13 -0
- data/spec/support/matchers/invalidate.rb +22 -0
- data/spec/support/person.rb +20 -0
- data/spec/support/poly_company.rb +10 -0
- data/spec/support/poly_person.rb +10 -0
- data/spec/support/poly_post.rb +9 -0
- data/spec/support/prison_cell.rb +11 -0
- data/spec/support/prison_inmate.rb +12 -0
- data/spec/support/secret_parent.rb +11 -0
- data/spec/support/sometimes_secret.rb +11 -0
- data/spec/support/tool.rb +11 -0
- data/spec/support/tool_box.rb +10 -0
- metadata +62 -137
data/spec/config_spec.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::CachedJson::Config do
|
4
|
+
before :each do
|
5
|
+
@cache = Mongoid::CachedJson::Config.cache
|
6
|
+
end
|
7
|
+
after :each do
|
8
|
+
Mongoid::CachedJson::Config.cache = @cache
|
9
|
+
end
|
10
|
+
it 'configures a cache store' do
|
11
|
+
cache = Class.new
|
12
|
+
Mongoid::CachedJson.configure do |config|
|
13
|
+
config.cache = cache
|
14
|
+
end
|
15
|
+
expect(cache).to receive(:fetch).once
|
16
|
+
JsonFoobar.new.as_json
|
17
|
+
end
|
18
|
+
it 'sets disable_caching to false' do
|
19
|
+
expect(Mongoid::CachedJson.config.disable_caching).to be_falsey
|
20
|
+
end
|
21
|
+
end
|
data/spec/dalli_spec.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require 'active_support/cache/dalli_store'
|
3
|
+
|
4
|
+
describe ActiveSupport::Cache::DalliStore do
|
5
|
+
before :each do
|
6
|
+
@cache = Mongoid::CachedJson::Config.cache
|
7
|
+
Mongoid::CachedJson.configure do |config|
|
8
|
+
config.cache = ActiveSupport::Cache.lookup_store(:dalli_store)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
after :each do
|
12
|
+
Mongoid::CachedJson::Config.cache = @cache
|
13
|
+
end
|
14
|
+
it 'uses dalli_store' do
|
15
|
+
expect(Mongoid::CachedJson.config.cache).to be_a ActiveSupport::Cache::DalliStore
|
16
|
+
end
|
17
|
+
context 'read_multi' do
|
18
|
+
context 'array' do
|
19
|
+
it 'uses a local cache to fetch repeated objects' do
|
20
|
+
options = { properties: :all, is_top_level_json: true, version: :unspecified }
|
21
|
+
tool1 = Tool.create!(name: 'hammer')
|
22
|
+
tool1_key = Tool.cached_json_key(options, Tool, tool1.id)
|
23
|
+
tool2 = Tool.create!(name: 'screwdriver')
|
24
|
+
tool2_key = Tool.cached_json_key(options, Tool, tool2.id)
|
25
|
+
expect(Mongoid::CachedJson.config.cache).not_to receive(:fetch)
|
26
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:read_multi).with(tool1_key, tool2_key).once.and_return(
|
27
|
+
tool1_key => { _id: tool1.id.to_s },
|
28
|
+
tool2_key => { _id: tool2.id.to_s }
|
29
|
+
)
|
30
|
+
expect([tool1, tool2].as_json(properties: :all)).to eq([
|
31
|
+
{ tool_box: nil, _id: tool1.id.to_s },
|
32
|
+
{ tool_box: nil, _id: tool2.id.to_s }
|
33
|
+
])
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
data/spec/hash_spec.rb
ADDED
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Hash do
|
4
|
+
it 'hash' do
|
5
|
+
expect({ x: 'x', y: 'y' }.as_json).to eq(x: 'x', y: 'y')
|
6
|
+
end
|
7
|
+
it 'materializes multiple objects that may or may not respond to as_json_partial' do
|
8
|
+
foobar1 = JsonFoobar.create(foo: 'FOO1', baz: 'BAZ', bar: 'BAR')
|
9
|
+
foobar2 = JsonFoobar.create(foo: 'FOO2', baz: 'BAZ', bar: 'BAR')
|
10
|
+
expect({
|
11
|
+
:x => :y,
|
12
|
+
:foobar1 => foobar1,
|
13
|
+
:foobar2 => foobar2,
|
14
|
+
:z => {
|
15
|
+
foobar1: foobar1
|
16
|
+
},
|
17
|
+
:t => [foobar1, :y],
|
18
|
+
'empty' => []
|
19
|
+
}.as_json).to eq(
|
20
|
+
:x => 'y',
|
21
|
+
:foobar1 => { :foo => 'FOO1', 'Baz' => 'BAZ', :default_foo => 'DEFAULT_FOO' },
|
22
|
+
:foobar2 => { :foo => 'FOO2', 'Baz' => 'BAZ', :default_foo => 'DEFAULT_FOO' },
|
23
|
+
:z => { foobar1: { :foo => 'FOO1', 'Baz' => 'BAZ', :default_foo => 'DEFAULT_FOO' } },
|
24
|
+
:t => [{ :foo => 'FOO1', 'Baz' => 'BAZ', :default_foo => 'DEFAULT_FOO' }, 'y'],
|
25
|
+
'empty' => []
|
26
|
+
)
|
27
|
+
end
|
28
|
+
context 'without read_multi' do
|
29
|
+
before :each do
|
30
|
+
Mongoid::CachedJson.config.cache.instance_eval { undef :read_multi }
|
31
|
+
end
|
32
|
+
it 'uses a local cache to fetch repeated objects' do
|
33
|
+
tool = Tool.create!(name: 'hammer')
|
34
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:fetch).once.and_return(
|
35
|
+
x: :y
|
36
|
+
)
|
37
|
+
expect({
|
38
|
+
t1: tool,
|
39
|
+
t2: tool,
|
40
|
+
t3: tool
|
41
|
+
}.as_json(properties: :all)).to eq(
|
42
|
+
t1: { tool_box: nil, x: :y },
|
43
|
+
t2: { tool_box: nil, x: :y },
|
44
|
+
t3: { tool_box: nil, x: :y }
|
45
|
+
)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
context 'with read_multi' do
|
49
|
+
it 'uses a local cache to fetch repeated objects' do
|
50
|
+
tool = Tool.create!(name: 'hammer')
|
51
|
+
tool_key = "as_json/unspecified/Tool/#{tool.id}/all/true"
|
52
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:read_multi).once.with(tool_key).and_return(
|
53
|
+
tool_key => { x: :y }
|
54
|
+
)
|
55
|
+
expect({
|
56
|
+
t1: tool,
|
57
|
+
t2: tool,
|
58
|
+
t3: tool
|
59
|
+
}.as_json(properties: :all)).to eq(
|
60
|
+
t1: { tool_box: nil, x: :y },
|
61
|
+
t2: { tool_box: nil, x: :y },
|
62
|
+
t3: { tool_box: nil, x: :y }
|
63
|
+
)
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Mongoid::Criteria do
|
4
|
+
it 'mongoid_criteria' do
|
5
|
+
tool_box = ToolBox.create!(color: 'red')
|
6
|
+
Tool.create!(name: 'hammer', tool_box: tool_box)
|
7
|
+
Tool.create!(name: 'screwdriver', tool_box: tool_box)
|
8
|
+
expect(Tool.where(tool_box_id: tool_box.id).as_json(properties: :all)).to eq([
|
9
|
+
{ tool_box: { color: 'red' }, name: 'hammer' },
|
10
|
+
{ tool_box: { color: 'red' }, name: 'screwdriver' }
|
11
|
+
])
|
12
|
+
end
|
13
|
+
context 'without read_multi' do
|
14
|
+
before :each do
|
15
|
+
Mongoid::CachedJson.config.cache.instance_eval { undef :read_multi }
|
16
|
+
end
|
17
|
+
it 'materializes multiple objects using a single partial' do
|
18
|
+
tool_box = ToolBox.create!(color: 'red')
|
19
|
+
Tool.create!(name: 'hammer', tool_box: tool_box)
|
20
|
+
Tool.create!(name: 'screwdriver', tool_box: tool_box)
|
21
|
+
# once per tool and once for the tool box
|
22
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:fetch).exactly(3).times.and_return(
|
23
|
+
x: :y
|
24
|
+
)
|
25
|
+
expect(tool_box.tools.as_json(properties: :all)).to eq([
|
26
|
+
{ tool_box: { x: :y }, x: :y },
|
27
|
+
{ tool_box: { x: :y }, x: :y }
|
28
|
+
])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
context 'with read_multi' do
|
32
|
+
it 'responds to read_multi' do
|
33
|
+
expect(Mongoid::CachedJson.config.cache).to respond_to :read_multi
|
34
|
+
end
|
35
|
+
it 'materializes multiple objects using a single partial' do
|
36
|
+
tool_box = ToolBox.create!(color: 'red')
|
37
|
+
tool1 = Tool.create!(name: 'hammer', tool_box: tool_box)
|
38
|
+
tool2 = Tool.create!(name: 'screwdriver', tool_box: tool_box)
|
39
|
+
# once per tool and once for the tool box
|
40
|
+
keys = [
|
41
|
+
"as_json/unspecified/Tool/#{tool1.id}/all/true",
|
42
|
+
"as_json/unspecified/ToolBox/#{tool_box.id}/all/false",
|
43
|
+
"as_json/unspecified/Tool/#{tool2.id}/all/true"
|
44
|
+
]
|
45
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:read_multi).once.with(*keys).and_return(
|
46
|
+
keys[0] => { x: :y },
|
47
|
+
keys[1] => { x: :y },
|
48
|
+
keys[2] => { x: :y }
|
49
|
+
)
|
50
|
+
expect(tool_box.tools.as_json(properties: :all)).to eq([
|
51
|
+
{ tool_box: { x: :y }, x: :y },
|
52
|
+
{ tool_box: { x: :y }, x: :y }
|
53
|
+
])
|
54
|
+
end
|
55
|
+
it 'does not call fetch for missing objects, only write' do
|
56
|
+
tool_box = ToolBox.create!(color: 'red')
|
57
|
+
tool1 = Tool.create!(name: 'hammer', tool_box: tool_box)
|
58
|
+
tool2 = Tool.create!(name: 'screwdriver', tool_box: tool_box)
|
59
|
+
# once per tool and once for the tool box
|
60
|
+
keys = [
|
61
|
+
"as_json/unspecified/Tool/#{tool1.id}/all/true",
|
62
|
+
"as_json/unspecified/ToolBox/#{tool_box.id}/all/false",
|
63
|
+
"as_json/unspecified/Tool/#{tool2.id}/all/true"
|
64
|
+
]
|
65
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:read_multi).once.with(*keys).and_return(
|
66
|
+
keys[0] => { x: :y },
|
67
|
+
keys[1] => { x: :y }
|
68
|
+
)
|
69
|
+
# read_multi returned only 2 of 3 things, don't call fetch, just store the third value
|
70
|
+
expect(Mongoid::CachedJson.config.cache).not_to receive(:fetch)
|
71
|
+
expect(Mongoid::CachedJson.config.cache).to receive(:write).with("as_json/unspecified/Tool/#{tool2.id}/all/true", name: 'screwdriver')
|
72
|
+
expect(tool_box.tools.as_json(properties: :all)).to eq([
|
73
|
+
{ tool_box: { x: :y }, x: :y },
|
74
|
+
{ tool_box: { x: :y }, name: 'screwdriver' }
|
75
|
+
])
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
2
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
3
|
+
|
4
|
+
require 'rspec'
|
5
|
+
require 'mongoid-cached-json'
|
6
|
+
|
7
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each do |f|
|
8
|
+
require f
|
9
|
+
end
|
10
|
+
|
11
|
+
Mongoid.configure do |config|
|
12
|
+
config.connect_to('cached_json_test')
|
13
|
+
end
|
14
|
+
|
15
|
+
RSpec.configure do |config|
|
16
|
+
config.raise_errors_for_deprecations!
|
17
|
+
config.after :each do
|
18
|
+
Mongoid::CachedJson.config.reset!
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class AwesomeImage
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :name
|
6
|
+
field :nickname, default: 'Mona'
|
7
|
+
field :url, default: 'http://example.com/404.html'
|
8
|
+
belongs_to :awesome_artwork
|
9
|
+
|
10
|
+
json_fields \
|
11
|
+
name: {},
|
12
|
+
nickname: {},
|
13
|
+
url: { properties: :public }
|
14
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
class FastJsonArtwork
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :name, default: 'Artwork'
|
6
|
+
field :display_name, default: 'Awesome Artwork'
|
7
|
+
field :price, default: 1000
|
8
|
+
has_one :fast_json_image
|
9
|
+
|
10
|
+
json_fields \
|
11
|
+
name: {},
|
12
|
+
display_name: { properties: :public },
|
13
|
+
price: { properties: :all },
|
14
|
+
image: { type: :reference, definition: :fast_json_image }
|
15
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class FastJsonImage
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :name, default: 'Image'
|
6
|
+
belongs_to :fast_json_artwork
|
7
|
+
has_and_belongs_to_many :fast_json_urls
|
8
|
+
|
9
|
+
json_fields \
|
10
|
+
name: {},
|
11
|
+
urls: { type: :reference, definition: :fast_json_urls }
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
class FastJsonUrl
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :url, default: 'http://art.sy/omg.jpeg'
|
6
|
+
field :is_public, default: false
|
7
|
+
has_and_belongs_to_many :fast_json_image
|
8
|
+
|
9
|
+
json_fields \
|
10
|
+
url: {},
|
11
|
+
is_public: { properties: :all }
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class JsonFoobar
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :foo
|
6
|
+
field :bar
|
7
|
+
field :baz
|
8
|
+
field :default_foo, default: 'DEFAULT_FOO'
|
9
|
+
|
10
|
+
json_fields \
|
11
|
+
:foo => { properties: :short },
|
12
|
+
:bar => { properties: :public },
|
13
|
+
'Baz' => { definition: :baz, version: :unspecified },
|
14
|
+
'Taz' => { definition: :baz, version: :v2 },
|
15
|
+
'Naz' => { definition: :baz, versions: [:v2, :v3] },
|
16
|
+
:renamed_baz => { properties: :all, definition: :baz },
|
17
|
+
:default_foo => {}, # default value for properties is :short
|
18
|
+
:computed_field => { properties: :all, definition: lambda { |x| "#{x.foo}#{x.bar}" } }
|
19
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class JsonManager
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :name
|
6
|
+
field :ssn, default: '123-45-6789'
|
7
|
+
has_many :json_employees
|
8
|
+
belongs_to :supervisor, class_name: 'JsonSupervisor'
|
9
|
+
|
10
|
+
json_fields \
|
11
|
+
name: {},
|
12
|
+
ssn: { properties: :all },
|
13
|
+
employees: { type: :reference, definition: :json_employees }
|
14
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
class JsonParentFoobar
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
belongs_to :json_polymorphic_referenced_foobar
|
6
|
+
embeds_one :json_polymorphic_embedded_foobar
|
7
|
+
|
8
|
+
json_fields \
|
9
|
+
json_polymorphic_referenced_foobar: { type: :reference },
|
10
|
+
json_polymorphic_embedded_foobar: { type: :reference }
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class JsonSupervisor
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::CachedJson
|
4
|
+
|
5
|
+
field :name
|
6
|
+
field :ssn, default: '123-45-6789'
|
7
|
+
has_many :json_managers
|
8
|
+
|
9
|
+
json_fields \
|
10
|
+
name: {},
|
11
|
+
ssn: { properties: :all },
|
12
|
+
managers: { type: :reference, definition: :json_managers, properties: :all, reference_properties: :short }
|
13
|
+
end
|