wayne-friendly 0.5.1
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 +28 -0
- data/CONTRIBUTORS.md +7 -0
- data/LICENSE +20 -0
- data/README.md +288 -0
- data/Rakefile +68 -0
- data/TODO.md +5 -0
- data/VERSION +1 -0
- data/examples/friendly.yml +7 -0
- data/friendly.gemspec +240 -0
- data/lib/friendly.rb +58 -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 +98 -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/data_store.rb +73 -0
- data/lib/friendly/document.rb +70 -0
- data/lib/friendly/document/associations.rb +50 -0
- data/lib/friendly/document/attributes.rb +114 -0
- data/lib/friendly/document/convenience.rb +41 -0
- data/lib/friendly/document/mixin.rb +15 -0
- data/lib/friendly/document/scoping.rb +66 -0
- data/lib/friendly/document/storage.rb +63 -0
- data/lib/friendly/document_table.rb +56 -0
- data/lib/friendly/index.rb +73 -0
- data/lib/friendly/indexer.rb +50 -0
- data/lib/friendly/memcached.rb +48 -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 +43 -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 +111 -0
- data/lib/friendly/table.rb +15 -0
- data/lib/friendly/table_creator.rb +50 -0
- data/lib/friendly/time.rb +14 -0
- data/lib/friendly/translator.rb +33 -0
- data/lib/friendly/uuid.rb +148 -0
- data/lib/tasks/friendly.rake +7 -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 +30 -0
- data/spec/integration/dirty_tracking_spec.rb +43 -0
- data/spec/integration/find_via_cache_spec.rb +101 -0
- data/spec/integration/finder_spec.rb +71 -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/offline_indexing_spec.rb +53 -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 +69 -0
- data/spec/integration/write_through_cache_spec.rb +53 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +105 -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 +125 -0
- data/spec/unit/cache_by_id_spec.rb +102 -0
- data/spec/unit/cache_spec.rb +21 -0
- data/spec/unit/data_store_spec.rb +201 -0
- data/spec/unit/document/attributes_spec.rb +130 -0
- data/spec/unit/document_spec.rb +318 -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/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 +244 -0
- data/spec/unit/translator_spec.rb +91 -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 +337 -0
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::Cache::ByID" do
|
|
4
|
+
before do
|
|
5
|
+
@cache = stub(:set => nil)
|
|
6
|
+
@klass = stub(:name => "Product")
|
|
7
|
+
@id_cache = Friendly::Cache::ByID.new(@klass, [:id], {}, @cache)
|
|
8
|
+
@subject = @id_cache
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it { should be_satisfies(query(:id => "asdf")) }
|
|
12
|
+
it { should be_satisfies(query(:id => ["asdf"])) }
|
|
13
|
+
it { should_not be_satisfies(query(:id => ["asdf"], :name => "asdf")) }
|
|
14
|
+
it { should_not be_satisfies(query(:name => "asdf")) }
|
|
15
|
+
|
|
16
|
+
it "has a default version of 0" do
|
|
17
|
+
@id_cache.version.should == 0
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "is possible to override version" do
|
|
21
|
+
Friendly::Cache::ByID.new(@klass, [:id], {:version => 1}).version.should == 1
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
describe "when an object is created" do
|
|
25
|
+
before do
|
|
26
|
+
@uuid = stub(:to_guid => "xxxx-xxx-xxx-xxxx")
|
|
27
|
+
@doc = stub(:id => @uuid)
|
|
28
|
+
@id_cache.create(@doc)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "sets the cache value in the db" do
|
|
32
|
+
@cache.should have_received(:set).with("Product/0/#{@uuid.to_guid}", @doc)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
describe "when an object is updated" do
|
|
37
|
+
before do
|
|
38
|
+
@uuid = stub(:to_guid => "xxxx-xxx-xxx-xxxx")
|
|
39
|
+
@doc = stub(:id => @uuid)
|
|
40
|
+
@id_cache.update(@doc)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "sets the cache value in the db" do
|
|
44
|
+
@cache.should have_received(:set).with("Product/0/#{@uuid.to_guid}", @doc)
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
describe "when an object is destroyed" do
|
|
49
|
+
before do
|
|
50
|
+
@cache.stubs(:delete)
|
|
51
|
+
@uuid = stub(:to_guid => "xxxx-xxx-xxx-xxxx")
|
|
52
|
+
@doc = stub(:id => @uuid)
|
|
53
|
+
@id_cache.destroy(@doc)
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "deletes the object from cache" do
|
|
57
|
+
@cache.should have_received(:delete).with("Product/0/#{@uuid.to_guid}")
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
describe "finding a single object in cache" do
|
|
62
|
+
before do
|
|
63
|
+
@uuid = stub(:to_guid => "xxxx-xxx-xxx-xxxx")
|
|
64
|
+
@doc = stub
|
|
65
|
+
@cache.stubs(:get).with("Product/0/xxxx-xxx-xxx-xxxx").returns(@doc).yields
|
|
66
|
+
@block_called = true
|
|
67
|
+
@returned = @id_cache.first(query(:id => @uuid)) do
|
|
68
|
+
@block_called = true
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "returns the document" do
|
|
73
|
+
@returned.should == @doc
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "passes along the block to the memcached object" do
|
|
77
|
+
@block_called.should be_true
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
describe "finding many objects in the cache" do
|
|
82
|
+
before do
|
|
83
|
+
@uuid = stub(:to_guid => "xxxx-xxx-xxx-xxxx")
|
|
84
|
+
@doc = stub
|
|
85
|
+
@key = "Product/0/xxxx-xxx-xxx-xxxx"
|
|
86
|
+
@cache.stubs(:multiget).with([@key, @key]).
|
|
87
|
+
returns({@uuid.to_guid => @doc}).yields(@uuid.to_guid)
|
|
88
|
+
@block_called = []
|
|
89
|
+
@returned = @id_cache.all(query(:id => [@uuid, @uuid])) do |id|
|
|
90
|
+
@block_called << id
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
it "returns the values from the hash" do
|
|
95
|
+
@returned.should == [@doc]
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "passes the block along to the cache" do
|
|
99
|
+
@block_called.should == [@uuid.to_guid]
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::Cache" do
|
|
4
|
+
describe "getting a cache object for :id" do
|
|
5
|
+
before do
|
|
6
|
+
@cache = Friendly::Cache.cache_for(stub, [:id], {})
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
it "instantiates a Cache::ByID" do
|
|
10
|
+
@cache.should be_instance_of(Friendly::Cache::ByID)
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe "for other fields" do
|
|
15
|
+
it "raises NotSupported" do
|
|
16
|
+
lambda {
|
|
17
|
+
Friendly::Cache.cache_for(stub, [:asdf], {})
|
|
18
|
+
}.should raise_error(Friendly::NotSupported)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::DataStore" do
|
|
4
|
+
before do
|
|
5
|
+
@users = DatasetFake.new(:insert => 42)
|
|
6
|
+
@db = DatabaseFake.new("users" => @users)
|
|
7
|
+
@datastore = Friendly::DataStore.new(@db)
|
|
8
|
+
@klass = stub(:table_name => "users")
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
describe "inserting data" do
|
|
12
|
+
before do
|
|
13
|
+
@return = @datastore.insert(@klass, :name => "Stewie")
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "inserts it in to the table in the datastore" do
|
|
17
|
+
@users.inserts.length.should == 1
|
|
18
|
+
@users.inserts.should include(:name => "Stewie")
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "returns the id from the dataset" do
|
|
22
|
+
@return.should == 42
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe "retrieving all based on a query" do
|
|
27
|
+
before do
|
|
28
|
+
@users.where = {{:name => "Stewie"} => stub(:map => [{:id => 1}])}
|
|
29
|
+
@return = @datastore.all(@klass, query(:name => "Stewie"))
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "gets the data from the dataset for the klass and makes it an arary" do
|
|
33
|
+
@return.should == [{:id => 1}]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
describe "retrieving all with a limit" do
|
|
38
|
+
before do
|
|
39
|
+
@filtered = stub
|
|
40
|
+
@filtered.stubs(:limit).with(10, nil).returns(stub(:map => [{:id => 1}]))
|
|
41
|
+
@users.where = {{:name => "Stewie"} => @filtered}
|
|
42
|
+
@query = query(:name => "Stewie", :limit! => 10)
|
|
43
|
+
@return = @datastore.all(@klass, @query)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "limits the filtered dataset and returns the results" do
|
|
47
|
+
@return.should == [{:id => 1}]
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
describe "retrieving all with a offset" do
|
|
52
|
+
before do
|
|
53
|
+
@filtered = stub
|
|
54
|
+
@filtered.stubs(:limit).with(nil, 10).returns(stub(:map => [{:id => 1}]))
|
|
55
|
+
@users.where = {{:name => "Stewie"} => @filtered}
|
|
56
|
+
@query = query(:name => "Stewie", :offset! => 10)
|
|
57
|
+
@return = @datastore.all(@klass, @query)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
it "offsets the filtered dataset and returns the results" do
|
|
61
|
+
@return.should == [{:id => 1}]
|
|
62
|
+
end
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
describe "retrieving all with order" do
|
|
66
|
+
before do
|
|
67
|
+
@filtered = stub
|
|
68
|
+
@filtered.stubs(:order).with(:created_at).returns(stub(:map => [{:id => 1}]))
|
|
69
|
+
@users.where = {{:name => "Stewie"} => @filtered}
|
|
70
|
+
@query = query(:name => "Stewie", :order! => :created_at)
|
|
71
|
+
@return = @datastore.all(@klass, @query)
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
it "orders the filtered dataset and returns the results" do
|
|
75
|
+
@return.should == [{:id => 1}]
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
describe "all without conditions" do
|
|
80
|
+
before do
|
|
81
|
+
@all = stub(:map => [])
|
|
82
|
+
@users.stubs(:order).with(:created_at).returns(@all)
|
|
83
|
+
@query = query(:order! => :created_at)
|
|
84
|
+
@return = @datastore.all(@klass, @query)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "orders the filtered dataset and returns the results" do
|
|
88
|
+
@return.should == []
|
|
89
|
+
end
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
describe "retrieving first with conditions" do
|
|
93
|
+
before do
|
|
94
|
+
@users.first = {{:id => 1} => {:id => 1}}
|
|
95
|
+
@return = @datastore.first(@klass, query(:id => 1))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
it "gets the first object matching the conditions from the dataset" do
|
|
99
|
+
@return.should == {:id => 1}
|
|
100
|
+
end
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
describe "updating data" do
|
|
104
|
+
before do
|
|
105
|
+
@filtered = DatasetFake.new(:update => true)
|
|
106
|
+
@users.where = {{:id => 1} => @filtered}
|
|
107
|
+
@return = @datastore.update(@klass, 1, :name => "Peter")
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "filter the dataset by id and update the filtered row" do
|
|
111
|
+
@filtered.updates.length.should == 1
|
|
112
|
+
@filtered.updates.should include(:name => "Peter")
|
|
113
|
+
end
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "deleting data" do
|
|
117
|
+
before do
|
|
118
|
+
@filtered = stub
|
|
119
|
+
@filtered.stubs(:delete)
|
|
120
|
+
@users.where = {{:id => 1} => @filtered}
|
|
121
|
+
@datastore.delete(@klass, 1)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "filters the dataset by id and deletes" do
|
|
125
|
+
@filtered.should have_received(:delete)
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
describe "when a batch transaction has been started" do
|
|
130
|
+
before do
|
|
131
|
+
@datastore.start_batch
|
|
132
|
+
@persistable = stub(:table_name => "some_table")
|
|
133
|
+
@datastore.insert(@persistable, {:some => "attrs"})
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
after { Thread.current[:friendly_batch] = nil }
|
|
137
|
+
|
|
138
|
+
it "adds the attributes to the batch for that table" do
|
|
139
|
+
inserts = Thread.current[:friendly_batch]["some_table"]
|
|
140
|
+
inserts.length.should == 1
|
|
141
|
+
inserts.should include(:some => "attrs")
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
describe "starting a batch" do
|
|
146
|
+
before do
|
|
147
|
+
@datastore.start_batch
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
after { Thread.current[:friendly_batch] = nil }
|
|
151
|
+
|
|
152
|
+
it "sets Thread.current[:friendly_batch] to empty hash" do
|
|
153
|
+
Thread.current[:friendly_batch].should == {}
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
describe "resetting a batch transaction" do
|
|
158
|
+
before do
|
|
159
|
+
@db.stubs(:from)
|
|
160
|
+
Thread.current[:friendly_batch] = {"users" => [{:a => "b"}]}
|
|
161
|
+
@datastore.reset_batch
|
|
162
|
+
end
|
|
163
|
+
after { Thread.current[:friendly_batch] = nil }
|
|
164
|
+
|
|
165
|
+
it "sets Thread.current[:friendly_batch] to nil without inserting" do
|
|
166
|
+
Thread.current[:friendly_batch].should be_nil
|
|
167
|
+
@db.should have_received(:from).never
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
describe "flushing a batch" do
|
|
172
|
+
before do
|
|
173
|
+
@records = [{:name => "Stewie"}, {:name => "Brian"}]
|
|
174
|
+
Thread.current[:friendly_batch] = {"users" => @records}
|
|
175
|
+
@users.stubs(:multi_insert)
|
|
176
|
+
@datastore.flush_batch
|
|
177
|
+
end
|
|
178
|
+
after { Thread.current[:friendly_batch] = nil }
|
|
179
|
+
|
|
180
|
+
it "performs the multi_insert on each table" do
|
|
181
|
+
@users.should have_received(:multi_insert).
|
|
182
|
+
with(@records, :commit_every => 1000)
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
it "resets the batch" do
|
|
186
|
+
Thread.current[:friendly_batch].should be_nil
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
describe "counting" do
|
|
191
|
+
before do
|
|
192
|
+
@filtered = stub(:count => 10)
|
|
193
|
+
@users.stubs(:where).with(:name => "James").returns(@filtered)
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "fitlers and counts in the db" do
|
|
197
|
+
@datastore.count(@klass, query(:name => "James")).should == 10
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require File.expand_path("../../../spec_helper", __FILE__)
|
|
2
|
+
|
|
3
|
+
describe "Friendly::Document::Attributes" do
|
|
4
|
+
before do
|
|
5
|
+
@klass = Class.new do
|
|
6
|
+
include Friendly::Document::Attributes
|
|
7
|
+
|
|
8
|
+
attribute :name, String
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
describe "#initialize" do
|
|
13
|
+
it "sets the attributes using the setters" do
|
|
14
|
+
@doc = @klass.new :name => "Bond"
|
|
15
|
+
@doc.name.should == "Bond"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
it "assigns the default values" do
|
|
19
|
+
@klass.attribute :id, Friendly::UUID
|
|
20
|
+
@klass.attributes[:id] = stub(:assign_default_value => nil)
|
|
21
|
+
@klass.attributes[:name] = stub(:assign_default_value => nil,
|
|
22
|
+
:typecast => "Bond")
|
|
23
|
+
@doc = @klass.new :name => "Bond"
|
|
24
|
+
@klass.attributes[:id].should have_received(:assign_default_value).with(@doc)
|
|
25
|
+
@klass.attributes[:name].should have_received(:assign_default_value).with(@doc)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
describe "#attributes=" do
|
|
30
|
+
before do
|
|
31
|
+
@object = @klass.new
|
|
32
|
+
@object.attributes = {:name => "Bond"}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "sets the attributes using the setters" do
|
|
36
|
+
@object.name.should == "Bond"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "raises ArgumentError when there are duplicate keys of differing type" do
|
|
40
|
+
lambda {
|
|
41
|
+
@object.attributes = {:name => "Bond", "name" => "Bond"}
|
|
42
|
+
}.should raise_error(ArgumentError)
|
|
43
|
+
end
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
describe "#to_hash" do
|
|
47
|
+
before do
|
|
48
|
+
@object = @klass.new(:name => "Stewie")
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "creates a hash that contains its attributes" do
|
|
52
|
+
@object.to_hash.should == {:name => "Stewie"}
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
describe "#assign" do
|
|
57
|
+
before do
|
|
58
|
+
@object = @klass.new
|
|
59
|
+
@object.assign(:name, "James Bond")
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "assigns the value to the attribute" do
|
|
63
|
+
@object.name.should == "James Bond"
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
describe "#will_change" do
|
|
68
|
+
before do
|
|
69
|
+
@klass.send(:attr_accessor, :some_variable)
|
|
70
|
+
@object = @klass.new
|
|
71
|
+
@object.some_variable = "Some value"
|
|
72
|
+
@object.will_change(:some_variable)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "makes the object #changed?" do
|
|
76
|
+
@object.should be_changed
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
it "returns the value of the variable for #attribute_was" do
|
|
80
|
+
@object.attribute_was(:some_variable).should == "Some value"
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
it "returns true for attribute_changed?(:some_variable)" do
|
|
84
|
+
@object.should be_attribute_changed(:some_variable)
|
|
85
|
+
end
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
describe "#reset_changes" do
|
|
89
|
+
before do
|
|
90
|
+
@klass.send(:attr_accessor, :some_variable)
|
|
91
|
+
@object = @klass.new
|
|
92
|
+
@object.some_variable = "Some value"
|
|
93
|
+
@object.will_change(:some_variable)
|
|
94
|
+
@object.reset_changes
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
it "resets the changed status of the object" do
|
|
98
|
+
@object.should_not be_changed
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "returns nil for attribute_was(:some_variable)" do
|
|
102
|
+
@object.attribute_was(:some_variable).should be_nil
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "returns false for attribute_changed?(:some_variable)" do
|
|
106
|
+
@object.should_not be_attribute_changed(:some_variable)
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
describe "#new_without_change_tracking" do
|
|
111
|
+
before do
|
|
112
|
+
@klass = Class.new do
|
|
113
|
+
attr_reader :name
|
|
114
|
+
|
|
115
|
+
def name=(name)
|
|
116
|
+
will_change(:name)
|
|
117
|
+
@name = name
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
include Friendly::Document::Attributes
|
|
121
|
+
end
|
|
122
|
+
@doc = @klass.new_without_change_tracking(:name => "James")
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "initializes and then calls reset_changes" do
|
|
126
|
+
@doc.name.should == "James"
|
|
127
|
+
@doc.should_not be_changed
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|