viking-sequel 3.10.0
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/CHANGELOG +3134 -0
- data/COPYING +19 -0
- data/README.rdoc +723 -0
- data/Rakefile +193 -0
- data/bin/sequel +196 -0
- data/doc/advanced_associations.rdoc +644 -0
- data/doc/cheat_sheet.rdoc +218 -0
- data/doc/dataset_basics.rdoc +106 -0
- data/doc/dataset_filtering.rdoc +158 -0
- data/doc/opening_databases.rdoc +296 -0
- data/doc/prepared_statements.rdoc +104 -0
- data/doc/reflection.rdoc +84 -0
- data/doc/release_notes/1.0.txt +38 -0
- data/doc/release_notes/1.1.txt +143 -0
- data/doc/release_notes/1.3.txt +101 -0
- data/doc/release_notes/1.4.0.txt +53 -0
- data/doc/release_notes/1.5.0.txt +155 -0
- data/doc/release_notes/2.0.0.txt +298 -0
- data/doc/release_notes/2.1.0.txt +271 -0
- data/doc/release_notes/2.10.0.txt +328 -0
- data/doc/release_notes/2.11.0.txt +215 -0
- data/doc/release_notes/2.12.0.txt +534 -0
- data/doc/release_notes/2.2.0.txt +253 -0
- data/doc/release_notes/2.3.0.txt +88 -0
- data/doc/release_notes/2.4.0.txt +106 -0
- data/doc/release_notes/2.5.0.txt +137 -0
- data/doc/release_notes/2.6.0.txt +157 -0
- data/doc/release_notes/2.7.0.txt +166 -0
- data/doc/release_notes/2.8.0.txt +171 -0
- data/doc/release_notes/2.9.0.txt +97 -0
- data/doc/release_notes/3.0.0.txt +221 -0
- data/doc/release_notes/3.1.0.txt +406 -0
- data/doc/release_notes/3.10.0.txt +286 -0
- data/doc/release_notes/3.2.0.txt +268 -0
- data/doc/release_notes/3.3.0.txt +192 -0
- data/doc/release_notes/3.4.0.txt +325 -0
- data/doc/release_notes/3.5.0.txt +510 -0
- data/doc/release_notes/3.6.0.txt +366 -0
- data/doc/release_notes/3.7.0.txt +179 -0
- data/doc/release_notes/3.8.0.txt +151 -0
- data/doc/release_notes/3.9.0.txt +233 -0
- data/doc/schema.rdoc +36 -0
- data/doc/sharding.rdoc +113 -0
- data/doc/virtual_rows.rdoc +205 -0
- data/lib/sequel.rb +1 -0
- data/lib/sequel/adapters/ado.rb +90 -0
- data/lib/sequel/adapters/ado/mssql.rb +30 -0
- data/lib/sequel/adapters/amalgalite.rb +176 -0
- data/lib/sequel/adapters/db2.rb +139 -0
- data/lib/sequel/adapters/dbi.rb +113 -0
- data/lib/sequel/adapters/do.rb +188 -0
- data/lib/sequel/adapters/do/mysql.rb +49 -0
- data/lib/sequel/adapters/do/postgres.rb +91 -0
- data/lib/sequel/adapters/do/sqlite.rb +40 -0
- data/lib/sequel/adapters/firebird.rb +283 -0
- data/lib/sequel/adapters/informix.rb +77 -0
- data/lib/sequel/adapters/jdbc.rb +587 -0
- data/lib/sequel/adapters/jdbc/as400.rb +58 -0
- data/lib/sequel/adapters/jdbc/h2.rb +133 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
- data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
- data/lib/sequel/adapters/mysql.rb +421 -0
- data/lib/sequel/adapters/odbc.rb +143 -0
- data/lib/sequel/adapters/odbc/mssql.rb +42 -0
- data/lib/sequel/adapters/openbase.rb +64 -0
- data/lib/sequel/adapters/oracle.rb +131 -0
- data/lib/sequel/adapters/postgres.rb +504 -0
- data/lib/sequel/adapters/shared/mssql.rb +490 -0
- data/lib/sequel/adapters/shared/mysql.rb +498 -0
- data/lib/sequel/adapters/shared/oracle.rb +195 -0
- data/lib/sequel/adapters/shared/postgres.rb +830 -0
- data/lib/sequel/adapters/shared/progress.rb +44 -0
- data/lib/sequel/adapters/shared/sqlite.rb +389 -0
- data/lib/sequel/adapters/sqlite.rb +224 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
- data/lib/sequel/connection_pool.rb +99 -0
- data/lib/sequel/connection_pool/sharded_single.rb +84 -0
- data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
- data/lib/sequel/connection_pool/single.rb +29 -0
- data/lib/sequel/connection_pool/threaded.rb +150 -0
- data/lib/sequel/core.rb +293 -0
- data/lib/sequel/core_sql.rb +241 -0
- data/lib/sequel/database.rb +1079 -0
- data/lib/sequel/database/schema_generator.rb +327 -0
- data/lib/sequel/database/schema_methods.rb +203 -0
- data/lib/sequel/database/schema_sql.rb +320 -0
- data/lib/sequel/dataset.rb +32 -0
- data/lib/sequel/dataset/actions.rb +441 -0
- data/lib/sequel/dataset/features.rb +86 -0
- data/lib/sequel/dataset/graph.rb +254 -0
- data/lib/sequel/dataset/misc.rb +119 -0
- data/lib/sequel/dataset/mutation.rb +64 -0
- data/lib/sequel/dataset/prepared_statements.rb +227 -0
- data/lib/sequel/dataset/query.rb +709 -0
- data/lib/sequel/dataset/sql.rb +996 -0
- data/lib/sequel/exceptions.rb +51 -0
- data/lib/sequel/extensions/blank.rb +43 -0
- data/lib/sequel/extensions/inflector.rb +242 -0
- data/lib/sequel/extensions/looser_typecasting.rb +21 -0
- data/lib/sequel/extensions/migration.rb +239 -0
- data/lib/sequel/extensions/named_timezones.rb +61 -0
- data/lib/sequel/extensions/pagination.rb +100 -0
- data/lib/sequel/extensions/pretty_table.rb +82 -0
- data/lib/sequel/extensions/query.rb +52 -0
- data/lib/sequel/extensions/schema_dumper.rb +271 -0
- data/lib/sequel/extensions/sql_expr.rb +122 -0
- data/lib/sequel/extensions/string_date_time.rb +46 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
- data/lib/sequel/metaprogramming.rb +9 -0
- data/lib/sequel/model.rb +120 -0
- data/lib/sequel/model/associations.rb +1514 -0
- data/lib/sequel/model/base.rb +1069 -0
- data/lib/sequel/model/default_inflections.rb +45 -0
- data/lib/sequel/model/errors.rb +39 -0
- data/lib/sequel/model/exceptions.rb +21 -0
- data/lib/sequel/model/inflections.rb +162 -0
- data/lib/sequel/model/plugins.rb +70 -0
- data/lib/sequel/plugins/active_model.rb +59 -0
- data/lib/sequel/plugins/association_dependencies.rb +103 -0
- data/lib/sequel/plugins/association_proxies.rb +41 -0
- data/lib/sequel/plugins/boolean_readers.rb +53 -0
- data/lib/sequel/plugins/caching.rb +141 -0
- data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
- data/lib/sequel/plugins/composition.rb +138 -0
- data/lib/sequel/plugins/force_encoding.rb +72 -0
- data/lib/sequel/plugins/hook_class_methods.rb +126 -0
- data/lib/sequel/plugins/identity_map.rb +116 -0
- data/lib/sequel/plugins/instance_filters.rb +98 -0
- data/lib/sequel/plugins/instance_hooks.rb +57 -0
- data/lib/sequel/plugins/lazy_attributes.rb +77 -0
- data/lib/sequel/plugins/many_through_many.rb +208 -0
- data/lib/sequel/plugins/nested_attributes.rb +206 -0
- data/lib/sequel/plugins/optimistic_locking.rb +81 -0
- data/lib/sequel/plugins/rcte_tree.rb +281 -0
- data/lib/sequel/plugins/schema.rb +66 -0
- data/lib/sequel/plugins/serialization.rb +166 -0
- data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
- data/lib/sequel/plugins/subclasses.rb +45 -0
- data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
- data/lib/sequel/plugins/timestamps.rb +87 -0
- data/lib/sequel/plugins/touch.rb +118 -0
- data/lib/sequel/plugins/typecast_on_load.rb +72 -0
- data/lib/sequel/plugins/validation_class_methods.rb +405 -0
- data/lib/sequel/plugins/validation_helpers.rb +223 -0
- data/lib/sequel/sql.rb +1020 -0
- data/lib/sequel/timezones.rb +161 -0
- data/lib/sequel/version.rb +12 -0
- data/lib/sequel_core.rb +1 -0
- data/lib/sequel_model.rb +1 -0
- data/spec/adapters/firebird_spec.rb +407 -0
- data/spec/adapters/informix_spec.rb +97 -0
- data/spec/adapters/mssql_spec.rb +403 -0
- data/spec/adapters/mysql_spec.rb +1019 -0
- data/spec/adapters/oracle_spec.rb +286 -0
- data/spec/adapters/postgres_spec.rb +969 -0
- data/spec/adapters/spec_helper.rb +51 -0
- data/spec/adapters/sqlite_spec.rb +432 -0
- data/spec/core/connection_pool_spec.rb +808 -0
- data/spec/core/core_sql_spec.rb +417 -0
- data/spec/core/database_spec.rb +1662 -0
- data/spec/core/dataset_spec.rb +3827 -0
- data/spec/core/expression_filters_spec.rb +595 -0
- data/spec/core/object_graph_spec.rb +296 -0
- data/spec/core/schema_generator_spec.rb +159 -0
- data/spec/core/schema_spec.rb +830 -0
- data/spec/core/spec_helper.rb +56 -0
- data/spec/core/version_spec.rb +7 -0
- data/spec/extensions/active_model_spec.rb +76 -0
- data/spec/extensions/association_dependencies_spec.rb +127 -0
- data/spec/extensions/association_proxies_spec.rb +50 -0
- data/spec/extensions/blank_spec.rb +67 -0
- data/spec/extensions/boolean_readers_spec.rb +92 -0
- data/spec/extensions/caching_spec.rb +250 -0
- data/spec/extensions/class_table_inheritance_spec.rb +252 -0
- data/spec/extensions/composition_spec.rb +194 -0
- data/spec/extensions/force_encoding_spec.rb +117 -0
- data/spec/extensions/hook_class_methods_spec.rb +470 -0
- data/spec/extensions/identity_map_spec.rb +202 -0
- data/spec/extensions/inflector_spec.rb +181 -0
- data/spec/extensions/instance_filters_spec.rb +55 -0
- data/spec/extensions/instance_hooks_spec.rb +133 -0
- data/spec/extensions/lazy_attributes_spec.rb +153 -0
- data/spec/extensions/looser_typecasting_spec.rb +39 -0
- data/spec/extensions/many_through_many_spec.rb +884 -0
- data/spec/extensions/migration_spec.rb +332 -0
- data/spec/extensions/named_timezones_spec.rb +72 -0
- data/spec/extensions/nested_attributes_spec.rb +396 -0
- data/spec/extensions/optimistic_locking_spec.rb +100 -0
- data/spec/extensions/pagination_spec.rb +99 -0
- data/spec/extensions/pretty_table_spec.rb +91 -0
- data/spec/extensions/query_spec.rb +85 -0
- data/spec/extensions/rcte_tree_spec.rb +205 -0
- data/spec/extensions/schema_dumper_spec.rb +357 -0
- data/spec/extensions/schema_spec.rb +127 -0
- data/spec/extensions/serialization_spec.rb +209 -0
- data/spec/extensions/single_table_inheritance_spec.rb +96 -0
- data/spec/extensions/spec_helper.rb +91 -0
- data/spec/extensions/sql_expr_spec.rb +89 -0
- data/spec/extensions/string_date_time_spec.rb +93 -0
- data/spec/extensions/subclasses_spec.rb +52 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
- data/spec/extensions/thread_local_timezones_spec.rb +45 -0
- data/spec/extensions/timestamps_spec.rb +150 -0
- data/spec/extensions/touch_spec.rb +155 -0
- data/spec/extensions/typecast_on_load_spec.rb +69 -0
- data/spec/extensions/validation_class_methods_spec.rb +984 -0
- data/spec/extensions/validation_helpers_spec.rb +438 -0
- data/spec/integration/associations_test.rb +281 -0
- data/spec/integration/database_test.rb +26 -0
- data/spec/integration/dataset_test.rb +963 -0
- data/spec/integration/eager_loader_test.rb +734 -0
- data/spec/integration/model_test.rb +130 -0
- data/spec/integration/plugin_test.rb +814 -0
- data/spec/integration/prepared_statement_test.rb +213 -0
- data/spec/integration/schema_test.rb +361 -0
- data/spec/integration/spec_helper.rb +73 -0
- data/spec/integration/timezone_test.rb +55 -0
- data/spec/integration/transaction_test.rb +122 -0
- data/spec/integration/type_test.rb +96 -0
- data/spec/model/association_reflection_spec.rb +175 -0
- data/spec/model/associations_spec.rb +2633 -0
- data/spec/model/base_spec.rb +418 -0
- data/spec/model/dataset_methods_spec.rb +78 -0
- data/spec/model/eager_loading_spec.rb +1391 -0
- data/spec/model/hooks_spec.rb +240 -0
- data/spec/model/inflector_spec.rb +26 -0
- data/spec/model/model_spec.rb +593 -0
- data/spec/model/plugins_spec.rb +236 -0
- data/spec/model/record_spec.rb +1500 -0
- data/spec/model/spec_helper.rb +97 -0
- data/spec/model/validations_spec.rb +153 -0
- data/spec/rcov.opts +6 -0
- data/spec/spec_config.rb.example +10 -0
- metadata +346 -0
@@ -0,0 +1,202 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "Sequel::Plugins::IdentityMap" do
|
4
|
+
before do
|
5
|
+
class ::IdentityMapModel < Sequel::Model
|
6
|
+
plugin :identity_map
|
7
|
+
attr_accessor :foo
|
8
|
+
columns :id
|
9
|
+
ds = dataset
|
10
|
+
def ds.fetch_rows(sql)
|
11
|
+
c = @opts[:where].args.first
|
12
|
+
c = c.column if c.is_a?(Sequel::SQL::QualifiedIdentifier)
|
13
|
+
h = {c=>@opts[:where].args.last}
|
14
|
+
execute(sql)
|
15
|
+
yield h
|
16
|
+
end
|
17
|
+
end
|
18
|
+
class ::IdentityMapAlbum < ::IdentityMapModel
|
19
|
+
columns :id, :artist_id
|
20
|
+
end
|
21
|
+
class ::IdentityMapArtist < ::IdentityMapModel
|
22
|
+
end
|
23
|
+
@c = ::IdentityMapModel
|
24
|
+
@c1 = ::IdentityMapAlbum
|
25
|
+
@c2 = ::IdentityMapArtist
|
26
|
+
MODEL_DB.reset
|
27
|
+
end
|
28
|
+
after do
|
29
|
+
Object.send(:remove_const, :IdentityMapAlbum)
|
30
|
+
Object.send(:remove_const, :IdentityMapArtist)
|
31
|
+
Object.send(:remove_const, :IdentityMapModel)
|
32
|
+
end
|
33
|
+
|
34
|
+
it "#identity_map should return a hash if an identity map is currently being used" do
|
35
|
+
@c.with_identity_map{@c.identity_map.should == {}}
|
36
|
+
end
|
37
|
+
|
38
|
+
it "#identity_map should return nil if an identity map is not currently being used" do
|
39
|
+
@c.identity_map.should == nil
|
40
|
+
end
|
41
|
+
|
42
|
+
it "#identity_map_key should be the same for the same class and pk" do
|
43
|
+
@c.identity_map_key(1).should == @c.identity_map_key(1)
|
44
|
+
end
|
45
|
+
|
46
|
+
it "#identity_map_key should be different for a different class" do
|
47
|
+
@c1.identity_map_key(1).should_not == @c2.identity_map_key(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
it "#identity_map_key should be different for different anonymous classes" do
|
51
|
+
Class.new(@c).identity_map_key(1).should_not == Class.new(@c).identity_map_key(1)
|
52
|
+
end
|
53
|
+
|
54
|
+
it "#identity_map_key should be different for a different pk" do
|
55
|
+
@c.identity_map_key(1).should_not == @c.identity_map_key(2)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "#identity_map_key should be different if the pk is nil" do
|
59
|
+
@c.identity_map_key(nil).should_not == @c.identity_map_key(nil)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "#load should return an object if there is no current identity map" do
|
63
|
+
o = @c.load(:id=>1)
|
64
|
+
o.should be_a_kind_of(@c)
|
65
|
+
o.values.should == {:id=>1}
|
66
|
+
end
|
67
|
+
|
68
|
+
it "#load should return an object if there is a current identity map" do
|
69
|
+
@c.with_identity_map do
|
70
|
+
o = @c.load(:id=>1)
|
71
|
+
o.should be_a_kind_of(@c)
|
72
|
+
o.values.should == {:id=>1}
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
it "#load should should store the object in the current identity map if it isn't already there" do
|
77
|
+
@c.with_identity_map do
|
78
|
+
@c.identity_map[@c.identity_map_key(1)].should == nil
|
79
|
+
o = @c.load(:id=>1)
|
80
|
+
@c.identity_map[@c.identity_map_key(1)].should == o
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
it "#load should update the record in the current identity map if new fields if it is already there" do
|
85
|
+
@c.with_identity_map do
|
86
|
+
o = @c.load(:id=>1, :a=>2)
|
87
|
+
o.values.should == {:id=>1, :a=>2}
|
88
|
+
o = @c.load(:id=>1, :b=>3)
|
89
|
+
o.values.should == {:id=>1, :a=>2, :b=>3}
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "#load should not update existing fields in the record if the record is in the current identity map" do
|
94
|
+
@c.with_identity_map do
|
95
|
+
o = @c.load(:id=>1, :a=>2)
|
96
|
+
o.values.should == {:id=>1, :a=>2}
|
97
|
+
o = @c.load(:id=>1, :a=>4)
|
98
|
+
o.values.should == {:id=>1, :a=>2}
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
it "should use the identity map as a lookup cache in Model.[] to save on database queries" do
|
103
|
+
@c.with_identity_map do
|
104
|
+
MODEL_DB.sqls.length.should == 0
|
105
|
+
o = @c[1]
|
106
|
+
MODEL_DB.sqls.length.should == 1
|
107
|
+
o.foo = 1
|
108
|
+
@c[1].foo.should == o.foo
|
109
|
+
MODEL_DB.sqls.length.should == 1
|
110
|
+
@c[2].foo.should_not == o.foo
|
111
|
+
MODEL_DB.sqls.length.should == 2
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
it "should remove instances from the identity map if they are deleted or destroyed" do
|
116
|
+
@c.with_identity_map do
|
117
|
+
MODEL_DB.sqls.length.should == 0
|
118
|
+
o = @c[1]
|
119
|
+
MODEL_DB.sqls.length.should == 1
|
120
|
+
o.foo = 1
|
121
|
+
@c[1].should == o
|
122
|
+
MODEL_DB.sqls.length.should == 1
|
123
|
+
o.destroy
|
124
|
+
MODEL_DB.sqls.length.should == 2
|
125
|
+
@c[1].foo.should_not == o.foo
|
126
|
+
MODEL_DB.sqls.length.should == 3
|
127
|
+
|
128
|
+
MODEL_DB.reset
|
129
|
+
o = @c[2]
|
130
|
+
MODEL_DB.sqls.length.should == 1
|
131
|
+
o.foo = 1
|
132
|
+
@c[2].should == o
|
133
|
+
MODEL_DB.sqls.length.should == 1
|
134
|
+
o.delete
|
135
|
+
MODEL_DB.sqls.length.should == 2
|
136
|
+
@c[2].foo.should_not == o.foo
|
137
|
+
MODEL_DB.sqls.length.should == 3
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
it "should use the identity map as a lookup cache when retrieving many_to_one associated records" do
|
142
|
+
@c1.many_to_one :artist, :class=>@c2
|
143
|
+
@c.with_identity_map do
|
144
|
+
MODEL_DB.sqls.length.should == 0
|
145
|
+
o = @c1.load(:id=>1, :artist_id=>2)
|
146
|
+
a = o.artist
|
147
|
+
a.should be_a_kind_of(@c2)
|
148
|
+
MODEL_DB.sqls.length.should == 1
|
149
|
+
o = @c1.load(:id=>2, :artist_id=>2)
|
150
|
+
o.artist.should == a
|
151
|
+
MODEL_DB.sqls.length.should == 1
|
152
|
+
o = @c1.load(:id=>3, :artist_id=>3)
|
153
|
+
o.artist.should_not == a
|
154
|
+
MODEL_DB.sqls.length.should == 2
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
it "should not use the identity map as a lookup cache for a one_to_one association" do
|
159
|
+
c = @c2
|
160
|
+
@c2.one_to_one :artist, :class=>@c1, :key=>:artist_id
|
161
|
+
@c.with_identity_map do
|
162
|
+
MODEL_DB.sqls.length.should == 0
|
163
|
+
o = @c2.load(:id=>2)
|
164
|
+
a = o.artist
|
165
|
+
a.should be_a_kind_of(@c1)
|
166
|
+
MODEL_DB.sqls.length.should == 1
|
167
|
+
o.reload
|
168
|
+
MODEL_DB.sqls.length.should == 2
|
169
|
+
o.artist.should == a
|
170
|
+
MODEL_DB.sqls.length.should == 3
|
171
|
+
end
|
172
|
+
end
|
173
|
+
|
174
|
+
it "should not use the identity map as a lookup cache if the assocation has a nil :key option" do
|
175
|
+
c = @c2
|
176
|
+
@c1.many_to_one :artist, :class=>@c2, :key=>nil, :dataset=>proc{c.filter(:artist_id=>artist_id)}
|
177
|
+
@c.with_identity_map do
|
178
|
+
MODEL_DB.sqls.length.should == 0
|
179
|
+
o = @c1.load(:id=>1, :artist_id=>2)
|
180
|
+
a = o.artist
|
181
|
+
a.should be_a_kind_of(@c2)
|
182
|
+
MODEL_DB.sqls.length.should == 1
|
183
|
+
o = @c1.load(:id=>2, :artist_id=>2)
|
184
|
+
o.artist.should == a
|
185
|
+
MODEL_DB.sqls.length.should == 2
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
it "should not use the identity map as a lookup cache if the assocation's :primary_key option doesn't match the primary key of the associated class" do
|
190
|
+
@c1.many_to_one :artist, :class=>@c2, :primary_key=>:artist_id
|
191
|
+
@c.with_identity_map do
|
192
|
+
MODEL_DB.sqls.length.should == 0
|
193
|
+
o = @c1.load(:id=>1, :artist_id=>2)
|
194
|
+
a = o.artist
|
195
|
+
a.should be_a_kind_of(@c2)
|
196
|
+
MODEL_DB.sqls.length.should == 1
|
197
|
+
o = @c1.load(:id=>2, :artist_id=>2)
|
198
|
+
o.artist.should == a
|
199
|
+
MODEL_DB.sqls.length.should == 2
|
200
|
+
end
|
201
|
+
end
|
202
|
+
end
|
@@ -0,0 +1,181 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe String do
|
4
|
+
it "#camelize and #camelcase should transform the word to CamelCase" do
|
5
|
+
"egg_and_hams".camelize.should == "EggAndHams"
|
6
|
+
"egg_and_hams".camelize(false).should == "eggAndHams"
|
7
|
+
"post".camelize.should == "Post"
|
8
|
+
"post".camelcase.should == "Post"
|
9
|
+
end
|
10
|
+
|
11
|
+
it "#constantize should eval the string to get a constant" do
|
12
|
+
"String".constantize.should == String
|
13
|
+
"String::Inflections".constantize.should == String::Inflections
|
14
|
+
proc{"BKSDDF".constantize}.should raise_error
|
15
|
+
proc{"++A++".constantize}.should raise_error
|
16
|
+
end
|
17
|
+
|
18
|
+
it "#dasherize should transform underscores to dashes" do
|
19
|
+
"egg_and_hams".dasherize.should == "egg-and-hams"
|
20
|
+
"post".dasherize.should == "post"
|
21
|
+
end
|
22
|
+
|
23
|
+
it "#demodulize should remove any preceding modules" do
|
24
|
+
"String::Inflections::Blah".demodulize.should == "Blah"
|
25
|
+
"String::Inflections".demodulize.should == "Inflections"
|
26
|
+
"String".demodulize.should == "String"
|
27
|
+
end
|
28
|
+
|
29
|
+
it "#humanize should remove _i, transform underscore to spaces, and capitalize" do
|
30
|
+
"egg_and_hams".humanize.should == "Egg and hams"
|
31
|
+
"post".humanize.should == "Post"
|
32
|
+
"post_id".humanize.should == "Post"
|
33
|
+
end
|
34
|
+
|
35
|
+
it "#titleize and #titlecase should underscore, humanize, and capitalize all words" do
|
36
|
+
"egg-and: hams".titleize.should == "Egg And: Hams"
|
37
|
+
"post".titleize.should == "Post"
|
38
|
+
"post".titlecase.should == "Post"
|
39
|
+
end
|
40
|
+
|
41
|
+
it "#underscore should add underscores between CamelCased words, change :: to / and - to _, and downcase" do
|
42
|
+
"EggAndHams".underscore.should == "egg_and_hams"
|
43
|
+
"EGGAndHams".underscore.should == "egg_and_hams"
|
44
|
+
"Egg::And::Hams".underscore.should == "egg/and/hams"
|
45
|
+
"post".underscore.should == "post"
|
46
|
+
"post-id".underscore.should == "post_id"
|
47
|
+
end
|
48
|
+
|
49
|
+
it "#pluralize should transform words from singular to plural" do
|
50
|
+
"post".pluralize.should == "posts"
|
51
|
+
"octopus".pluralize.should =="octopuses"
|
52
|
+
"the blue mailman".pluralize.should == "the blue mailmen"
|
53
|
+
"CamelOctopus".pluralize.should == "CamelOctopuses"
|
54
|
+
end
|
55
|
+
|
56
|
+
it "#singularize should transform words from plural to singular" do
|
57
|
+
"posts".singularize.should == "post"
|
58
|
+
"octopuses".singularize.should == "octopus"
|
59
|
+
"the blue mailmen".singularize.should == "the blue mailman"
|
60
|
+
"CamelOctopuses".singularize.should == "CamelOctopus"
|
61
|
+
end
|
62
|
+
|
63
|
+
it "#tableize should transform class names to table names" do
|
64
|
+
"RawScaledScorer".tableize.should == "raw_scaled_scorers"
|
65
|
+
"egg_and_ham".tableize.should == "egg_and_hams"
|
66
|
+
"fancyCategory".tableize.should == "fancy_categories"
|
67
|
+
end
|
68
|
+
|
69
|
+
it "#classify should tranform table names to class names" do
|
70
|
+
"egg_and_hams".classify.should == "EggAndHam"
|
71
|
+
"post".classify.should == "Post"
|
72
|
+
end
|
73
|
+
|
74
|
+
it "#foreign_key should create a foreign key name from a class name" do
|
75
|
+
"Message".foreign_key.should == "message_id"
|
76
|
+
"Message".foreign_key(false).should == "messageid"
|
77
|
+
"Admin::Post".foreign_key.should == "post_id"
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
describe String::Inflections do
|
82
|
+
before do
|
83
|
+
@plurals, @singulars, @uncountables = String.inflections.plurals.dup, String.inflections.singulars.dup, String.inflections.uncountables.dup
|
84
|
+
end
|
85
|
+
after do
|
86
|
+
String.inflections.plurals.replace(@plurals)
|
87
|
+
String.inflections.singulars.replace(@singulars)
|
88
|
+
String.inflections.uncountables.replace(@uncountables)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "should be possible to clear the list of singulars, plurals, and uncountables" do
|
92
|
+
String.inflections.clear(:plurals)
|
93
|
+
String.inflections.plurals.should == []
|
94
|
+
String.inflections.plural('blah', 'blahs')
|
95
|
+
String.inflections.clear
|
96
|
+
String.inflections.plurals.should == []
|
97
|
+
String.inflections.singulars.should == []
|
98
|
+
String.inflections.uncountables.should == []
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should be able to specify new inflection rules" do
|
102
|
+
String.inflections do |i|
|
103
|
+
i.plural(/xx$/i, 'xxx')
|
104
|
+
i.singular(/ttt$/i, 'tt')
|
105
|
+
i.irregular('yy', 'yyy')
|
106
|
+
i.uncountable(%w'zz')
|
107
|
+
end
|
108
|
+
'roxx'.pluralize.should == 'roxxx'
|
109
|
+
'rottt'.singularize.should == 'rott'
|
110
|
+
'yy'.pluralize.should == 'yyy'
|
111
|
+
'yyy'.singularize.should == 'yy'
|
112
|
+
'zz'.pluralize.should == 'zz'
|
113
|
+
'zz'.singularize.should == 'zz'
|
114
|
+
end
|
115
|
+
|
116
|
+
it "should be yielded and returned by String.inflections" do
|
117
|
+
String.inflections{|i| i.should == String::Inflections}.should == String::Inflections
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe 'Default inflections' do
|
122
|
+
it "should support the default inflection rules" do
|
123
|
+
{
|
124
|
+
:test=>:tests,
|
125
|
+
:ax=>:axes,
|
126
|
+
:testis=>:testes,
|
127
|
+
:octopus=>:octopuses,
|
128
|
+
:virus=>:viruses,
|
129
|
+
:alias=>:aliases,
|
130
|
+
:status=>:statuses,
|
131
|
+
:bus=>:buses,
|
132
|
+
:buffalo=>:buffaloes,
|
133
|
+
:tomato=>:tomatoes,
|
134
|
+
:datum=>:data,
|
135
|
+
:bacterium=>:bacteria,
|
136
|
+
:analysis=>:analyses,
|
137
|
+
:basis=>:bases,
|
138
|
+
:diagnosis=>:diagnoses,
|
139
|
+
:parenthesis=>:parentheses,
|
140
|
+
:prognosis=>:prognoses,
|
141
|
+
:synopsis=>:synopses,
|
142
|
+
:thesis=>:theses,
|
143
|
+
:wife=>:wives,
|
144
|
+
:giraffe=>:giraffes,
|
145
|
+
:self=>:selves,
|
146
|
+
:dwarf=>:dwarves,
|
147
|
+
:hive=>:hives,
|
148
|
+
:fly=>:flies,
|
149
|
+
:buy=>:buys,
|
150
|
+
:soliloquy=>:soliloquies,
|
151
|
+
:day=>:days,
|
152
|
+
:attorney=>:attorneys,
|
153
|
+
:boy=>:boys,
|
154
|
+
:hoax=>:hoaxes,
|
155
|
+
:lunch=>:lunches,
|
156
|
+
:princess=>:princesses,
|
157
|
+
:matrix=>:matrices,
|
158
|
+
:vertex=>:vertices,
|
159
|
+
:index=>:indices,
|
160
|
+
:mouse=>:mice,
|
161
|
+
:louse=>:lice,
|
162
|
+
:quiz=>:quizzes,
|
163
|
+
:motive=>:motives,
|
164
|
+
:movie=>:movies,
|
165
|
+
:series=>:series,
|
166
|
+
:crisis=>:crises,
|
167
|
+
:person=>:people,
|
168
|
+
:man=>:men,
|
169
|
+
:woman=>:women,
|
170
|
+
:child=>:children,
|
171
|
+
:sex=>:sexes,
|
172
|
+
:move=>:moves
|
173
|
+
}.each do |k, v|
|
174
|
+
k.to_s.pluralize.should == v.to_s
|
175
|
+
v.to_s.singularize.should == k.to_s
|
176
|
+
end
|
177
|
+
[:equipment, :information, :rice, :money, :species, :series, :fish, :sheep, :news].each do |a|
|
178
|
+
a.to_s.pluralize.should == a.to_s.singularize
|
179
|
+
end
|
180
|
+
end
|
181
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "instance_filters plugin" do
|
4
|
+
before do
|
5
|
+
@c = Class.new(Sequel::Model(:people)) do
|
6
|
+
end
|
7
|
+
@sql = sql = ''
|
8
|
+
@v = v = [1]
|
9
|
+
@c.dataset.quote_identifiers = false
|
10
|
+
@c.dataset.meta_def(:update) do |opts|
|
11
|
+
sql.replace(update_sql(opts))
|
12
|
+
return v.first
|
13
|
+
end
|
14
|
+
@c.dataset.meta_def(:delete) do
|
15
|
+
sql.replace(delete_sql)
|
16
|
+
return v.first
|
17
|
+
end
|
18
|
+
@c.columns :id, :name, :num
|
19
|
+
@c.plugin :instance_filters
|
20
|
+
@p = @c.load(:id=>1, :name=>'John', :num=>1)
|
21
|
+
end
|
22
|
+
|
23
|
+
specify "should raise an error when updating a stale record" do
|
24
|
+
@p.update(:name=>'Bob')
|
25
|
+
@sql.should == "UPDATE people SET name = 'Bob' WHERE (id = 1)"
|
26
|
+
@p.instance_filter(:name=>'Jim')
|
27
|
+
@v.replace([0])
|
28
|
+
proc{@p.update(:name=>'Joe')}.should raise_error(Sequel::Plugins::InstanceFilters::Error)
|
29
|
+
@sql.should == "UPDATE people SET name = 'Joe' WHERE ((id = 1) AND (name = 'Jim'))"
|
30
|
+
end
|
31
|
+
|
32
|
+
specify "should raise an error when destroying a stale record" do
|
33
|
+
@p.destroy
|
34
|
+
@sql.should == "DELETE FROM people WHERE (id = 1)"
|
35
|
+
@p.instance_filter(:name=>'Jim')
|
36
|
+
@v.replace([0])
|
37
|
+
proc{@p.destroy}.should raise_error(Sequel::Plugins::InstanceFilters::Error)
|
38
|
+
@sql.should == "DELETE FROM people WHERE ((id = 1) AND (name = 'Jim'))"
|
39
|
+
end
|
40
|
+
|
41
|
+
specify "should apply all instance filters" do
|
42
|
+
@p.instance_filter(:name=>'Jim')
|
43
|
+
@p.instance_filter{num > 2}
|
44
|
+
@p.update(:name=>'Bob')
|
45
|
+
@sql.should == "UPDATE people SET name = 'Bob' WHERE ((id = 1) AND (name = 'Jim') AND (num > 2))"
|
46
|
+
end
|
47
|
+
|
48
|
+
specify "should drop instance filters after updating" do
|
49
|
+
@p.instance_filter(:name=>'Joe')
|
50
|
+
@p.update(:name=>'Joe')
|
51
|
+
@sql.should == "UPDATE people SET name = 'Joe' WHERE ((id = 1) AND (name = 'Joe'))"
|
52
|
+
@p.update(:name=>'Bob')
|
53
|
+
@sql.should == "UPDATE people SET name = 'Bob' WHERE (id = 1)"
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,133 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "InstanceHooks plugin" do
|
4
|
+
def r(x)
|
5
|
+
@r << x
|
6
|
+
x
|
7
|
+
end
|
8
|
+
|
9
|
+
before do
|
10
|
+
@c = Class.new(Sequel::Model(:items))
|
11
|
+
@c.plugin :instance_hooks
|
12
|
+
@c.raise_on_save_failure = false
|
13
|
+
@o = @c.new
|
14
|
+
@x = @c.load({:id=>1})
|
15
|
+
@r = []
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should support before_create_hook and after_create_hook" do
|
19
|
+
@o.after_create_hook{r 1}
|
20
|
+
@o.before_create_hook{r 2}
|
21
|
+
@o.after_create_hook{r 3}
|
22
|
+
@o.before_create_hook{r 4}
|
23
|
+
@o.save.should_not == nil
|
24
|
+
@r.should == [4, 2, 1, 3]
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should cancel the save if before_create_hook block returns false" do
|
28
|
+
@o.after_create_hook{r 1}
|
29
|
+
@o.before_create_hook{r false}
|
30
|
+
@o.before_create_hook{r 4}
|
31
|
+
@o.save.should == nil
|
32
|
+
@r.should == [4, false]
|
33
|
+
@r.clear
|
34
|
+
@o.save.should == nil
|
35
|
+
@r.should == [4, false]
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should support before_update_hook and after_update_hook" do
|
39
|
+
@x.after_update_hook{r 1}
|
40
|
+
@x.before_update_hook{r 2}
|
41
|
+
@x.after_update_hook{r 3}
|
42
|
+
@x.before_update_hook{r 4}
|
43
|
+
@x.save.should_not == nil
|
44
|
+
@r.should == [4, 2, 1, 3]
|
45
|
+
@x.save.should_not == nil
|
46
|
+
@r.should == [4, 2, 1, 3]
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should cancel the save if before_update_hook block returns false" do
|
50
|
+
@x.after_update_hook{r 1}
|
51
|
+
@x.before_update_hook{r false}
|
52
|
+
@x.before_update_hook{r 4}
|
53
|
+
@x.save.should == nil
|
54
|
+
@r.should == [4, false]
|
55
|
+
@r.clear
|
56
|
+
@x.save.should == nil
|
57
|
+
@r.should == [4, false]
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should support before_save_hook and after_save_hook" do
|
61
|
+
@o.after_save_hook{r 1}
|
62
|
+
@o.before_save_hook{r 2}
|
63
|
+
@o.after_save_hook{r 3}
|
64
|
+
@o.before_save_hook{r 4}
|
65
|
+
@o.save.should_not == nil
|
66
|
+
@r.should == [4, 2, 1, 3]
|
67
|
+
@r.clear
|
68
|
+
|
69
|
+
@x.after_save_hook{r 1}
|
70
|
+
@x.before_save_hook{r 2}
|
71
|
+
@x.after_save_hook{r 3}
|
72
|
+
@x.before_save_hook{r 4}
|
73
|
+
@x.save.should_not == nil
|
74
|
+
@r.should == [4, 2, 1, 3]
|
75
|
+
@x.save.should_not == nil
|
76
|
+
@r.should == [4, 2, 1, 3]
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should cancel the save if before_save_hook block returns false" do
|
80
|
+
@x.after_save_hook{r 1}
|
81
|
+
@x.before_save_hook{r false}
|
82
|
+
@x.before_save_hook{r 4}
|
83
|
+
@x.save.should == nil
|
84
|
+
@r.should == [4, false]
|
85
|
+
@r.clear
|
86
|
+
|
87
|
+
@x.after_save_hook{r 1}
|
88
|
+
@x.before_save_hook{r false}
|
89
|
+
@x.before_save_hook{r 4}
|
90
|
+
@x.save.should == nil
|
91
|
+
@r.should == [4, false]
|
92
|
+
@r.clear
|
93
|
+
@x.save.should == nil
|
94
|
+
@r.should == [4, false]
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should support before_destroy_hook and after_destroy_hook" do
|
98
|
+
@x.after_destroy_hook{r 1}
|
99
|
+
@x.before_destroy_hook{r 2}
|
100
|
+
@x.after_destroy_hook{r 3}
|
101
|
+
@x.before_destroy_hook{r 4}
|
102
|
+
@x.destroy.should_not == nil
|
103
|
+
@r.should == [4, 2, 1, 3]
|
104
|
+
end
|
105
|
+
|
106
|
+
it "should cancel the destroy if before_destroy_hook block returns false" do
|
107
|
+
@x.after_destroy_hook{r 1}
|
108
|
+
@x.before_destroy_hook{r false}
|
109
|
+
@x.before_destroy_hook{r 4}
|
110
|
+
@x.destroy.should == nil
|
111
|
+
@r.should == [4, false]
|
112
|
+
end
|
113
|
+
|
114
|
+
it "should support before_validation_hook and after_validation_hook" do
|
115
|
+
@o.after_validation_hook{r 1}
|
116
|
+
@o.before_validation_hook{r 2}
|
117
|
+
@o.after_validation_hook{r 3}
|
118
|
+
@o.before_validation_hook{r 4}
|
119
|
+
@o.valid?.should == true
|
120
|
+
@r.should == [4, 2, 1, 3]
|
121
|
+
end
|
122
|
+
|
123
|
+
it "should cancel the save if before_validation_hook block returns false" do
|
124
|
+
@o.after_validation_hook{r 1}
|
125
|
+
@o.before_validation_hook{r false}
|
126
|
+
@o.before_validation_hook{r 4}
|
127
|
+
@o.valid?.should == false
|
128
|
+
@r.should == [4, false]
|
129
|
+
@r.clear
|
130
|
+
@o.valid?.should == false
|
131
|
+
@r.should == [4, false]
|
132
|
+
end
|
133
|
+
end
|