strokedb 0.0.2.1 → 0.0.2.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.
- data/README +18 -20
- data/bench.html +4001 -0
- data/bin/strokedb +14 -0
- data/examples/movies.rb +105 -0
- data/examples/movies2.rb +97 -0
- data/examples/strokewiki/README +28 -0
- data/examples/strokewiki/view/edit.xhtml +27 -0
- data/examples/strokewiki/view/new.xhtml +26 -0
- data/examples/strokewiki/view/pages.xhtml +27 -0
- data/examples/strokewiki/view/show.xhtml +40 -0
- data/examples/strokewiki/view/versions.xhtml +25 -0
- data/examples/strokewiki/wiki.rb +106 -0
- data/examples/todo.rb +92 -0
- data/lib/strokedb.rb +85 -0
- data/lib/{config → strokedb}/config.rb +14 -9
- data/lib/strokedb/console.rb +87 -0
- data/lib/strokedb/core_ext.rb +10 -0
- data/lib/{util/ext → strokedb/core_ext}/blank.rb +1 -1
- data/lib/{util/ext → strokedb/core_ext}/enumerable.rb +0 -0
- data/lib/{util/ext → strokedb/core_ext}/fixnum.rb +0 -0
- data/lib/strokedb/core_ext/float.rb +4 -0
- data/lib/{util/ext → strokedb/core_ext}/hash.rb +0 -0
- data/lib/strokedb/core_ext/infinity.rb +33 -0
- data/lib/strokedb/core_ext/kernel.rb +41 -0
- data/lib/strokedb/core_ext/object.rb +16 -0
- data/lib/{util/ext → strokedb/core_ext}/string.rb +28 -1
- data/lib/strokedb/core_ext/symbol.rb +13 -0
- data/lib/strokedb/data_structures.rb +5 -0
- data/lib/strokedb/data_structures/chunked_skiplist.rb +123 -0
- data/lib/{data_structures → strokedb/data_structures}/inverted_list.rb +0 -0
- data/lib/{data_structures → strokedb/data_structures}/point_query.rb +0 -0
- data/lib/strokedb/data_structures/simple_skiplist.rb +350 -0
- data/lib/{data_structures → strokedb/data_structures}/skiplist.rb +1 -1
- data/lib/{document → strokedb}/document.rb +180 -71
- data/lib/{document → strokedb/document}/callback.rb +0 -0
- data/lib/{document → strokedb/document}/delete.rb +2 -2
- data/lib/strokedb/document/dsl.rb +4 -0
- data/lib/{document → strokedb/document/dsl}/associations.rb +0 -0
- data/lib/{document → strokedb/document/dsl}/coercions.rb +0 -0
- data/lib/strokedb/document/dsl/meta_dsl.rb +7 -0
- data/lib/{document → strokedb/document/dsl}/validations.rb +26 -21
- data/lib/{document → strokedb/document/dsl}/virtualize.rb +0 -0
- data/lib/{document → strokedb/document}/meta.rb +92 -29
- data/lib/{document → strokedb/document}/slot.rb +17 -5
- data/lib/{document → strokedb/document}/util.rb +0 -0
- data/lib/{document → strokedb/document}/versions.rb +2 -2
- data/lib/strokedb/index.rb +2 -0
- data/lib/strokedb/nsurl.rb +24 -0
- data/lib/strokedb/store.rb +149 -0
- data/lib/strokedb/stores.rb +6 -0
- data/lib/{stores → strokedb/stores}/chainable_storage.rb +20 -14
- data/lib/strokedb/stores/file_storage.rb +118 -0
- data/lib/{stores/inverted_list_index → strokedb/stores}/inverted_list_file_storage.rb +50 -0
- data/lib/strokedb/stores/memory_storage.rb +80 -0
- data/lib/{stores → strokedb/stores}/remote_store.rb +10 -4
- data/lib/strokedb/sync.rb +4 -0
- data/lib/{sync → strokedb/sync}/chain_sync.rb +0 -0
- data/lib/{sync → strokedb/sync}/diff.rb +12 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/array.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/default.rb +0 -0
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/hash.rb +1 -1
- data/lib/{sync/stroke_diff → strokedb/sync/diff}/string.rb +1 -1
- data/lib/{sync → strokedb/sync}/lamport_timestamp.rb +0 -0
- data/lib/{sync → strokedb/sync}/store_sync.rb +15 -7
- data/lib/strokedb/transaction.rb +78 -0
- data/lib/{util → strokedb}/util.rb +14 -7
- data/lib/strokedb/util/attach_dsl.rb +29 -0
- data/lib/{util → strokedb/util}/blankslate.rb +0 -0
- data/lib/strokedb/util/class_optimization.rb +93 -0
- data/lib/{util → strokedb/util}/inflect.rb +0 -0
- data/lib/strokedb/util/java_util.rb +13 -0
- data/lib/{util → strokedb/util}/lazy_array.rb +0 -0
- data/lib/{util → strokedb/util}/lazy_mapping_array.rb +4 -0
- data/lib/{util → strokedb/util}/lazy_mapping_hash.rb +0 -0
- data/lib/{util → strokedb/util}/serialization.rb +21 -0
- data/lib/strokedb/util/uuid.rb +159 -0
- data/lib/{util → strokedb/util}/xml.rb +0 -0
- data/lib/{view → strokedb}/view.rb +2 -2
- data/lib/strokedb/volumes.rb +5 -0
- data/lib/strokedb/volumes/archive_volume.rb +165 -0
- data/lib/strokedb/volumes/block_volume.rb +169 -0
- data/lib/strokedb/volumes/distributed_pointer.rb +43 -0
- data/lib/strokedb/volumes/fixed_length_skiplist_volume.rb +109 -0
- data/lib/strokedb/volumes/map_volume.rb +268 -0
- data/meta/MANIFEST +175 -0
- data/script/console +2 -70
- data/spec/integration/remote_store_spec.rb +70 -0
- data/spec/integration/search_spec.rb +76 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/lib/spec_helper.rb +1 -0
- data/spec/lib/strokedb/config_spec.rb +250 -0
- data/spec/lib/strokedb/core_ext/blank_spec.rb +20 -0
- data/spec/lib/strokedb/core_ext/extract_spec.rb +42 -0
- data/spec/lib/strokedb/core_ext/float_spec.rb +62 -0
- data/spec/lib/strokedb/core_ext/infinity_spec.rb +40 -0
- data/spec/lib/strokedb/core_ext/spec_helper.rb +1 -0
- data/spec/lib/strokedb/core_ext/string_spec.rb +25 -0
- data/spec/lib/strokedb/core_ext/symbol_spec.rb +8 -0
- data/spec/lib/strokedb/data_structures/chunked_skiplist_spec.rb +144 -0
- data/spec/lib/strokedb/data_structures/inverted_list_spec.rb +172 -0
- data/spec/lib/strokedb/data_structures/simple_skiplist_spec.rb +200 -0
- data/spec/lib/strokedb/data_structures/skiplist_spec.rb +253 -0
- data/spec/lib/strokedb/data_structures/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/associations_spec.rb +319 -0
- data/spec/lib/strokedb/document/callbacks_spec.rb +134 -0
- data/spec/lib/strokedb/document/coercions_spec.rb +110 -0
- data/spec/lib/strokedb/document/document_spec.rb +1063 -0
- data/spec/lib/strokedb/document/meta_meta_spec.rb +30 -0
- data/spec/lib/strokedb/document/meta_spec.rb +435 -0
- data/spec/lib/strokedb/document/metaslot_spec.rb +43 -0
- data/spec/lib/strokedb/document/slot_spec.rb +130 -0
- data/spec/lib/strokedb/document/spec_helper.rb +1 -0
- data/spec/lib/strokedb/document/validations_spec.rb +1081 -0
- data/spec/lib/strokedb/document/virtualize_spec.rb +80 -0
- data/spec/lib/strokedb/nsurl_spec.rb +73 -0
- data/spec/lib/strokedb/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/chained_storages_spec.rb +116 -0
- data/spec/lib/strokedb/stores/spec_helper.rb +1 -0
- data/spec/lib/strokedb/stores/store_spec.rb +201 -0
- data/spec/lib/strokedb/stores/transaction_spec.rb +107 -0
- data/spec/lib/strokedb/sync/chain_sync_spec.rb +43 -0
- data/spec/lib/strokedb/sync/diff_spec.rb +111 -0
- data/spec/lib/strokedb/sync/lamport_timestamp_spec.rb +174 -0
- data/spec/lib/strokedb/sync/slot_diff_spec.rb +164 -0
- data/spec/lib/strokedb/sync/spec_helper.rb +1 -0
- data/spec/lib/strokedb/sync/store_sync_spec.rb +181 -0
- data/spec/lib/strokedb/sync/stroke_diff/array_spec.rb +97 -0
- data/spec/lib/strokedb/sync/stroke_diff/complex_spec.rb +58 -0
- data/spec/lib/strokedb/sync/stroke_diff/hash_spec.rb +144 -0
- data/spec/lib/strokedb/sync/stroke_diff/scalar_spec.rb +23 -0
- data/spec/lib/strokedb/sync/stroke_diff/spec_helper.rb +25 -0
- data/spec/lib/strokedb/sync/stroke_diff/string_spec.rb +61 -0
- data/spec/lib/strokedb/util/attach_dsl_spec.rb +45 -0
- data/spec/lib/strokedb/util/inflect_spec.rb +14 -0
- data/spec/lib/strokedb/util/lazy_array_spec.rb +157 -0
- data/spec/lib/strokedb/util/lazy_mapping_array_spec.rb +174 -0
- data/spec/lib/strokedb/util/lazy_mapping_hash_spec.rb +92 -0
- data/spec/lib/strokedb/util/spec_helper.rb +1 -0
- data/spec/lib/strokedb/util/uuid_spec.rb +46 -0
- data/spec/lib/strokedb/view_spec.rb +228 -0
- data/spec/lib/strokedb/volumes/archive_volume_spec.rb +105 -0
- data/spec/lib/strokedb/volumes/block_volume_spec.rb +100 -0
- data/spec/lib/strokedb/volumes/distributed_pointer_spec.rb +14 -0
- data/spec/lib/strokedb/volumes/fixed_length_skiplist_volume_spec.rb +177 -0
- data/spec/lib/strokedb/volumes/map_volume_spec.rb +172 -0
- data/spec/lib/strokedb/volumes/spec_helper.rb +1 -0
- data/spec/regression/docref_spec.rb +94 -0
- data/spec/regression/meta_spec.rb +23 -0
- data/spec/regression/spec_helper.rb +1 -0
- data/spec/regression/sync_spec.rb +36 -0
- data/spec/spec.opts +7 -0
- data/spec/spec_helper.rb +37 -0
- data/spec/temp/storages/TIMESTAMP +1 -0
- data/spec/temp/storages/UUID +1 -0
- data/spec/temp/storages/database-sync/TIMESTAMP +1 -0
- data/spec/temp/storages/database-sync/UUID +1 -0
- data/spec/temp/storages/database-sync/config +1 -0
- data/spec/temp/storages/database-sync/file/LAST +1 -0
- data/spec/temp/storages/database-sync/file/bd/f6/bdf675e5-8a7b-494e-97f2-f74a14ccd95d.av +0 -0
- data/spec/temp/storages/database-sync/file/uindex.wal +0 -0
- data/spec/temp/storages/database-sync/inverted_list_file/INVERTED_INDEX +1 -0
- data/spec/temp/storages/inverted_list_storage/INVERTED_INDEX +0 -0
- data/strokedb.gemspec +120 -0
- data/task/benchmark.task +9 -0
- data/task/ditz.task +30 -0
- data/task/echoe.rb +17 -0
- data/task/rcov.task +50 -0
- data/task/rdoc.task +10 -0
- data/task/rspec.task +0 -0
- data/vendor/java_inline.rb +106 -0
- data/vendor/rbmodexcl/mrimodexcl.rb +82 -0
- data/vendor/rbmodexcl/rbmodexcl.rb +5 -0
- data/vendor/rbmodexcl/rbxmodexcl.rb +48 -0
- data/vendor/rbmodexcl/spec/unextend_spec.rb +50 -0
- data/vendor/rbmodexcl/spec/uninclude_spec.rb +26 -0
- metadata +271 -79
- data/CONTRIBUTORS +0 -7
- data/CREDITS +0 -13
- data/bin/sdbc +0 -2
- data/lib/init.rb +0 -57
- data/lib/stores/inverted_list_index/inverted_list_index.rb +0 -49
- data/lib/stores/skiplist_store/chunk.rb +0 -119
- data/lib/stores/skiplist_store/chunk_storage.rb +0 -21
- data/lib/stores/skiplist_store/file_chunk_storage.rb +0 -44
- data/lib/stores/skiplist_store/memory_chunk_storage.rb +0 -37
- data/lib/stores/skiplist_store/skiplist_store.rb +0 -217
- data/lib/stores/store.rb +0 -5
- data/lib/sync/stroke_diff/stroke_diff.rb +0 -9
- data/lib/util/ext/object.rb +0 -8
- data/lib/util/java_util.rb +0 -9
- data/lib/util/trigger_partition.rb +0 -136
- data/strokedb.rb +0 -75
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Document" do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
setup_default_store
|
|
7
|
+
Object.send!(:remove_const,'SomeMeta') if defined?(SomeMeta)
|
|
8
|
+
SomeMeta = Meta.new
|
|
9
|
+
@document = Document.new
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
it "should assign a uuid-named slot for metaslot" do
|
|
13
|
+
@document[Meta] = SomeMeta
|
|
14
|
+
@document.slotnames.should include(Meta.document.uuid)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should assign a uuid-named slot for metaslot" do
|
|
18
|
+
@document[SomeMeta] = "some value"
|
|
19
|
+
@document.slotnames.should include(SomeMeta.document.uuid)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "should be able to read metaslot" do
|
|
23
|
+
@document[SomeMeta] = "some value"
|
|
24
|
+
@document[SomeMeta].should == "some value"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
describe "with metaslot assigned, once saved and reloaded" do
|
|
28
|
+
|
|
29
|
+
before(:each) do
|
|
30
|
+
@document[SomeMeta] = "some value"
|
|
31
|
+
@document.save!
|
|
32
|
+
@document = @document.reload
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should be able to read metaslot" do
|
|
36
|
+
@document[SomeMeta].should == "some value"
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
|
|
43
|
+
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
describe "Slot" do
|
|
4
|
+
|
|
5
|
+
before(:each) do
|
|
6
|
+
@store = setup_default_store
|
|
7
|
+
@document = Document.new
|
|
8
|
+
@slot = Slot.new(@document)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "should store string value" do
|
|
12
|
+
@slot.value = "some value"
|
|
13
|
+
@slot.value.should == "some value"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "should store numeric value" do
|
|
17
|
+
@slot.value = 1
|
|
18
|
+
@slot.value.should == 1
|
|
19
|
+
@slot.value = 1.1
|
|
20
|
+
@slot.value.should == 1.1
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
it "should store Array value" do
|
|
24
|
+
@slot.value = [1,2,3]
|
|
25
|
+
@slot.value.should == [1,2,3]
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should store Hash value" do
|
|
29
|
+
@slot.value = { "1" => "2"}
|
|
30
|
+
@slot.value.should == { "1" => "2"}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
it "should store boolean value" do
|
|
34
|
+
@slot.value = true
|
|
35
|
+
@slot.value.should == true
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
it "should store nil value" do
|
|
39
|
+
@slot.value = nil
|
|
40
|
+
@slot.value.should be_nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should store symbol value and convert it to string" do
|
|
44
|
+
@slot.value = :a
|
|
45
|
+
@slot.value.should == 'a'
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should store Range value" do
|
|
49
|
+
@slot.value = 1..100
|
|
50
|
+
@slot.value.should == (1..100)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
it "should store Regexp value" do
|
|
54
|
+
@slot.value = /.+/
|
|
55
|
+
@slot.value.should == /.+/
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should store Time object" do
|
|
59
|
+
t = Time.now
|
|
60
|
+
@slot.value = t
|
|
61
|
+
@slot.value.should be_close(t, 0.000002)
|
|
62
|
+
@slot.to_raw.should match(XMLSCHEMA_TIME_RE)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "should store VersionedDocument reference if value is a saved Document" do
|
|
66
|
+
some_doc = Document.create!(:something => 1)
|
|
67
|
+
some_doc.save!
|
|
68
|
+
@slot.value = some_doc
|
|
69
|
+
@slot.value.should == some_doc
|
|
70
|
+
@slot.to_raw.should match(/@##{UUID_RE}.#{VERSION_RE}/)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should store VersionedDocument reference if value is a VersionedDocument" do
|
|
74
|
+
some_doc = Document.new(:something => 1)
|
|
75
|
+
some_doc.extend(VersionedDocument)
|
|
76
|
+
some_doc.save!
|
|
77
|
+
@slot.value = some_doc
|
|
78
|
+
@slot.value.should == some_doc
|
|
79
|
+
@slot.to_raw.should match(/@##{UUID_RE}.#{VERSION_RE}/)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should store Document reference if value is a saved Document" do
|
|
83
|
+
some_doc = Document.new
|
|
84
|
+
@slot.value = some_doc
|
|
85
|
+
@slot.value.should == some_doc
|
|
86
|
+
@slot.to_raw.should match(/@##{UUID_RE}/)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
it "should raise ArgumentError for non-supported types" do
|
|
90
|
+
lambda { @slot.value = Object.new }.should raise_error(ArgumentError)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should preserve Ruby object for a complex value" do
|
|
94
|
+
@slot.value = ["some value"]
|
|
95
|
+
@slot.value.object_id.should == @slot.value.object_id
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
describe "Slot that directly references document" do
|
|
101
|
+
|
|
102
|
+
before(:each) do
|
|
103
|
+
setup_default_store
|
|
104
|
+
@another_doc = Document.create! :some_data => "1"
|
|
105
|
+
@doc = Document.create! :another_doc => @another_doc
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should load the same Ruby object each time" do
|
|
109
|
+
doc = @doc.reload
|
|
110
|
+
doc_obj = doc.another_doc
|
|
111
|
+
doc.another_doc.object_id.should == doc_obj.object_id
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
describe "Slot that indirectly references document" do
|
|
117
|
+
|
|
118
|
+
before(:each) do
|
|
119
|
+
setup_default_store
|
|
120
|
+
@another_doc = Document.create! :some_data => "1"
|
|
121
|
+
@doc = Document.create! :another_docs => [@another_doc]
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
it "should load the same Ruby object each time" do
|
|
125
|
+
doc = @doc.reload
|
|
126
|
+
doc_obj = doc.another_docs.first
|
|
127
|
+
doc.another_docs.first.object_id.should == doc_obj.object_id
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
end
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
|
@@ -0,0 +1,1081 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper'
|
|
2
|
+
|
|
3
|
+
def validations_setup
|
|
4
|
+
setup_default_store
|
|
5
|
+
setup_index
|
|
6
|
+
Object.send!(:remove_const, 'Foo') if defined?(Foo)
|
|
7
|
+
Object.send!(:remove_const, 'Bar') if defined?(Bar)
|
|
8
|
+
Object.send!(:remove_const, 'User') if defined?(User)
|
|
9
|
+
Object.send!(:remove_const, 'Email') if defined?(Email)
|
|
10
|
+
Object.send!(:remove_const, 'Item') if defined?(Item)
|
|
11
|
+
Object.send!(:remove_const, 'OneMoreItem') if defined?(OneMoreItem)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def erroneous_stuff
|
|
15
|
+
Meta.new(:name => "ErroneousStuff") do
|
|
16
|
+
on_validation do |doc|
|
|
17
|
+
doc.errors.add(:something, "123")
|
|
18
|
+
doc.errors.add(:other, "456")
|
|
19
|
+
end
|
|
20
|
+
end.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
describe "Document validation" do
|
|
24
|
+
before :each do
|
|
25
|
+
validations_setup
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "should treat an empty document as valid" do
|
|
29
|
+
Foo = Meta.new
|
|
30
|
+
s = Foo.new
|
|
31
|
+
|
|
32
|
+
s.should be_valid
|
|
33
|
+
s.errors.should be_empty
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "should not treat a document with errors as valid" do
|
|
37
|
+
s = erroneous_stuff
|
|
38
|
+
|
|
39
|
+
s.should_not be_valid
|
|
40
|
+
s.errors.messages.sort.should == %w(123 456)
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "should raise InvalidDocumentError on a save! call" do
|
|
44
|
+
lambda { erroneous_stuff.save! }.should raise_error(InvalidDocumentError)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should not raise InvalidDocumentError on a save!(false) call" do
|
|
48
|
+
lambda { erroneous_stuff.save!(false) }.should_not raise_error(InvalidDocumentError)
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
describe "Document with errors" do
|
|
53
|
+
before :each do
|
|
54
|
+
validations_setup
|
|
55
|
+
@erroneous_doc = erroneous_stuff
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should return the number of errors" do
|
|
59
|
+
@erroneous_doc.should_not be_valid
|
|
60
|
+
@erroneous_doc.errors.size.should == 2
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "should yield each attribute and associated message per error added" do
|
|
64
|
+
@erroneous_doc.should_not be_valid
|
|
65
|
+
@erroneous_doc.errors.each { }.should == {"something"=>["123"], "other"=>["456"]}
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
describe "validates_presence_of" do
|
|
71
|
+
before :each do
|
|
72
|
+
validations_setup
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
it "should tell valid if slot is there" do
|
|
76
|
+
Foo = Meta.new { validates_presence_of :name, :on => :save }
|
|
77
|
+
s = Foo.new({:name => "Rick Roll"})
|
|
78
|
+
s.should be_valid
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should tell invalid if slot is absent" do
|
|
82
|
+
Foo = Meta.new { validates_presence_of :name, :on => :save }
|
|
83
|
+
s = Foo.new
|
|
84
|
+
|
|
85
|
+
s.should_not be_valid
|
|
86
|
+
s.errors.messages.should == [ "Foo's name should be present on save" ]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
describe "Validation helpers" do
|
|
91
|
+
before(:each) { validations_setup }
|
|
92
|
+
|
|
93
|
+
it "should respect :on => :create" do
|
|
94
|
+
Foo = Meta.new { validates_presence_of :name, :on => :create }
|
|
95
|
+
s1 = Foo.new
|
|
96
|
+
bang { s1.save! }
|
|
97
|
+
|
|
98
|
+
s2 = Foo.new(:name => "Rick Roll")
|
|
99
|
+
no_bang { s2.save! }
|
|
100
|
+
s2.remove_slot!(:name)
|
|
101
|
+
no_bang { s2.save! }
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
it "should respect :on => :update" do
|
|
105
|
+
Foo = Meta.new { validates_presence_of :name, :on => :update }
|
|
106
|
+
|
|
107
|
+
s = Foo.new
|
|
108
|
+
no_bang { s.save! }
|
|
109
|
+
bang { s.save! }
|
|
110
|
+
s[:name] = "Rick Roll"
|
|
111
|
+
no_bang { s.save! }
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
it "should respect :on => :save" do
|
|
115
|
+
Foo = Meta.new { validates_presence_of :name, :on => :save }
|
|
116
|
+
s1 = Foo.new
|
|
117
|
+
bang { s1.save! }
|
|
118
|
+
|
|
119
|
+
s2 = Foo.new(:name => "Rick Roll")
|
|
120
|
+
no_bang { s2.save! }
|
|
121
|
+
s2.remove_slot!(:name)
|
|
122
|
+
bang { s2.save! }
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should respect :message" do
|
|
126
|
+
Foo = Meta.new do
|
|
127
|
+
validates_presence_of :name, :on => :save, :message => 'On #{on} Meta #{meta} SlotName #{slotname}'
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
s = Foo.new
|
|
131
|
+
s.valid?.should be_false
|
|
132
|
+
s.errors.messages.should == [ "On save Meta Foo SlotName name" ]
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should allow to use document slot for :if and :unless evaluation" do
|
|
136
|
+
Foo = Meta.new do validates_presence_of :name, :on => :save, :if => :slot end
|
|
137
|
+
bang { Foo.create!(:slot => true) }
|
|
138
|
+
no_bang { Foo.create!(:slot => false) }
|
|
139
|
+
|
|
140
|
+
Bar = Meta.new do validates_presence_of :name, :on => :save, :unless => :slot end
|
|
141
|
+
no_bang { Bar.create!(:slot => true) }
|
|
142
|
+
bang { Bar.create!(:slot => false) }
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
it "should raise an ArgumentError when given something not callable for :if and :unless" do
|
|
146
|
+
lambda do
|
|
147
|
+
Meta.new { validates_presence_of :name, :on => :save, :if => 123 }
|
|
148
|
+
end.should raise_error(ArgumentError)
|
|
149
|
+
|
|
150
|
+
lambda do
|
|
151
|
+
Meta.new { validates_presence_of :name, :on => :save, :if => lambda { } }
|
|
152
|
+
end.should raise_error(ArgumentError)
|
|
153
|
+
|
|
154
|
+
lambda do
|
|
155
|
+
Meta.new { validates_presence_of :name, :on => :save, :unless => 123 }
|
|
156
|
+
end.should raise_error(ArgumentError)
|
|
157
|
+
|
|
158
|
+
lambda do
|
|
159
|
+
Meta.new { validates_presence_of :name, :on => :save, :unless => lambda { } }
|
|
160
|
+
end.should raise_error(ArgumentError)
|
|
161
|
+
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def bang
|
|
165
|
+
lambda { yield }.should raise_error(InvalidDocumentError)
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def no_bang
|
|
169
|
+
lambda { yield }.should_not raise_error(InvalidDocumentError)
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
describe "validates_type_of" do
|
|
174
|
+
before :each do
|
|
175
|
+
validations_setup
|
|
176
|
+
|
|
177
|
+
Email = Meta.new
|
|
178
|
+
User = Meta.new { validates_type_of :email, :as => :email }
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
it "should actually check the type" do
|
|
182
|
+
e = Email.create!
|
|
183
|
+
User.new(:email => e).should be_valid
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "should treat other types as invalid" do
|
|
187
|
+
OmgEmail = Meta.new
|
|
188
|
+
e = OmgEmail.create!
|
|
189
|
+
|
|
190
|
+
User.new(:email => e).should_not be_valid
|
|
191
|
+
User.new(:email => "name@server.com").should_not be_valid
|
|
192
|
+
u = User.new(:email => nil)
|
|
193
|
+
u.should_not be_valid
|
|
194
|
+
u.errors.messages.should == [ "User's email should be of type Email" ]
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
it "should treat absent slot as valid with :allow_nil => true" do
|
|
198
|
+
Foo = Meta.new { validates_type_of :email, :as => :email, :allow_nil => true }
|
|
199
|
+
Foo.new.should be_valid
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
describe "validates_format_of" do
|
|
205
|
+
before(:each) do
|
|
206
|
+
validations_setup
|
|
207
|
+
User = Meta.new { validates_format_of :email, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i }
|
|
208
|
+
end
|
|
209
|
+
|
|
210
|
+
it "should be valid when :email value match regexp" do
|
|
211
|
+
User.new(:email => 'cool@strokedb.com').should be_valid
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
it "should be invalid when :email value does not match regexp" do
|
|
215
|
+
User.new(:email => 'cool-strokedb.com').should_not be_valid
|
|
216
|
+
end
|
|
217
|
+
|
|
218
|
+
it "should raise an exception if no regex is provided" do
|
|
219
|
+
lambda { Meta.new { validates_format_of :email, :with => "nothing" } }.should raise_error(ArgumentError)
|
|
220
|
+
end
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
describe "validates_uniqueness_of" do
|
|
224
|
+
before :each do
|
|
225
|
+
validations_setup
|
|
226
|
+
User = Meta.new { validates_uniqueness_of :email }
|
|
227
|
+
end
|
|
228
|
+
|
|
229
|
+
it "should treat unique slot values as valid" do
|
|
230
|
+
u1 = User.create!(:email => "name@server.com")
|
|
231
|
+
u2 = User.new(:email => "othername@otherserver.com")
|
|
232
|
+
u2.should be_valid
|
|
233
|
+
end
|
|
234
|
+
|
|
235
|
+
it "should treat duplicate slot values as invalid" do
|
|
236
|
+
u1 = User.create!(:email => "name@server.com")
|
|
237
|
+
u2 = User.new(:email => "name@server.com")
|
|
238
|
+
u2.should_not be_valid
|
|
239
|
+
u2.errors.messages.should == [ "A document with a email of name@server.com already exists" ]
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "should respect slot name" do
|
|
243
|
+
u1 = User.create!(:email => "name@server.com")
|
|
244
|
+
u2 = User.new(:otherfield => "name@server.com")
|
|
245
|
+
u2.should be_valid
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
describe "document with multiple metas" do
|
|
249
|
+
before :each do
|
|
250
|
+
validations_setup
|
|
251
|
+
Object.send!(:remove_const,'User') if defined?(User)
|
|
252
|
+
Object.send!(:remove_const,'Admin') if defined?(Admin)
|
|
253
|
+
|
|
254
|
+
User = Meta.new { validates_uniqueness_of :email }
|
|
255
|
+
Admin = Meta.new
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
it "should be valid" do
|
|
259
|
+
u = (User+Admin).create!(:email => 'foo@bar.org')
|
|
260
|
+
u.should be_valid
|
|
261
|
+
end
|
|
262
|
+
|
|
263
|
+
it "should be valid" do
|
|
264
|
+
u = User.create!(:email => 'foo@bar.org')
|
|
265
|
+
u.should be_valid
|
|
266
|
+
u.metas << Admin
|
|
267
|
+
u.should be_valid
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
it "should not be valid" do
|
|
271
|
+
u = User.create!(:email => 'foo@bar.org')
|
|
272
|
+
u.should be_valid
|
|
273
|
+
a = Admin.create!(:email => 'foo@bar.org')
|
|
274
|
+
a.should be_valid
|
|
275
|
+
|
|
276
|
+
u.metas << Admin
|
|
277
|
+
a.should be_valid
|
|
278
|
+
u.should_not be_valid
|
|
279
|
+
end
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
describe "should allow to modify an existing document" do
|
|
283
|
+
it "test 1" do
|
|
284
|
+
u = User.create!(:email => "name@server.com", :status => :newbie)
|
|
285
|
+
u.status = :hacker
|
|
286
|
+
u.should be_valid
|
|
287
|
+
u.save!
|
|
288
|
+
u.status = :hax0r
|
|
289
|
+
u.should be_valid
|
|
290
|
+
u.save!
|
|
291
|
+
u.email = "hax0r@hax0r.com"
|
|
292
|
+
u.should be_valid
|
|
293
|
+
u.save!
|
|
294
|
+
u.email = "name@server.com"
|
|
295
|
+
u.status = :newbie_again
|
|
296
|
+
u.should be_valid
|
|
297
|
+
u.save!
|
|
298
|
+
u.email = "hax0r@hax0r.com"
|
|
299
|
+
u.should be_valid
|
|
300
|
+
end
|
|
301
|
+
|
|
302
|
+
it "test 2" do
|
|
303
|
+
Foo = Meta.new do
|
|
304
|
+
validates_uniqueness_of :login
|
|
305
|
+
virtualizes :blah
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
foo = Foo.create!(:login => "vasya")
|
|
309
|
+
|
|
310
|
+
foo.somefield = 777
|
|
311
|
+
foo.should be_valid
|
|
312
|
+
end
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
it "should respect :allow_nil set to false" do
|
|
316
|
+
Foo = Meta.new { validates_uniqueness_of :slot, :allow_nil => false }
|
|
317
|
+
Foo.create!(:slot => nil)
|
|
318
|
+
Foo.new.should_not be_valid
|
|
319
|
+
end
|
|
320
|
+
|
|
321
|
+
it "should respect :allow_nil set to true" do
|
|
322
|
+
Foo = Meta.new { validates_uniqueness_of :slot, :allow_nil => true }
|
|
323
|
+
Foo.create!(:slot => nil)
|
|
324
|
+
Foo.new.should be_valid
|
|
325
|
+
end
|
|
326
|
+
|
|
327
|
+
it "should default :allow_nil to false" do
|
|
328
|
+
Foo = Meta.new { validates_uniqueness_of :slot }
|
|
329
|
+
Foo.create!(:slot => nil)
|
|
330
|
+
Foo.new.should_not be_valid
|
|
331
|
+
end
|
|
332
|
+
|
|
333
|
+
it "should respect :allow_blank set to false" do
|
|
334
|
+
Foo = Meta.new { validates_uniqueness_of :slot, :allow_blank => false }
|
|
335
|
+
Foo.create!(:slot => "")
|
|
336
|
+
Foo.new.should_not be_valid
|
|
337
|
+
end
|
|
338
|
+
|
|
339
|
+
it "should respect :allow_blank set to true" do
|
|
340
|
+
Foo = Meta.new { validates_uniqueness_of :slot, :allow_blank => true }
|
|
341
|
+
Foo.create!(:slot => "")
|
|
342
|
+
Foo.new.should be_valid
|
|
343
|
+
end
|
|
344
|
+
|
|
345
|
+
it "should default :allow_blank to false" do
|
|
346
|
+
Foo = Meta.new { validates_uniqueness_of :slot }
|
|
347
|
+
Foo.create!(:slot => "")
|
|
348
|
+
Foo.new.should_not be_valid
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
it "should respect :case_sensitive"
|
|
352
|
+
end
|
|
353
|
+
|
|
354
|
+
describe "validates_confirmation_of" do
|
|
355
|
+
before :each do
|
|
356
|
+
validations_setup
|
|
357
|
+
User = Meta.new { validates_confirmation_of :password }
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
it "should be valid when confirmed" do
|
|
361
|
+
User.new(:password => "sekret", :password_confirmation => "sekret").should be_valid
|
|
362
|
+
end
|
|
363
|
+
|
|
364
|
+
it "should be valid when confirmation is not set" do
|
|
365
|
+
User.new(:password => "sekret").should be_valid
|
|
366
|
+
end
|
|
367
|
+
|
|
368
|
+
it "should not be valid when not confirmed" do
|
|
369
|
+
u = User.new(:password => "sekret", :password_confirmation => "invalid_guess")
|
|
370
|
+
u.should_not be_valid
|
|
371
|
+
u.errors.messages.should == [ "User's password doesn't match confirmation" ]
|
|
372
|
+
end
|
|
373
|
+
|
|
374
|
+
it "should not serialize confirmation slot" do
|
|
375
|
+
u = User.create!(:password => "sekret", :password_confirmation => "sekret")
|
|
376
|
+
User.find(u.uuid).has_slot?("password_confirmation").should_not be_true
|
|
377
|
+
end
|
|
378
|
+
end
|
|
379
|
+
|
|
380
|
+
describe "validates_acceptance_of" do
|
|
381
|
+
before :each do
|
|
382
|
+
validations_setup
|
|
383
|
+
end
|
|
384
|
+
|
|
385
|
+
it "should treat accepted value as valid" do
|
|
386
|
+
Meta.new(:name => 'some') { validates_acceptance_of :eula, :accept => "yep" }.new(:eula => "yep").should be_valid
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
it "should treat not accepted value as invalid" do
|
|
390
|
+
Meta.new(:name => 'some') { validates_acceptance_of :eula, :accept => "yep" }.new(:eula => "nope").should_not be_valid
|
|
391
|
+
end
|
|
392
|
+
|
|
393
|
+
it "should respect allow_nil" do
|
|
394
|
+
Meta.new(:name => 'some') { validates_acceptance_of :eula, :accept => "yep", :allow_nil => true }.new.should be_valid
|
|
395
|
+
Meta.new(:name => 'some') { validates_acceptance_of :eula, :accept => "yep", :allow_nil => false }.new.should_not be_valid
|
|
396
|
+
end
|
|
397
|
+
|
|
398
|
+
it "should set :allow_nil to true by default" do
|
|
399
|
+
Meta.new(:name => 'some') { validates_acceptance_of :eula, :accept => "yep" }.new.should be_valid
|
|
400
|
+
end
|
|
401
|
+
|
|
402
|
+
it "should set :accept to \"1\" by default" do
|
|
403
|
+
Meta.new(:name => 'some') { validates_acceptance_of :eula }.new(:eula => "1").should be_valid
|
|
404
|
+
end
|
|
405
|
+
|
|
406
|
+
it "should make a slot virtual" do
|
|
407
|
+
Foo = Meta.new{ validates_acceptance_of :eula, :accept => "yep" }
|
|
408
|
+
f = Foo.create!(:eula => "yep")
|
|
409
|
+
Foo.find(f.uuid).has_slot?("eula").should_not be_true
|
|
410
|
+
end
|
|
411
|
+
end
|
|
412
|
+
|
|
413
|
+
describe "validates_length_of" do
|
|
414
|
+
before :each do
|
|
415
|
+
validations_setup
|
|
416
|
+
end
|
|
417
|
+
|
|
418
|
+
describe "options handling" do
|
|
419
|
+
it "should raise ArgumentError when more than one range option is specified" do
|
|
420
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name, :is => 10, :maximum => 20 } }
|
|
421
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name, :is => 10, :within => 1..20 } }
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
it "should raise ArgumentError when no range option is specified" do
|
|
425
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name } }
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
it "should raise ArgumentError when not Range given to :in or :within" do
|
|
429
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name, :in => 10 } }
|
|
430
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name, :within => "somewhere between one and a million" } }
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
it "should raise ArgumentError when something other than nonnegative Integer is given to :is, :minimum, :maximum" do
|
|
434
|
+
%w(is minimum maximum).each do |arg|
|
|
435
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name, arg => "blah" } }
|
|
436
|
+
arg_bang { Meta.new(:name => 'some') { validates_length_of :name, arg => -1 } }
|
|
437
|
+
end
|
|
438
|
+
end
|
|
439
|
+
|
|
440
|
+
def arg_bang
|
|
441
|
+
lambda { yield }.should raise_error(ArgumentError)
|
|
442
|
+
end
|
|
443
|
+
end
|
|
444
|
+
|
|
445
|
+
%w(within in).each do |within|
|
|
446
|
+
describe ":#{within}" do
|
|
447
|
+
before :each do
|
|
448
|
+
Foo = Meta.new { validates_length_of :bar, within => 10..50 }
|
|
449
|
+
end
|
|
450
|
+
|
|
451
|
+
it "should consider valid when slot is within the range" do
|
|
452
|
+
Foo.new(:bar => "*"*30).should be_valid
|
|
453
|
+
Foo.new(:bar => [1]*30).should be_valid
|
|
454
|
+
end
|
|
455
|
+
|
|
456
|
+
it "should consider invalid when slot is too small" do
|
|
457
|
+
f = Foo.new(:bar => "12345")
|
|
458
|
+
f.should_not be_valid
|
|
459
|
+
f.errors.messages.should == [ "bar is too short (minimum is 10 characters)" ]
|
|
460
|
+
Foo.new(:bar => [1]*5).should_not be_valid
|
|
461
|
+
end
|
|
462
|
+
|
|
463
|
+
it "should consider invalid when slot is too big" do
|
|
464
|
+
f = Foo.new(:bar => "!"*100)
|
|
465
|
+
f.should_not be_valid
|
|
466
|
+
f.errors.messages.should == [ "bar is too long (maximum is 50 characters)" ]
|
|
467
|
+
Foo.new(:bar => [1]*100).should_not be_valid
|
|
468
|
+
end
|
|
469
|
+
|
|
470
|
+
it "should respect :too_short" do
|
|
471
|
+
Bar = Meta.new { validates_length_of :foo, within => 1..5, :too_short => "blah %d" }
|
|
472
|
+
b = Bar.new(:foo => "")
|
|
473
|
+
b.should_not be_valid
|
|
474
|
+
b.errors.messages.should == [ "blah 1" ]
|
|
475
|
+
end
|
|
476
|
+
|
|
477
|
+
it "should respect :too_long" do
|
|
478
|
+
Bar = Meta.new { validates_length_of :foo, within => 1..5, :too_long => "blah %d" }
|
|
479
|
+
b = Bar.new(:foo => "123456")
|
|
480
|
+
b.should_not be_valid
|
|
481
|
+
b.errors.messages.should == [ "blah 5" ]
|
|
482
|
+
end
|
|
483
|
+
end
|
|
484
|
+
end
|
|
485
|
+
|
|
486
|
+
describe ":is" do
|
|
487
|
+
before :each do
|
|
488
|
+
Foo = Meta.new { validates_length_of :bar, :is => 4 }
|
|
489
|
+
end
|
|
490
|
+
|
|
491
|
+
it "should consider valid when slot value has the right length" do
|
|
492
|
+
Foo.new(:bar => "1234").should be_valid
|
|
493
|
+
Foo.new(:bar => %w(ein zwei drei Polizei)).should be_valid
|
|
494
|
+
end
|
|
495
|
+
|
|
496
|
+
it "should consider invalid when slot value has invalid length" do
|
|
497
|
+
f = Foo.new(:bar => "12345")
|
|
498
|
+
f.should_not be_valid
|
|
499
|
+
f.errors.messages.should == [ "bar has the wrong length (should be 4 characters)" ]
|
|
500
|
+
|
|
501
|
+
Foo.new(:bar => %w(ein zwei alles)).should_not be_valid
|
|
502
|
+
end
|
|
503
|
+
|
|
504
|
+
it "should respect :message" do
|
|
505
|
+
Bar = Meta.new { validates_length_of :foo, :is => 66, :message => "fkup %d" }
|
|
506
|
+
b = Bar.new(:foo => "123456")
|
|
507
|
+
b.should_not be_valid
|
|
508
|
+
b.errors.messages.should == [ "fkup 66" ]
|
|
509
|
+
end
|
|
510
|
+
end
|
|
511
|
+
|
|
512
|
+
describe ":minimum" do
|
|
513
|
+
before :each do
|
|
514
|
+
Foo = Meta.new { validates_length_of :bar, :minimum => 4 }
|
|
515
|
+
end
|
|
516
|
+
|
|
517
|
+
it "should consider valid when slot value has the right length" do
|
|
518
|
+
Foo.new(:bar => "1234").should be_valid
|
|
519
|
+
Foo.new(:bar => "12345").should be_valid
|
|
520
|
+
Foo.new(:bar => %w(ein zwei drei vier Polizei)).should be_valid
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
it "should consider invalid when slot value has invalid length" do
|
|
524
|
+
f = Foo.new(:bar => "125")
|
|
525
|
+
f.should_not be_valid
|
|
526
|
+
f.errors.messages.should == [ "bar is too short (minimum is 4 characters)" ]
|
|
527
|
+
|
|
528
|
+
Foo.new(:bar => %w(ein zwei alles)).should_not be_valid
|
|
529
|
+
end
|
|
530
|
+
|
|
531
|
+
it "should respect :message" do
|
|
532
|
+
Bar = Meta.new { validates_length_of :foo, :minimum => 66, :message => "fkup %d" }
|
|
533
|
+
b = Bar.new(:foo => "123456")
|
|
534
|
+
b.should_not be_valid
|
|
535
|
+
b.errors.messages.should == [ "fkup 66" ]
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
describe :maximum do
|
|
540
|
+
before :each do
|
|
541
|
+
Foo = Meta.new { validates_length_of :bar, :maximum => 4 }
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
it "should consider valid when slot value has the right length" do
|
|
545
|
+
Foo.new(:bar => "1234").should be_valid
|
|
546
|
+
Foo.new(:bar => "123").should be_valid
|
|
547
|
+
Foo.new(:bar => %w(ein zwei drei)).should be_valid
|
|
548
|
+
end
|
|
549
|
+
|
|
550
|
+
it "should consider invalid when slot value has invalid length" do
|
|
551
|
+
f = Foo.new(:bar => "123456")
|
|
552
|
+
f.should_not be_valid
|
|
553
|
+
f.errors.messages.should == [ "bar is too long (maximum is 4 characters)" ]
|
|
554
|
+
|
|
555
|
+
Foo.new(:bar => %w(ein zwei drei vier Polizei)).should_not be_valid
|
|
556
|
+
end
|
|
557
|
+
|
|
558
|
+
it "should respect :message" do
|
|
559
|
+
Bar = Meta.new { validates_length_of :foo, :maximum => 66, :message => "fkup %d" }
|
|
560
|
+
b = Bar.new(:foo => "6"*67)
|
|
561
|
+
b.should_not be_valid
|
|
562
|
+
b.errors.messages.should == [ "fkup 66" ]
|
|
563
|
+
end
|
|
564
|
+
end
|
|
565
|
+
|
|
566
|
+
it "should respect :allow_nil" do
|
|
567
|
+
Meta.new(:name => 'some') { validates_length_of :bar, :is => 10, :allow_nil => false }.new.should_not be_valid
|
|
568
|
+
Meta.new(:name => 'some') { validates_length_of :bar, :is => 10, :allow_nil => true }.new.should be_valid
|
|
569
|
+
end
|
|
570
|
+
|
|
571
|
+
it "should respect :allow_blank" do
|
|
572
|
+
Foo = Meta.new { validates_length_of :bar, :is => 10, :allow_blank => false }
|
|
573
|
+
Foo.new.should_not be_valid
|
|
574
|
+
Foo.new(:bar => " ").should_not be_valid
|
|
575
|
+
|
|
576
|
+
Bar = Meta.new { validates_length_of :bar, :is => 10, :allow_blank => true }
|
|
577
|
+
Bar.new.should be_valid
|
|
578
|
+
Bar.new(:bar => " ").should be_valid
|
|
579
|
+
end
|
|
580
|
+
end
|
|
581
|
+
|
|
582
|
+
describe "validates_inclusion_of" do
|
|
583
|
+
before :each do
|
|
584
|
+
validations_setup
|
|
585
|
+
Item = Meta.new do
|
|
586
|
+
validates_inclusion_of :gender, :in => %w( m f )
|
|
587
|
+
validates_inclusion_of :age, :in => 0..99
|
|
588
|
+
end
|
|
589
|
+
end
|
|
590
|
+
|
|
591
|
+
it "should raise ArgumentError unless option :in is suplied" do
|
|
592
|
+
lambda do
|
|
593
|
+
Meta.new { validates_inclusion_of :format }
|
|
594
|
+
end.should raise_error(ArgumentError)
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
it "should raise ArgumentError unless param is an enumerable" do
|
|
598
|
+
lambda do
|
|
599
|
+
Meta.new { validates_inclusion_of :format, :in => 42 }
|
|
600
|
+
end.should raise_error(ArgumentError)
|
|
601
|
+
end
|
|
602
|
+
|
|
603
|
+
it "should be valid" do
|
|
604
|
+
i = Item.new(:gender => 'm', :age => 42)
|
|
605
|
+
i.should be_valid
|
|
606
|
+
i.errors.messages.should be_empty
|
|
607
|
+
end
|
|
608
|
+
|
|
609
|
+
it "should not be valid" do
|
|
610
|
+
i = Item.new(:gender => 'x', :age => 'x')
|
|
611
|
+
i.should_not be_valid
|
|
612
|
+
i.errors.messages.should == [ "Value of gender is not included in the list", "Value of age is not included in the list" ]
|
|
613
|
+
end
|
|
614
|
+
|
|
615
|
+
it "should be invalid without gender and age set" do
|
|
616
|
+
Item.new.should_not be_valid
|
|
617
|
+
end
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
describe "validates_exclusion_of" do
|
|
621
|
+
before :each do
|
|
622
|
+
validations_setup
|
|
623
|
+
Item = Meta.new do
|
|
624
|
+
validates_exclusion_of :gender, :in => %w( m f )
|
|
625
|
+
validates_exclusion_of :age, :in => 30..70
|
|
626
|
+
end
|
|
627
|
+
end
|
|
628
|
+
|
|
629
|
+
it "should raise ArgumentError unless option :in is suplied" do
|
|
630
|
+
lambda do
|
|
631
|
+
Meta.new { validates_exclusion_of :gender }
|
|
632
|
+
end.should raise_error(ArgumentError)
|
|
633
|
+
end
|
|
634
|
+
|
|
635
|
+
it "should raise ArgumentError unless param is an enumerable" do
|
|
636
|
+
lambda do
|
|
637
|
+
Meta.new { validates_inclusion_of :gender, :in => 42 }
|
|
638
|
+
end.should raise_error(ArgumentError)
|
|
639
|
+
end
|
|
640
|
+
|
|
641
|
+
it "should be valid" do
|
|
642
|
+
i = Item.new(:gender => 'x', :age => 25)
|
|
643
|
+
i.should be_valid
|
|
644
|
+
end
|
|
645
|
+
|
|
646
|
+
it "should not be valid" do
|
|
647
|
+
i = Item.new(:gender => 'm', :age => 42)
|
|
648
|
+
i.should_not be_valid
|
|
649
|
+
i.errors.messages.should == [ "Value of gender is reserved", "Value of age is reserved" ]
|
|
650
|
+
end
|
|
651
|
+
end
|
|
652
|
+
|
|
653
|
+
describe "validates_associated" do
|
|
654
|
+
before :each do
|
|
655
|
+
validations_setup
|
|
656
|
+
|
|
657
|
+
Foo = Meta.new { has_many :bars; validates_associated :bars }
|
|
658
|
+
Bar = Meta.new { has_many :items; validates_associated :items }
|
|
659
|
+
Item = Meta.new { validates_associated :associate }
|
|
660
|
+
OneMoreItem = Meta.new { validates_associated :associate; validates_presence_of :something }
|
|
661
|
+
User = Meta.new
|
|
662
|
+
end
|
|
663
|
+
|
|
664
|
+
it "should consider not existing association as valid" do
|
|
665
|
+
Foo.new.should be_valid
|
|
666
|
+
end
|
|
667
|
+
|
|
668
|
+
it "should consider valid when associated document is also valid" do
|
|
669
|
+
perfectly_valid = User.new
|
|
670
|
+
Item.new(:associate => perfectly_valid).should be_valid
|
|
671
|
+
end
|
|
672
|
+
|
|
673
|
+
it "should consider invalid when associated document is invalid" do
|
|
674
|
+
invalid = erroneous_stuff
|
|
675
|
+
invalid.should_not be_valid
|
|
676
|
+
item = Item.new(:associate => invalid)
|
|
677
|
+
item.should_not be_valid
|
|
678
|
+
item.errors.messages.should == [ "associate is invalid" ]
|
|
679
|
+
end
|
|
680
|
+
|
|
681
|
+
it "should work with has_many association" do
|
|
682
|
+
f = Foo.new
|
|
683
|
+
f.bars << Bar.new
|
|
684
|
+
f.should be_valid
|
|
685
|
+
f.bars << Bar.new
|
|
686
|
+
f.should be_valid
|
|
687
|
+
|
|
688
|
+
err = erroneous_stuff
|
|
689
|
+
|
|
690
|
+
lambda { f.bars << err }.should raise_error(InvalidDocumentError)
|
|
691
|
+
f.should be_valid
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
it "should work with a document chain" do
|
|
695
|
+
i3 = erroneous_stuff
|
|
696
|
+
i3.should_not be_valid
|
|
697
|
+
|
|
698
|
+
i2 = Item.new
|
|
699
|
+
i2.should be_valid
|
|
700
|
+
i2.associate = i3
|
|
701
|
+
i2.should_not be_valid
|
|
702
|
+
|
|
703
|
+
i1 = Item.new
|
|
704
|
+
i1.should be_valid
|
|
705
|
+
i1.associate = i2
|
|
706
|
+
i1.should_not be_valid
|
|
707
|
+
|
|
708
|
+
i1.associate = i3
|
|
709
|
+
i1.should_not be_valid
|
|
710
|
+
i1.associate = nil
|
|
711
|
+
i1.should be_valid
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
it "should catch direct circular referenced validations" do
|
|
715
|
+
i = Item.new
|
|
716
|
+
i1 = Item.new(:associate => i)
|
|
717
|
+
i.associate = i1
|
|
718
|
+
lambda { i.valid? }.should_not raise_error(SystemStackError)
|
|
719
|
+
i.should be_valid
|
|
720
|
+
oi = OneMoreItem.new
|
|
721
|
+
oi1 = OneMoreItem.new(:associate => oi)
|
|
722
|
+
oi.associate = oi1
|
|
723
|
+
oi.should_not be_valid
|
|
724
|
+
oi1.should_not be_valid
|
|
725
|
+
end
|
|
726
|
+
|
|
727
|
+
it "should catch circular referenced validations through has_many association" do
|
|
728
|
+
b = Bar.new
|
|
729
|
+
b.items << (i = Item.new(:associate => b))
|
|
730
|
+
lambda { b.valid? }.should_not raise_error(SystemStackError)
|
|
731
|
+
lambda { i.valid? }.should_not raise_error(SystemStackError)
|
|
732
|
+
end
|
|
733
|
+
|
|
734
|
+
end
|
|
735
|
+
|
|
736
|
+
describe "validates_numericality_of" do
|
|
737
|
+
before :each do
|
|
738
|
+
validations_setup
|
|
739
|
+
end
|
|
740
|
+
|
|
741
|
+
describe "general behaviour" do
|
|
742
|
+
before :each do
|
|
743
|
+
Item = Meta.new do
|
|
744
|
+
validates_numericality_of :price
|
|
745
|
+
end
|
|
746
|
+
end
|
|
747
|
+
|
|
748
|
+
it "should raise error on String value" do
|
|
749
|
+
i = Item.new(:price => "A")
|
|
750
|
+
i.should_not be_valid
|
|
751
|
+
i.errors.messages.should == [ "price is not a number" ]
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
it "should treat integer as valid" do
|
|
755
|
+
i = Item.new(:price => 1)
|
|
756
|
+
i.should be_valid
|
|
757
|
+
end
|
|
758
|
+
|
|
759
|
+
it "should treat negative integer as valid" do
|
|
760
|
+
i = Item.new(:price => -1)
|
|
761
|
+
i.should be_valid
|
|
762
|
+
end
|
|
763
|
+
|
|
764
|
+
it "should treat float as valid" do
|
|
765
|
+
i = Item.new(:price => 2.5)
|
|
766
|
+
i.should be_valid
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
it "should treat negative float as valid" do
|
|
770
|
+
i = Item.new(:price => -2.5)
|
|
771
|
+
i.should be_valid
|
|
772
|
+
end
|
|
773
|
+
|
|
774
|
+
it "should treat float in exponential notation as valid" do
|
|
775
|
+
i = Item.new(:price => "1.23456E-3")
|
|
776
|
+
i.should be_valid
|
|
777
|
+
end
|
|
778
|
+
end
|
|
779
|
+
|
|
780
|
+
describe "should respect :only_integer" do
|
|
781
|
+
before :each do
|
|
782
|
+
Item = Meta.new do
|
|
783
|
+
validates_numericality_of :price, :only_integer => true
|
|
784
|
+
end
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
it "should treat integer as valid when :only_integer is specified" do
|
|
788
|
+
Item.new(:price => 123).should be_valid
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
it "should treat integer in string as valid when :only_integer is specified" do
|
|
792
|
+
Item.new(:price => "123").should be_valid
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
it "should treat string as invalid when :only_integer is specified" do
|
|
796
|
+
i = Item.new(:price => "ququ")
|
|
797
|
+
i.should_not be_valid
|
|
798
|
+
i.errors.messages.should == [ "price must be integer" ]
|
|
799
|
+
end
|
|
800
|
+
|
|
801
|
+
it "should treat float as invalid when :only_integer is specified" do
|
|
802
|
+
i = Item.new(:price => 1.5)
|
|
803
|
+
i.should_not be_valid
|
|
804
|
+
i.errors.messages.should == [ "price must be integer" ]
|
|
805
|
+
end
|
|
806
|
+
end
|
|
807
|
+
|
|
808
|
+
describe "should respect :greater_than" do
|
|
809
|
+
before :each do
|
|
810
|
+
Item = Meta.new do
|
|
811
|
+
validates_numericality_of :number, :greater_than => 42
|
|
812
|
+
end
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
it "should raise ArgumentError if value is not numeric" do
|
|
816
|
+
lambda do
|
|
817
|
+
Meta.new { validates_numericality_of :number, :greater_than => "chicken" }
|
|
818
|
+
end.should raise_error(ArgumentError)
|
|
819
|
+
end
|
|
820
|
+
|
|
821
|
+
it "should be valid if value > 42" do
|
|
822
|
+
i = Item.new(:number => 44)
|
|
823
|
+
i.should be_valid
|
|
824
|
+
i.errors.messages.should be_empty
|
|
825
|
+
i.number = 44.3
|
|
826
|
+
i.should be_valid
|
|
827
|
+
i.errors.messages.should be_empty
|
|
828
|
+
end
|
|
829
|
+
|
|
830
|
+
it "should not be valid if value < 42" do
|
|
831
|
+
i = Item.new(:number => 41)
|
|
832
|
+
i.should_not be_valid
|
|
833
|
+
i.errors.messages.should == [ "number must be greater than 42" ]
|
|
834
|
+
end
|
|
835
|
+
|
|
836
|
+
it "should not be valid if value == 42" do
|
|
837
|
+
i = Item.new(:number => 42)
|
|
838
|
+
i.should_not be_valid
|
|
839
|
+
i.errors.messages.should == [ "number must be greater than 42" ]
|
|
840
|
+
end
|
|
841
|
+
end
|
|
842
|
+
|
|
843
|
+
describe "should respect :greater_than_or_equal_to" do
|
|
844
|
+
before :each do
|
|
845
|
+
Item = Meta.new do
|
|
846
|
+
validates_numericality_of :number, :greater_than_or_equal_to => 42
|
|
847
|
+
end
|
|
848
|
+
end
|
|
849
|
+
|
|
850
|
+
it "should raise ArgumentError if value is not numeric" do
|
|
851
|
+
lambda do
|
|
852
|
+
Meta.new { validates_numericality_of :number, :greater_than => "chicken" }
|
|
853
|
+
end.should raise_error(ArgumentError)
|
|
854
|
+
end
|
|
855
|
+
|
|
856
|
+
it "should be valid if value > 42" do
|
|
857
|
+
i = Item.new(:number => 44)
|
|
858
|
+
i.should be_valid
|
|
859
|
+
i.number = 44.3
|
|
860
|
+
i.should be_valid
|
|
861
|
+
end
|
|
862
|
+
|
|
863
|
+
it "should be valid if value == 42" do
|
|
864
|
+
i = Item.new(:number => 42)
|
|
865
|
+
i.should be_valid
|
|
866
|
+
end
|
|
867
|
+
|
|
868
|
+
it "should not be valid if value < 42" do
|
|
869
|
+
i = Item.new(:number => 41)
|
|
870
|
+
i.should_not be_valid
|
|
871
|
+
i.errors.messages.should == [ "number must be greater than or equal to 42" ]
|
|
872
|
+
end
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
describe "should respect :equal_to" do
|
|
876
|
+
before :each do
|
|
877
|
+
Item = Meta.new do
|
|
878
|
+
validates_numericality_of :number, :equal_to => 42
|
|
879
|
+
end
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
it "should raise ArgumentError if value is not numeric" do
|
|
883
|
+
lambda do
|
|
884
|
+
Meta.new { validates_numericality_of :number, :greater_than => "chicken" }
|
|
885
|
+
end.should raise_error(ArgumentError)
|
|
886
|
+
end
|
|
887
|
+
|
|
888
|
+
it "should be valid if value == 42" do
|
|
889
|
+
i = Item.new(:number => 42)
|
|
890
|
+
i.should be_valid
|
|
891
|
+
i.errors.messages.should be_empty
|
|
892
|
+
end
|
|
893
|
+
|
|
894
|
+
it "should not be valid if value > 42" do
|
|
895
|
+
i = Item.new(:number => 44)
|
|
896
|
+
i.should_not be_valid
|
|
897
|
+
i.errors.messages.should == [ "number must be equal to 42" ]
|
|
898
|
+
end
|
|
899
|
+
|
|
900
|
+
it "should not be valid if value < 42" do
|
|
901
|
+
i = Item.new(:number => 41)
|
|
902
|
+
i.should_not be_valid
|
|
903
|
+
i.errors.messages.should == [ "number must be equal to 42" ]
|
|
904
|
+
end
|
|
905
|
+
end
|
|
906
|
+
|
|
907
|
+
describe "should respect :less_than" do
|
|
908
|
+
before :each do
|
|
909
|
+
Item = Meta.new do
|
|
910
|
+
validates_numericality_of :number, :less_than => 42
|
|
911
|
+
end
|
|
912
|
+
end
|
|
913
|
+
|
|
914
|
+
it "should raise ArgumentError if value is not numeric" do
|
|
915
|
+
lambda do
|
|
916
|
+
Meta.new { validates_numericality_of :number, :less_than => "chicken" }
|
|
917
|
+
end.should raise_error(ArgumentError)
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
it "should be valid if value < 42" do
|
|
921
|
+
i = Item.new(:number => 41)
|
|
922
|
+
i.should be_valid
|
|
923
|
+
i.errors.messages.should be_empty
|
|
924
|
+
i.number = 41.3
|
|
925
|
+
i.should be_valid
|
|
926
|
+
i.errors.messages.should be_empty
|
|
927
|
+
end
|
|
928
|
+
|
|
929
|
+
it "should not be valid if value > 42" do
|
|
930
|
+
i = Item.new(:number => 43)
|
|
931
|
+
i.should_not be_valid
|
|
932
|
+
i.errors.messages.should == [ "number must be less than 42" ]
|
|
933
|
+
end
|
|
934
|
+
|
|
935
|
+
it "should not be valid if value == 42" do
|
|
936
|
+
i = Item.new(:number => 42)
|
|
937
|
+
i.should_not be_valid
|
|
938
|
+
i.errors.messages.should == [ "number must be less than 42" ]
|
|
939
|
+
end
|
|
940
|
+
end
|
|
941
|
+
|
|
942
|
+
describe "should respect :less_than_or_equal_to" do
|
|
943
|
+
before :each do
|
|
944
|
+
Item = Meta.new do
|
|
945
|
+
validates_numericality_of :number, :less_than_or_equal_to => 42
|
|
946
|
+
end
|
|
947
|
+
end
|
|
948
|
+
|
|
949
|
+
it "should raise ArgumentError if value is not numeric" do
|
|
950
|
+
lambda do
|
|
951
|
+
Meta.new { validates_numericality_of :number, :less_than_or_equal_to => "chicken" }
|
|
952
|
+
end.should raise_error(ArgumentError)
|
|
953
|
+
end
|
|
954
|
+
|
|
955
|
+
it "should be valid if value < 42" do
|
|
956
|
+
i = Item.new(:number => 41)
|
|
957
|
+
i.should be_valid
|
|
958
|
+
i.errors.messages.should be_empty
|
|
959
|
+
i.number = 41.3
|
|
960
|
+
i.should be_valid
|
|
961
|
+
i.errors.messages.should be_empty
|
|
962
|
+
end
|
|
963
|
+
|
|
964
|
+
it "should be valid if value == 42" do
|
|
965
|
+
i = Item.new(:number => 42)
|
|
966
|
+
i.should be_valid
|
|
967
|
+
i.errors.messages.should be_empty
|
|
968
|
+
end
|
|
969
|
+
|
|
970
|
+
it "should not be valid if value > 42" do
|
|
971
|
+
i = Item.new(:number => 43)
|
|
972
|
+
i.should_not be_valid
|
|
973
|
+
i.errors.messages.should == [ "number must be less than or equal to 42" ]
|
|
974
|
+
end
|
|
975
|
+
end
|
|
976
|
+
|
|
977
|
+
describe "should respect :odd" do
|
|
978
|
+
before :each do
|
|
979
|
+
Item = Meta.new do
|
|
980
|
+
validates_numericality_of :oddnumber, :odd => true
|
|
981
|
+
end
|
|
982
|
+
end
|
|
983
|
+
|
|
984
|
+
it "should raise ArgumentError when argument is not true" do
|
|
985
|
+
lambda do
|
|
986
|
+
Meta.new { validates_numericality_of :number, :odd => :really? }
|
|
987
|
+
end.should raise_error(ArgumentError)
|
|
988
|
+
end
|
|
989
|
+
|
|
990
|
+
it "should be valid when value is odd" do
|
|
991
|
+
i = Item.new(:oddnumber => 1)
|
|
992
|
+
i.should be_valid
|
|
993
|
+
i.errors.messages.should be_empty
|
|
994
|
+
end
|
|
995
|
+
|
|
996
|
+
it "should not be valid when value is even" do
|
|
997
|
+
i = Item.new(:oddnumber => 2)
|
|
998
|
+
i.should_not be_valid
|
|
999
|
+
i.errors.messages.should == [ "oddnumber must be odd" ]
|
|
1000
|
+
end
|
|
1001
|
+
end
|
|
1002
|
+
|
|
1003
|
+
describe "should respect :even" do
|
|
1004
|
+
before :each do
|
|
1005
|
+
Item = Meta.new do
|
|
1006
|
+
validates_numericality_of :evennumber, :even => true
|
|
1007
|
+
end
|
|
1008
|
+
end
|
|
1009
|
+
|
|
1010
|
+
it "should raise ArgumentError when argument is not true" do
|
|
1011
|
+
lambda do
|
|
1012
|
+
Meta.new { validates_numericality_of :number, :even => :really? }
|
|
1013
|
+
end.should raise_error(ArgumentError)
|
|
1014
|
+
end
|
|
1015
|
+
|
|
1016
|
+
it "should be valid when value is even" do
|
|
1017
|
+
i = Item.new(:evennumber => 4)
|
|
1018
|
+
i.should be_valid
|
|
1019
|
+
i.errors.messages.should be_empty
|
|
1020
|
+
end
|
|
1021
|
+
|
|
1022
|
+
it "should not be valid when value is odd" do
|
|
1023
|
+
i = Item.new(:evennumber => 1)
|
|
1024
|
+
i.should_not be_valid
|
|
1025
|
+
i.errors.messages.should == [ "evennumber must be even" ]
|
|
1026
|
+
end
|
|
1027
|
+
end
|
|
1028
|
+
|
|
1029
|
+
it "should respect :allow_nil" do
|
|
1030
|
+
Meta.new(:name => 'some') { validates_numericality_of :number, :allow_nil => true }.new.should be_valid
|
|
1031
|
+
end
|
|
1032
|
+
|
|
1033
|
+
describe "should allow for option combinations" do
|
|
1034
|
+
it ":less_than and :greater_than" do
|
|
1035
|
+
Item = Meta.new do
|
|
1036
|
+
validates_numericality_of :number, :less_than => 100, :greater_than => 50
|
|
1037
|
+
end
|
|
1038
|
+
|
|
1039
|
+
Item.new(:number => 60).should be_valid
|
|
1040
|
+
|
|
1041
|
+
i1 = Item.new(:number => 40)
|
|
1042
|
+
i1.should_not be_valid
|
|
1043
|
+
i1.errors.messages.should == [ "number must be greater than 50" ]
|
|
1044
|
+
|
|
1045
|
+
i2 = Item.new(:number => 150)
|
|
1046
|
+
i2.should_not be_valid
|
|
1047
|
+
i2.errors.messages.should == [ "number must be less than 100" ]
|
|
1048
|
+
end
|
|
1049
|
+
|
|
1050
|
+
it ":even and :less_than_or_equal_to" do
|
|
1051
|
+
Item = Meta.new do
|
|
1052
|
+
validates_numericality_of :number, :less_than_or_equal_to => 100, :even => true
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
Item.new(:number => 60).should be_valid
|
|
1056
|
+
|
|
1057
|
+
i1 = Item.new(:number => 111)
|
|
1058
|
+
i1.should_not be_valid
|
|
1059
|
+
i1.errors.messages.sort.should == ["number must be less than or equal to 100", "number must be even"].sort
|
|
1060
|
+
end
|
|
1061
|
+
end
|
|
1062
|
+
end
|
|
1063
|
+
|
|
1064
|
+
describe "Complex validations" do
|
|
1065
|
+
it "should gather errors for all slots"
|
|
1066
|
+
it "should run all validations for the same slot"
|
|
1067
|
+
it "should run all validations from all metas"
|
|
1068
|
+
it "should somehow deal with the case when different metas contain same validations types for the same slot"
|
|
1069
|
+
end
|
|
1070
|
+
|
|
1071
|
+
describe "Meta with validation enabled" do
|
|
1072
|
+
before(:each) do
|
|
1073
|
+
validations_setup
|
|
1074
|
+
User = Meta.new { validates_uniqueness_of :email }
|
|
1075
|
+
end
|
|
1076
|
+
|
|
1077
|
+
it "should be able to find instances of all documents" do
|
|
1078
|
+
doc = User.create! :email => "yrashk@gmail.com"
|
|
1079
|
+
User.find.should == [doc]
|
|
1080
|
+
end
|
|
1081
|
+
end
|