friendly_postgres 0.4.3
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.
- data/.document +2 -0
- data/.gitignore +26 -0
- data/APACHE-LICENSE +202 -0
- data/CHANGELOG.md +19 -0
- data/CONTRIBUTORS.md +7 -0
- data/LICENSE +20 -0
- data/README.md +265 -0
- data/Rakefile +68 -0
- data/TODO.md +5 -0
- data/VERSION +1 -0
- data/examples/friendly.yml +7 -0
- data/friendly.gemspec +232 -0
- data/lib/friendly.rb +54 -0
- data/lib/friendly/associations.rb +7 -0
- data/lib/friendly/associations/association.rb +34 -0
- data/lib/friendly/associations/set.rb +37 -0
- data/lib/friendly/attribute.rb +91 -0
- data/lib/friendly/boolean.rb +10 -0
- data/lib/friendly/cache.rb +24 -0
- data/lib/friendly/cache/by_id.rb +33 -0
- data/lib/friendly/config.rb +5 -0
- data/lib/friendly/data_store.rb +72 -0
- data/lib/friendly/document.rb +257 -0
- data/lib/friendly/document_table.rb +56 -0
- data/lib/friendly/index.rb +73 -0
- data/lib/friendly/memcached.rb +48 -0
- data/lib/friendly/named_scope.rb +17 -0
- data/lib/friendly/newrelic.rb +6 -0
- data/lib/friendly/query.rb +42 -0
- data/lib/friendly/scope.rb +100 -0
- data/lib/friendly/scope_proxy.rb +45 -0
- data/lib/friendly/sequel_monkey_patches.rb +34 -0
- data/lib/friendly/storage.rb +31 -0
- data/lib/friendly/storage_factory.rb +24 -0
- data/lib/friendly/storage_proxy.rb +103 -0
- data/lib/friendly/table.rb +15 -0
- data/lib/friendly/table_creator.rb +48 -0
- data/lib/friendly/time.rb +14 -0
- data/lib/friendly/translator.rb +32 -0
- data/lib/friendly/uuid.rb +148 -0
- data/rails/init.rb +3 -0
- data/spec/config.yml.example +7 -0
- data/spec/fakes/data_store_fake.rb +29 -0
- data/spec/fakes/database_fake.rb +12 -0
- data/spec/fakes/dataset_fake.rb +28 -0
- data/spec/fakes/document.rb +18 -0
- data/spec/fakes/serializer_fake.rb +12 -0
- data/spec/fakes/time_fake.rb +12 -0
- data/spec/integration/ad_hoc_scopes_spec.rb +42 -0
- data/spec/integration/basic_object_lifecycle_spec.rb +114 -0
- data/spec/integration/batch_insertion_spec.rb +29 -0
- data/spec/integration/convenience_api_spec.rb +25 -0
- data/spec/integration/count_spec.rb +12 -0
- data/spec/integration/default_value_spec.rb +15 -0
- data/spec/integration/find_via_cache_spec.rb +101 -0
- data/spec/integration/finder_spec.rb +64 -0
- data/spec/integration/has_many_spec.rb +18 -0
- data/spec/integration/index_spec.rb +57 -0
- data/spec/integration/named_scope_spec.rb +34 -0
- data/spec/integration/pagination_spec.rb +63 -0
- data/spec/integration/scope_chaining_spec.rb +22 -0
- data/spec/integration/table_creator_spec.rb +64 -0
- data/spec/integration/write_through_cache_spec.rb +53 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +103 -0
- data/spec/unit/associations/association_spec.rb +57 -0
- data/spec/unit/associations/set_spec.rb +43 -0
- data/spec/unit/attribute_spec.rb +105 -0
- data/spec/unit/cache_by_id_spec.rb +102 -0
- data/spec/unit/cache_spec.rb +21 -0
- data/spec/unit/config_spec.rb +4 -0
- data/spec/unit/data_store_spec.rb +188 -0
- data/spec/unit/document_spec.rb +358 -0
- data/spec/unit/document_table_spec.rb +126 -0
- data/spec/unit/friendly_spec.rb +25 -0
- data/spec/unit/index_spec.rb +196 -0
- data/spec/unit/memcached_spec.rb +114 -0
- data/spec/unit/named_scope_spec.rb +16 -0
- data/spec/unit/query_spec.rb +104 -0
- data/spec/unit/scope_proxy_spec.rb +44 -0
- data/spec/unit/scope_spec.rb +113 -0
- data/spec/unit/storage_factory_spec.rb +59 -0
- data/spec/unit/storage_proxy_spec.rb +218 -0
- data/spec/unit/translator_spec.rb +96 -0
- data/website/index.html +210 -0
- data/website/scripts/clipboard.swf +0 -0
- data/website/scripts/shBrushAS3.js +61 -0
- data/website/scripts/shBrushBash.js +66 -0
- data/website/scripts/shBrushCSharp.js +67 -0
- data/website/scripts/shBrushColdFusion.js +102 -0
- data/website/scripts/shBrushCpp.js +99 -0
- data/website/scripts/shBrushCss.js +93 -0
- data/website/scripts/shBrushDelphi.js +57 -0
- data/website/scripts/shBrushDiff.js +43 -0
- data/website/scripts/shBrushErlang.js +54 -0
- data/website/scripts/shBrushGroovy.js +69 -0
- data/website/scripts/shBrushJScript.js +52 -0
- data/website/scripts/shBrushJava.js +59 -0
- data/website/scripts/shBrushJavaFX.js +60 -0
- data/website/scripts/shBrushPerl.js +74 -0
- data/website/scripts/shBrushPhp.js +91 -0
- data/website/scripts/shBrushPlain.js +35 -0
- data/website/scripts/shBrushPowerShell.js +76 -0
- data/website/scripts/shBrushPython.js +66 -0
- data/website/scripts/shBrushRuby.js +57 -0
- data/website/scripts/shBrushScala.js +53 -0
- data/website/scripts/shBrushSql.js +68 -0
- data/website/scripts/shBrushVb.js +58 -0
- data/website/scripts/shBrushXml.js +71 -0
- data/website/scripts/shCore.js +30 -0
- data/website/scripts/shLegacy.js +30 -0
- data/website/styles/friendly.css +103 -0
- data/website/styles/help.png +0 -0
- data/website/styles/ie.css +35 -0
- data/website/styles/magnifier.png +0 -0
- data/website/styles/page_white_code.png +0 -0
- data/website/styles/page_white_copy.png +0 -0
- data/website/styles/print.css +29 -0
- data/website/styles/printer.png +0 -0
- data/website/styles/screen.css +257 -0
- data/website/styles/shCore.css +330 -0
- data/website/styles/shThemeDefault.css +173 -0
- data/website/styles/shThemeDjango.css +176 -0
- data/website/styles/shThemeEclipse.css +190 -0
- data/website/styles/shThemeEmacs.css +175 -0
- data/website/styles/shThemeFadeToGrey.css +177 -0
- data/website/styles/shThemeMidnight.css +175 -0
- data/website/styles/shThemeRDark.css +175 -0
- metadata +302 -0
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::ScopeProxy" do
|
|
4
|
+
before do
|
|
5
|
+
@klass = Class.new
|
|
6
|
+
@scope = stub
|
|
7
|
+
@scope_klass = stub
|
|
8
|
+
@scope_proxy = Friendly::ScopeProxy.new(@klass, @scope_klass)
|
|
9
|
+
@params = {:order! => :created_at.desc}
|
|
10
|
+
@scope_klass.stubs(:new).with(@klass, @params).returns(@scope)
|
|
11
|
+
@klass.stubs(:scope_proxy).returns(@scope_proxy)
|
|
12
|
+
@scope_proxy.add_named(:recent, @params)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "returns false for has_named_scope if it doesnt have one by that name" do
|
|
16
|
+
@scope_proxy.should_not be_has_named_scope(:whatever)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe "adding a scope" do
|
|
20
|
+
it "adds a scope by that name to the set" do
|
|
21
|
+
@scope_proxy.get(:recent).should == @params
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
it "adds a method to the klass that returns an instance of the scope" do
|
|
25
|
+
@klass.recent.should == @scope
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "returns true for #has_named_scope?(name)" do
|
|
29
|
+
@scope_proxy.should be_has_named_scope(:recent)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
describe "getting an instance of a scope" do
|
|
34
|
+
it "instantiates Scope" do
|
|
35
|
+
@scope_proxy.get_instance(:recent).should == @scope
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
describe "accessing an ad_hoc scope" do
|
|
40
|
+
it "instantiates Scope" do
|
|
41
|
+
@scope_proxy.ad_hoc(@params).should == @scope
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::Scope" do
|
|
4
|
+
before do
|
|
5
|
+
@klass = stub
|
|
6
|
+
@scope_parameters = {:name => "Quagmire", :order! => :created_at.desc}
|
|
7
|
+
@scope = Friendly::Scope.new(@klass, @scope_parameters)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
describe "#all" do
|
|
11
|
+
before do
|
|
12
|
+
@documents = stub
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "delegates to klass with the scope parameters" do
|
|
16
|
+
@klass.stubs(:all).with(@scope_parameters).returns(@documents)
|
|
17
|
+
@scope.all.should == @documents
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "merges additional parameters" do
|
|
21
|
+
merged = @scope_parameters.merge(:name => "Joe")
|
|
22
|
+
@klass.stubs(:all).with(merged).returns(@documents)
|
|
23
|
+
@scope.all(:name => "Joe").should == @documents
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "#first" do
|
|
28
|
+
before do
|
|
29
|
+
@document = stub
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "delegates to klass with the scope parameters" do
|
|
33
|
+
@klass.stubs(:first).with(@scope_parameters).returns(@document)
|
|
34
|
+
@scope.first.should == @document
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "merges additional parameters" do
|
|
38
|
+
merged = @scope_parameters.merge(:name => "Joe")
|
|
39
|
+
@klass.stubs(:first).with(merged).returns(@document)
|
|
40
|
+
@scope.first(:name => "Joe").should == @document
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
describe "#paginate" do
|
|
45
|
+
before do
|
|
46
|
+
@documents = stub
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "delegates to klass with the scope parameters" do
|
|
50
|
+
@klass.stubs(:paginate).with(@scope_parameters).returns(@documents)
|
|
51
|
+
@scope.paginate.should == @documents
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
it "merges additional parameters" do
|
|
55
|
+
merged = @scope_parameters.merge(:name => "Joe")
|
|
56
|
+
@klass.stubs(:paginate).with(merged).returns(@documents)
|
|
57
|
+
@scope.paginate(:name => "Joe").should == @documents
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "#build" do
|
|
62
|
+
it "instantiates klass with the scope parameters (minus modifiers)" do
|
|
63
|
+
@doc = stub
|
|
64
|
+
@klass.stubs(:new).with(:name => "Quagmire").returns(@doc)
|
|
65
|
+
@scope.build.should == @doc
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
it "merges additional parameters" do
|
|
69
|
+
@doc = stub
|
|
70
|
+
@klass.stubs(:new).with(:name => "Fred").returns(@doc)
|
|
71
|
+
@scope.build(:name => "Fred").should == @doc
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
describe "#create" do
|
|
76
|
+
it "delegates to klass#create with the scope parameters (minus modifiers)" do
|
|
77
|
+
@doc = stub
|
|
78
|
+
@klass.stubs(:create).with(:name => "Quagmire").returns(@doc)
|
|
79
|
+
@scope.create.should == @doc
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "merges additional parameters" do
|
|
83
|
+
@doc = stub
|
|
84
|
+
@klass.stubs(:create).with(:name => "Fred").returns(@doc)
|
|
85
|
+
@scope.create(:name => "Fred").should == @doc
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
describe "chaining another named scope" do
|
|
90
|
+
before do
|
|
91
|
+
@recent_params = {:order! => :created_at.desc}
|
|
92
|
+
@recent = Friendly::Scope.new(@klass, @recent_params)
|
|
93
|
+
@klass.stubs(:has_named_scope?).with(:recent).returns(true)
|
|
94
|
+
@klass.stubs(:recent).returns(@recent)
|
|
95
|
+
@scope_params = {:name => "Joe"}
|
|
96
|
+
@scope = Friendly::Scope.new(@klass, @scope_params)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "responds to the other scope method" do
|
|
100
|
+
@scope.should be_respond_to(:recent)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
it "creates a new scope that merges the two scopes together" do
|
|
104
|
+
merged_parameters = @scope_params.merge(@recent_params)
|
|
105
|
+
@scope.recent.parameters.should == merged_parameters
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "gives precedence to scopes on the right" do
|
|
109
|
+
@quagmire = Friendly::Scope.new(@klass, :name => "Quagmire")
|
|
110
|
+
(@scope + @quagmire).parameters[:name].should == "Quagmire"
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::StorageFactory" do
|
|
4
|
+
before do
|
|
5
|
+
@doc_table = stub
|
|
6
|
+
@doc_table_klass = stub(:new => @doc_table)
|
|
7
|
+
@index = stub
|
|
8
|
+
@index_klass = stub(:new => @index)
|
|
9
|
+
@cache_by_id = stub
|
|
10
|
+
@cache_klass = stub(:cache_for => @cache_by_id)
|
|
11
|
+
@factory = Friendly::StorageFactory.new(@doc_table_klass, @index_klass,
|
|
12
|
+
@cache_klass)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
describe "creating a document table" do
|
|
16
|
+
before do
|
|
17
|
+
@klass = stub
|
|
18
|
+
@returned = @factory.document_table(@klass)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns the result of the constructor" do
|
|
22
|
+
@returned.should == @doc_table
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "passes along the arguments to the constructor" do
|
|
26
|
+
@doc_table_klass.should have_received(:new).with(@klass)
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
describe "creating an index table" do
|
|
31
|
+
before do
|
|
32
|
+
@klass = stub
|
|
33
|
+
@returned = @factory.index(@klass)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "returns the result of the constructor" do
|
|
37
|
+
@returned.should == @index
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "passes along the arguments to the constructor" do
|
|
41
|
+
@index_klass.should have_received(:new).with(@klass)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
describe "creating an id cache table" do
|
|
46
|
+
before do
|
|
47
|
+
@klass = stub
|
|
48
|
+
@returned = @factory.cache(@klass, [:id])
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "delegates to Cache.for" do
|
|
52
|
+
@returned.should == @cache_by_id
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "supplies arguments to Cache" do
|
|
56
|
+
@cache_klass.should have_received(:cache_for).with(@klass, [:id])
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::StorageProxy" do
|
|
4
|
+
before do
|
|
5
|
+
@klass = stub
|
|
6
|
+
@index = stub(:create => nil,
|
|
7
|
+
:update => nil,
|
|
8
|
+
:destroy => nil,
|
|
9
|
+
:satsifies? => nil)
|
|
10
|
+
@table = stub(:satisfies? => false, :create => nil,
|
|
11
|
+
:update => nil, :destroy => nil)
|
|
12
|
+
@storage_factory = stub(:index => @index)
|
|
13
|
+
@storage_factory.stubs(:document_table).with(@klass).returns(@table)
|
|
14
|
+
@storage = Friendly::StorageProxy.new(@klass, @storage_factory)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "instantiates and adds a document table by default" do
|
|
18
|
+
@storage.tables.should include(@table)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe "doing a `first`" do
|
|
22
|
+
before do
|
|
23
|
+
@id = stub
|
|
24
|
+
@index = stub(:satisfies? => true, :first => @id)
|
|
25
|
+
@storage.tables << @index
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
describe "when there's an index that matches the conditions" do
|
|
29
|
+
before do
|
|
30
|
+
@result = @storage.first(:name => "x")
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "delegates to the index that satisfies the conditions" do
|
|
34
|
+
@index.should have_received(:first).once
|
|
35
|
+
@index.should have_received(:first).with(:name => "x")
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "returns id" do
|
|
39
|
+
@result.should == @id
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
describe "when there's no index that matches" do
|
|
44
|
+
before do
|
|
45
|
+
@index.stubs(:satisfies?).returns(false)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "raises MissingIndex" do
|
|
49
|
+
lambda {
|
|
50
|
+
@storage.first(:name => "x")
|
|
51
|
+
}.should raise_error(Friendly::MissingIndex)
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "doing an `all`" do
|
|
57
|
+
before do
|
|
58
|
+
@ids = [stub]
|
|
59
|
+
@index = stub(:satisfies? => true, :all => @ids)
|
|
60
|
+
@storage.tables << @index
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
describe "when there's an index that matches the conditions" do
|
|
64
|
+
before do
|
|
65
|
+
@query = query(:name => "x")
|
|
66
|
+
@result = @storage.all(@query)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "delegates to the index that satisfies the conditions" do
|
|
70
|
+
@index.should have_received(:all).once
|
|
71
|
+
@index.should have_received(:all).with(@query)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "returns the results" do
|
|
75
|
+
@result.should == @ids
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "when there's no index that matches" do
|
|
80
|
+
before do
|
|
81
|
+
@index.stubs(:satisfies?).returns(false)
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
it "raises MissingIndex" do
|
|
85
|
+
lambda {
|
|
86
|
+
@storage.all(:name => "x")
|
|
87
|
+
}.should raise_error(Friendly::MissingIndex)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
describe "when :preserve_order is true" do
|
|
92
|
+
before do
|
|
93
|
+
@docs = [stub(:id => 4), stub(:id => 3), stub(:id => 2)]
|
|
94
|
+
@index.stubs(:all).returns(@docs)
|
|
95
|
+
@result = @storage.all(query(:id => [2,3,4], :preserve_order! => true))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "sorts the results based on the order they're supplied in the query" do
|
|
99
|
+
@result.should == @docs.reverse
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
describe "adding an index to the set" do
|
|
105
|
+
before do
|
|
106
|
+
@storage.add(:name, :age)
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
it "creates an index" do
|
|
110
|
+
@storage_factory.should have_received(:index).once
|
|
111
|
+
@storage_factory.should have_received(:index).with(@klass, :name, :age)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "adds the index to the set" do
|
|
115
|
+
@storage.tables.should include(@index)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
describe "saving data" do
|
|
120
|
+
before do
|
|
121
|
+
@index_two = stub(:create => nil, :update => nil, :destroy => nil)
|
|
122
|
+
@storage_factory.stubs(:index).returns(@index).then.returns(@index_two)
|
|
123
|
+
@cache = stub(:create => nil, :update => nil, :destroy => nil)
|
|
124
|
+
@storage_factory.stubs(:cache).returns(@cache)
|
|
125
|
+
@storage.add(:name)
|
|
126
|
+
@storage.add(:age)
|
|
127
|
+
@storage.cache([:id])
|
|
128
|
+
@doc = stub
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
describe "on create" do
|
|
132
|
+
before do
|
|
133
|
+
@storage.create(@doc)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
it "delegates to all of the storage including caches" do
|
|
137
|
+
@index.should have_received(:create).with(@doc)
|
|
138
|
+
@index_two.should have_received(:create).with(@doc)
|
|
139
|
+
@table.should have_received(:create).with(@doc)
|
|
140
|
+
@cache.should have_received(:create).with(@doc)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
describe "on update" do
|
|
145
|
+
before do
|
|
146
|
+
@storage.update(@doc)
|
|
147
|
+
end
|
|
148
|
+
|
|
149
|
+
it "delegates to all of the storage including caches" do
|
|
150
|
+
@index.should have_received(:update).with(@doc)
|
|
151
|
+
@index_two.should have_received(:update).with(@doc)
|
|
152
|
+
@table.should have_received(:update).with(@doc)
|
|
153
|
+
@cache.should have_received(:update).with(@doc)
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
describe "on destroy" do
|
|
158
|
+
before do
|
|
159
|
+
@storage.destroy(@doc)
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
it "delegates to all of the storage including caches" do
|
|
163
|
+
@index.should have_received(:destroy).with(@doc)
|
|
164
|
+
@index_two.should have_received(:destroy).with(@doc)
|
|
165
|
+
@table.should have_received(:destroy).with(@doc)
|
|
166
|
+
@cache.should have_received(:destroy).with(@doc)
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe "adding a cache object" do
|
|
172
|
+
before do
|
|
173
|
+
@cache = stub
|
|
174
|
+
@storage_factory.stubs(:cache).returns(@cache)
|
|
175
|
+
@storage.cache([:id])
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
it "gets one from the storage_proxy" do
|
|
179
|
+
@storage_factory.should have_received(:cache).with(@klass, [:id], {})
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
it "adds it to its set of caches" do
|
|
183
|
+
@storage.caches.should include(@cache)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
describe "finding with a matching cache" do
|
|
188
|
+
before do
|
|
189
|
+
@cache = stub(:satisfies? => true, :first => nil)
|
|
190
|
+
@storage_factory.stubs(:cache).returns(@cache)
|
|
191
|
+
@storage.cache([:id])
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
describe "when there's a hit" do
|
|
195
|
+
before do
|
|
196
|
+
@doc = stub
|
|
197
|
+
@cache.stubs(:first).returns(@doc)
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
it "returns the result from the cache" do
|
|
201
|
+
@storage.first(:id => "x").should == @doc
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
|
|
206
|
+
describe "counting objects" do
|
|
207
|
+
before do
|
|
208
|
+
@index = stub(:count => 10)
|
|
209
|
+
@index.stubs(:satisfies?).with(:x => 1).returns(true)
|
|
210
|
+
@storage_factory.stubs(:index).returns(@index)
|
|
211
|
+
@storage.add(:a)
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "delegates to a satisfying index" do
|
|
215
|
+
@storage.count(:x => 1).should == 10
|
|
216
|
+
end
|
|
217
|
+
end
|
|
218
|
+
end
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
require 'ostruct'
|
|
3
|
+
|
|
4
|
+
describe "Friendly::Translator" do
|
|
5
|
+
before do
|
|
6
|
+
@serializer = stub
|
|
7
|
+
@time = stub
|
|
8
|
+
@translator = Friendly::Translator.new(@serializer, @time)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "translating a row to an object" do
|
|
12
|
+
before do
|
|
13
|
+
@serializer.stubs(:parse).with("THE JSON").returns(:name => "Stewie")
|
|
14
|
+
@time = Time.new
|
|
15
|
+
@row = {:added_id => 12345,
|
|
16
|
+
:created_at => @time,
|
|
17
|
+
:updated_at => @time,
|
|
18
|
+
:attributes => "THE JSON"}
|
|
19
|
+
@klass = FakeDocument
|
|
20
|
+
@doc = @translator.to_object(@klass, @row)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "creates a klass with the attributes from the json" do
|
|
24
|
+
@doc.name.should == "Stewie"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
it "sets updated_at" do
|
|
28
|
+
@doc.updated_at.should == @time
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "sets new_record to false" do
|
|
32
|
+
@doc.new_record.should be_false
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "translating from a document in to a record" do
|
|
37
|
+
describe "when the document has yet to be saved" do
|
|
38
|
+
before do
|
|
39
|
+
@hash = {:name => "Stewie"}
|
|
40
|
+
@time.stubs(:new).returns(Time.new)
|
|
41
|
+
@serializer.stubs(:generate).with(@hash).returns("SOME JSON")
|
|
42
|
+
@document = stub(:to_hash => @hash,
|
|
43
|
+
:new_record? => true,
|
|
44
|
+
:created_at => nil,
|
|
45
|
+
:id => 12345)
|
|
46
|
+
@record = @translator.to_record(@document)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
it "serializes the attributes" do
|
|
50
|
+
@record[:attributes].should == "SOME JSON"
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "sets updated_at" do
|
|
54
|
+
@record[:updated_at].should == @time.new
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "sets the id from the document" do
|
|
58
|
+
@record[:id].should == 12345
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
describe "when the document has already been saved" do
|
|
63
|
+
before do
|
|
64
|
+
@created_at = Time.new
|
|
65
|
+
@hash = {:name => "Stewie",
|
|
66
|
+
:id => 1,
|
|
67
|
+
:created_at => @created_at,
|
|
68
|
+
:updated_at => Time.new}
|
|
69
|
+
@time.stubs(:new).returns(Time.new + 5000)
|
|
70
|
+
@serializer.stubs(:generate).returns("SOME JSON")
|
|
71
|
+
@document = stub(:to_hash => @hash,
|
|
72
|
+
:created_at => @created_at,
|
|
73
|
+
:new_record? => false,
|
|
74
|
+
:id => 12345)
|
|
75
|
+
@record = @translator.to_record(@document)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "serializes the attributes" do
|
|
79
|
+
@serializer.should have_received(:generate).with(:name => "Stewie")
|
|
80
|
+
@record[:attributes].should == "SOME JSON"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "doesn't bump the created_at" do
|
|
84
|
+
@record[:created_at].should == @created_at
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "should bump the updated_at" do
|
|
88
|
+
@record[:updated_at].should == @time.new
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "takes the id from the documetn" do
|
|
92
|
+
@record[:id].should == 12345
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|