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,240 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "Model#after_initialize" do
|
4
|
+
specify "should be called after initialization" do
|
5
|
+
$values1 = nil
|
6
|
+
$reached_after_initialized = false
|
7
|
+
|
8
|
+
a = Class.new(Sequel::Model)
|
9
|
+
a.class_eval do
|
10
|
+
columns :x, :y
|
11
|
+
def after_initialize
|
12
|
+
$values1 = @values.clone
|
13
|
+
$reached_after_initialized = true
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
a.new(:x => 1, :y => 2)
|
18
|
+
$values1.should == {:x => 1, :y => 2}
|
19
|
+
$reached_after_initialized.should == true
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "Model#before_create && Model#after_create" do
|
24
|
+
before do
|
25
|
+
MODEL_DB.reset
|
26
|
+
|
27
|
+
@c = Class.new(Sequel::Model(:items))
|
28
|
+
@c.class_eval do
|
29
|
+
columns :x
|
30
|
+
no_primary_key
|
31
|
+
|
32
|
+
def after_create
|
33
|
+
MODEL_DB << "BLAH after"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
specify "should be called around new record creation" do
|
39
|
+
@c.send(:define_method, :before_create){MODEL_DB << "BLAH before"}
|
40
|
+
@c.create(:x => 2)
|
41
|
+
MODEL_DB.sqls.should == [
|
42
|
+
'BLAH before',
|
43
|
+
'INSERT INTO items (x) VALUES (2)',
|
44
|
+
'BLAH after'
|
45
|
+
]
|
46
|
+
end
|
47
|
+
|
48
|
+
specify ".create should cancel the save and raise an error if before_create returns false and raise_on_save_failure is true" do
|
49
|
+
@c.send(:define_method, :before_create){false}
|
50
|
+
proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
|
51
|
+
proc{@c.create(:x => 2)}.should raise_error(Sequel::BeforeHookFailed)
|
52
|
+
MODEL_DB.sqls.should == []
|
53
|
+
end
|
54
|
+
|
55
|
+
specify ".create should cancel the save and return nil if before_create returns false and raise_on_save_failure is false" do
|
56
|
+
@c.send(:define_method, :before_create){false}
|
57
|
+
@c.raise_on_save_failure = false
|
58
|
+
@c.create(:x => 2).should == nil
|
59
|
+
MODEL_DB.sqls.should == []
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
describe "Model#before_update && Model#after_update" do
|
64
|
+
before do
|
65
|
+
MODEL_DB.reset
|
66
|
+
|
67
|
+
@c = Class.new(Sequel::Model(:items))
|
68
|
+
@c.class_eval do
|
69
|
+
columns :id, :x
|
70
|
+
def after_update; MODEL_DB << "BLAH after" end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
specify "should be called around record update" do
|
75
|
+
@c.send(:define_method, :before_update){MODEL_DB << "BLAH before"}
|
76
|
+
m = @c.load(:id => 2233, :x=>123)
|
77
|
+
m.save
|
78
|
+
MODEL_DB.sqls.should == [
|
79
|
+
'BLAH before',
|
80
|
+
'UPDATE items SET x = 123 WHERE (id = 2233)',
|
81
|
+
'BLAH after'
|
82
|
+
]
|
83
|
+
end
|
84
|
+
|
85
|
+
specify "#save should cancel the save and raise an error if before_update returns false and raise_on_save_failure is true" do
|
86
|
+
@c.send(:define_method, :before_update){false}
|
87
|
+
proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
|
88
|
+
proc{@c.load(:id => 2233).save}.should raise_error(Sequel::BeforeHookFailed)
|
89
|
+
MODEL_DB.sqls.should == []
|
90
|
+
end
|
91
|
+
|
92
|
+
specify "#save should cancel the save and return nil if before_update returns false and raise_on_save_failure is false" do
|
93
|
+
@c.send(:define_method, :before_update){false}
|
94
|
+
@c.raise_on_save_failure = false
|
95
|
+
@c.load(:id => 2233).save.should == nil
|
96
|
+
MODEL_DB.sqls.should == []
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
describe "Model#before_save && Model#after_save" do
|
101
|
+
before do
|
102
|
+
MODEL_DB.reset
|
103
|
+
|
104
|
+
@c = Class.new(Sequel::Model(:items))
|
105
|
+
@c.class_eval do
|
106
|
+
columns :x
|
107
|
+
def after_save; MODEL_DB << "BLAH after" end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
specify "should be called around record update" do
|
112
|
+
@c.send(:define_method, :before_save){MODEL_DB << "BLAH before"}
|
113
|
+
m = @c.load(:id => 2233, :x=>123)
|
114
|
+
m.save
|
115
|
+
MODEL_DB.sqls.should == [
|
116
|
+
'BLAH before',
|
117
|
+
'UPDATE items SET x = 123 WHERE (id = 2233)',
|
118
|
+
'BLAH after'
|
119
|
+
]
|
120
|
+
end
|
121
|
+
|
122
|
+
specify "should be called around record creation" do
|
123
|
+
@c.send(:define_method, :before_save){MODEL_DB << "BLAH before"}
|
124
|
+
@c.no_primary_key
|
125
|
+
@c.create(:x => 2)
|
126
|
+
MODEL_DB.sqls.should == [
|
127
|
+
'BLAH before',
|
128
|
+
'INSERT INTO items (x) VALUES (2)',
|
129
|
+
'BLAH after'
|
130
|
+
]
|
131
|
+
end
|
132
|
+
|
133
|
+
specify "#save should cancel the save and raise an error if before_save returns false and raise_on_save_failure is true" do
|
134
|
+
@c.send(:define_method, :before_save){false}
|
135
|
+
proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
|
136
|
+
proc{@c.load(:id => 2233).save}.should raise_error(Sequel::BeforeHookFailed)
|
137
|
+
MODEL_DB.sqls.should == []
|
138
|
+
end
|
139
|
+
|
140
|
+
specify "#save should cancel the save and return nil if before_save returns false and raise_on_save_failure is false" do
|
141
|
+
@c.send(:define_method, :before_save){false}
|
142
|
+
@c.raise_on_save_failure = false
|
143
|
+
@c.load(:id => 2233).save.should == nil
|
144
|
+
MODEL_DB.sqls.should == []
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
describe "Model#before_destroy && Model#after_destroy" do
|
149
|
+
before do
|
150
|
+
MODEL_DB.reset
|
151
|
+
|
152
|
+
@c = Class.new(Sequel::Model(:items))
|
153
|
+
@c.class_eval do
|
154
|
+
def after_destroy; MODEL_DB << "BLAH after"; end
|
155
|
+
|
156
|
+
def delete
|
157
|
+
MODEL_DB << "DELETE BLAH"
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
specify "should be called around record destruction" do
|
163
|
+
@c.send(:define_method, :before_destroy){MODEL_DB << "BLAH before"}
|
164
|
+
m = @c.load(:id => 2233)
|
165
|
+
m.destroy
|
166
|
+
MODEL_DB.sqls.should == [
|
167
|
+
'BLAH before',
|
168
|
+
'DELETE BLAH',
|
169
|
+
'BLAH after'
|
170
|
+
]
|
171
|
+
end
|
172
|
+
|
173
|
+
specify "#destroy should cancel the destroy and raise an error if before_destroy returns false and raise_on_save_failure is true" do
|
174
|
+
@c.send(:define_method, :before_destroy){false}
|
175
|
+
proc{@c.load(:id => 2233).destroy}.should raise_error(Sequel::BeforeHookFailed)
|
176
|
+
MODEL_DB.sqls.should == []
|
177
|
+
end
|
178
|
+
|
179
|
+
specify "#destroy should cancel the destroy and return nil if before_destroy returns false and raise_on_save_failure is false" do
|
180
|
+
@c.send(:define_method, :before_destroy){false}
|
181
|
+
@c.raise_on_save_failure = false
|
182
|
+
@c.load(:id => 2233).destroy.should == nil
|
183
|
+
MODEL_DB.sqls.should == []
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
describe "Model#before_validation && Model#after_validation" do
|
188
|
+
before do
|
189
|
+
MODEL_DB.reset
|
190
|
+
|
191
|
+
@c = Class.new(Sequel::Model(:items))
|
192
|
+
@c.class_eval do
|
193
|
+
def after_validation; MODEL_DB << "BLAH after" end
|
194
|
+
|
195
|
+
def validate
|
196
|
+
errors.add(:id, 'not valid') unless id == 2233
|
197
|
+
end
|
198
|
+
columns :id
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
specify "should be called around validation" do
|
203
|
+
@c.send(:define_method, :before_validation){MODEL_DB << "BLAH before"}
|
204
|
+
m = @c.load(:id => 2233)
|
205
|
+
m.should be_valid
|
206
|
+
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
|
207
|
+
|
208
|
+
MODEL_DB.sqls.clear
|
209
|
+
m = @c.load(:id => 22)
|
210
|
+
m.should_not be_valid
|
211
|
+
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
|
212
|
+
end
|
213
|
+
|
214
|
+
specify "should be called when calling save" do
|
215
|
+
@c.send(:define_method, :before_validation){MODEL_DB << "BLAH before"}
|
216
|
+
m = @c.load(:id => 2233, :x=>123)
|
217
|
+
m.save.should == m
|
218
|
+
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after', 'UPDATE items SET x = 123 WHERE (id = 2233)']
|
219
|
+
|
220
|
+
MODEL_DB.sqls.clear
|
221
|
+
m = @c.load(:id => 22)
|
222
|
+
m.raise_on_save_failure = false
|
223
|
+
m.save.should == nil
|
224
|
+
MODEL_DB.sqls.should == ['BLAH before', 'BLAH after']
|
225
|
+
end
|
226
|
+
|
227
|
+
specify "#save should cancel the save and raise an error if before_validation returns false and raise_on_save_failure is true" do
|
228
|
+
@c.send(:define_method, :before_validation){false}
|
229
|
+
proc{@c.load(:id => 2233).save}.should_not raise_error(Sequel::ValidationFailed)
|
230
|
+
proc{@c.load(:id => 2233).save}.should raise_error(Sequel::BeforeHookFailed)
|
231
|
+
MODEL_DB.sqls.should == []
|
232
|
+
end
|
233
|
+
|
234
|
+
specify "#save should cancel the save and return nil if before_validation returns false and raise_on_save_failure is false" do
|
235
|
+
@c.send(:define_method, :before_validation){false}
|
236
|
+
@c.raise_on_save_failure = false
|
237
|
+
@c.load(:id => 2233).save.should == nil
|
238
|
+
MODEL_DB.sqls.should == []
|
239
|
+
end
|
240
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'spec_helper')
|
2
|
+
|
3
|
+
describe Sequel::Inflections do
|
4
|
+
before do
|
5
|
+
@plurals, @singulars, @uncountables = Sequel.inflections.plurals.dup, Sequel.inflections.singulars.dup, Sequel.inflections.uncountables.dup
|
6
|
+
end
|
7
|
+
after do
|
8
|
+
Sequel.inflections.plurals.replace(@plurals)
|
9
|
+
Sequel.inflections.singulars.replace(@singulars)
|
10
|
+
Sequel.inflections.uncountables.replace(@uncountables)
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should be possible to clear the list of singulars, plurals, and uncountables" do
|
14
|
+
Sequel.inflections.clear(:plurals)
|
15
|
+
Sequel.inflections.plurals.should == []
|
16
|
+
Sequel.inflections.plural('blah', 'blahs')
|
17
|
+
Sequel.inflections.clear
|
18
|
+
Sequel.inflections.plurals.should == []
|
19
|
+
Sequel.inflections.singulars.should == []
|
20
|
+
Sequel.inflections.uncountables.should == []
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should be yielded and returned by Sequel.inflections" do
|
24
|
+
Sequel.inflections{|i| i.should == Sequel::Inflections}.should == Sequel::Inflections
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,593 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe "Sequel::Model()" do
|
4
|
+
before do
|
5
|
+
@db = Sequel::Model.db
|
6
|
+
end
|
7
|
+
|
8
|
+
it "should return a model subclass with the given dataset if given a dataset" do
|
9
|
+
ds = @db[:blah]
|
10
|
+
c = Sequel::Model(ds)
|
11
|
+
c.superclass.should == Sequel::Model
|
12
|
+
c.dataset.should == ds
|
13
|
+
end
|
14
|
+
|
15
|
+
it "should return a model subclass with a dataset with the default database and given table name if given a symbol" do
|
16
|
+
c = Sequel::Model(:blah)
|
17
|
+
c.superclass.should == Sequel::Model
|
18
|
+
c.db.should == @db
|
19
|
+
c.table_name.should == :blah
|
20
|
+
end
|
21
|
+
|
22
|
+
it "should return a model subclass associated to the given database if given a database" do
|
23
|
+
db = Sequel::Database.new
|
24
|
+
c = Sequel::Model(db)
|
25
|
+
c.superclass.should == Sequel::Model
|
26
|
+
c.db.should == db
|
27
|
+
proc{c.dataset}.should raise_error(Sequel::Error)
|
28
|
+
class SmBlahTest < c
|
29
|
+
end
|
30
|
+
SmBlahTest.db.should == db
|
31
|
+
SmBlahTest.table_name.should == :sm_blah_tests
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe Sequel::Model do
|
36
|
+
it "should have class method aliased as model" do
|
37
|
+
Sequel::Model.instance_methods.collect{|x| x.to_s}.should include("model")
|
38
|
+
|
39
|
+
model_a = Class.new(Sequel::Model(:items))
|
40
|
+
model_a.new.model.should be(model_a)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "should be associated with a dataset" do
|
44
|
+
model_a = Class.new(Sequel::Model) { set_dataset MODEL_DB[:as] }
|
45
|
+
|
46
|
+
model_a.dataset.should be_a_kind_of(MockDataset)
|
47
|
+
model_a.dataset.opts[:from].should == [:as]
|
48
|
+
|
49
|
+
model_b = Class.new(Sequel::Model) { set_dataset MODEL_DB[:bs] }
|
50
|
+
|
51
|
+
model_b.dataset.should be_a_kind_of(MockDataset)
|
52
|
+
model_b.dataset.opts[:from].should == [:bs]
|
53
|
+
|
54
|
+
model_a.dataset.opts[:from].should == [:as]
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
58
|
+
|
59
|
+
describe Sequel::Model, "dataset & schema" do
|
60
|
+
before do
|
61
|
+
@model = Class.new(Sequel::Model(:items))
|
62
|
+
end
|
63
|
+
|
64
|
+
it "creates dynamic model subclass with set table name" do
|
65
|
+
@model.table_name.should == :items
|
66
|
+
end
|
67
|
+
|
68
|
+
it "defaults to primary key of id" do
|
69
|
+
@model.primary_key.should == :id
|
70
|
+
end
|
71
|
+
|
72
|
+
it "allow primary key change" do
|
73
|
+
@model.set_primary_key :ssn
|
74
|
+
@model.primary_key.should == :ssn
|
75
|
+
end
|
76
|
+
|
77
|
+
it "allows dataset change" do
|
78
|
+
@model.set_dataset(MODEL_DB[:foo])
|
79
|
+
@model.table_name.should == :foo
|
80
|
+
end
|
81
|
+
|
82
|
+
it "set_dataset should take a symbol" do
|
83
|
+
@model.db = MODEL_DB
|
84
|
+
@model.set_dataset(:foo)
|
85
|
+
@model.table_name.should == :foo
|
86
|
+
end
|
87
|
+
|
88
|
+
it "table_name should respect table aliases" do
|
89
|
+
@model.set_dataset(:foo___x)
|
90
|
+
@model.table_name.should == :x
|
91
|
+
end
|
92
|
+
|
93
|
+
it "set_dataset should raise an error unless given a Symbol or Dataset" do
|
94
|
+
proc{@model.set_dataset(Object.new)}.should raise_error(Sequel::Error)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "set_dataset should add the destroy method to the dataset" do
|
98
|
+
ds = MODEL_DB[:foo]
|
99
|
+
ds.should_not respond_to(:destroy)
|
100
|
+
@model.set_dataset(ds)
|
101
|
+
ds.should respond_to(:destroy)
|
102
|
+
end
|
103
|
+
|
104
|
+
it "should raise an error on set_dataset if there is an error connecting to the database" do
|
105
|
+
@model.meta_def(:columns){raise Sequel::DatabaseConnectionError}
|
106
|
+
proc{@model.set_dataset(MODEL_DB[:foo].join(:blah))}.should raise_error
|
107
|
+
end
|
108
|
+
|
109
|
+
it "should not raise an error if there is a problem getting the columns for a dataset" do
|
110
|
+
@model.meta_def(:columns){raise Sequel::Error}
|
111
|
+
proc{@model.set_dataset(MODEL_DB[:foo].join(:blah))}.should_not raise_error
|
112
|
+
end
|
113
|
+
|
114
|
+
it "doesn't raise an error on set_dataset if there is an error raised getting the schema" do
|
115
|
+
@model.meta_def(:get_db_schema){raise Sequel::Error}
|
116
|
+
proc{@model.set_dataset(MODEL_DB[:foo])}.should_not raise_error
|
117
|
+
end
|
118
|
+
|
119
|
+
it "doesn't raise an error on inherited if there is an error setting the dataset" do
|
120
|
+
@model.meta_def(:set_dataset){raise Sequel::Error}
|
121
|
+
proc{Class.new(@model)}.should_not raise_error
|
122
|
+
end
|
123
|
+
end
|
124
|
+
|
125
|
+
describe Sequel::Model, "constructor" do
|
126
|
+
|
127
|
+
before(:each) do
|
128
|
+
@m = Class.new(Sequel::Model)
|
129
|
+
@m.columns :a, :b
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should accept a hash" do
|
133
|
+
m = @m.new(:a => 1, :b => 2)
|
134
|
+
m.values.should == {:a => 1, :b => 2}
|
135
|
+
m.should be_new
|
136
|
+
end
|
137
|
+
|
138
|
+
it "should accept a block and yield itself to the block" do
|
139
|
+
block_called = false
|
140
|
+
m = @m.new {|i| block_called = true; i.should be_a_kind_of(@m); i.values[:a] = 1}
|
141
|
+
|
142
|
+
block_called.should be_true
|
143
|
+
m.values[:a].should == 1
|
144
|
+
end
|
145
|
+
|
146
|
+
end
|
147
|
+
|
148
|
+
describe Sequel::Model, "new" do
|
149
|
+
|
150
|
+
before(:each) do
|
151
|
+
@m = Class.new(Sequel::Model) do
|
152
|
+
set_dataset MODEL_DB[:items]
|
153
|
+
columns :x, :id
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should be marked as new?" do
|
158
|
+
o = @m.new
|
159
|
+
o.should be_new
|
160
|
+
end
|
161
|
+
|
162
|
+
it "should not be marked as new? once it is saved" do
|
163
|
+
o = @m.new(:x => 1)
|
164
|
+
o.should be_new
|
165
|
+
o.save
|
166
|
+
o.should_not be_new
|
167
|
+
end
|
168
|
+
|
169
|
+
it "should use the last inserted id as primary key if not in values" do
|
170
|
+
d = @m.dataset
|
171
|
+
def d.insert(*args)
|
172
|
+
super
|
173
|
+
1234
|
174
|
+
end
|
175
|
+
|
176
|
+
def d.first
|
177
|
+
{:x => 1, :id => 1234}
|
178
|
+
end
|
179
|
+
|
180
|
+
o = @m.new(:x => 1)
|
181
|
+
o.save
|
182
|
+
o.id.should == 1234
|
183
|
+
|
184
|
+
o = @m.load(:x => 1, :id => 333)
|
185
|
+
o.save
|
186
|
+
o.id.should == 333
|
187
|
+
end
|
188
|
+
|
189
|
+
end
|
190
|
+
|
191
|
+
describe Sequel::Model, ".subset" do
|
192
|
+
before do
|
193
|
+
MODEL_DB.reset
|
194
|
+
|
195
|
+
@c = Class.new(Sequel::Model(:items))
|
196
|
+
end
|
197
|
+
|
198
|
+
specify "should create a filter on the underlying dataset" do
|
199
|
+
proc {@c.new_only}.should raise_error(NoMethodError)
|
200
|
+
|
201
|
+
@c.subset(:new_only) {:age.sql_number < 'new'}
|
202
|
+
|
203
|
+
@c.new_only.sql.should == "SELECT * FROM items WHERE (age < 'new')"
|
204
|
+
@c.dataset.new_only.sql.should == "SELECT * FROM items WHERE (age < 'new')"
|
205
|
+
|
206
|
+
@c.subset(:pricey) {:price.sql_number > 100}
|
207
|
+
|
208
|
+
@c.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
|
209
|
+
@c.dataset.pricey.sql.should == "SELECT * FROM items WHERE (price > 100)"
|
210
|
+
|
211
|
+
@c.pricey.new_only.sql.should == "SELECT * FROM items WHERE ((price > 100) AND (age < 'new'))"
|
212
|
+
@c.new_only.pricey.sql.should == "SELECT * FROM items WHERE ((age < 'new') AND (price > 100))"
|
213
|
+
end
|
214
|
+
|
215
|
+
specify "should not override existing model methods" do
|
216
|
+
@c.meta_def(:active){true}
|
217
|
+
@c.subset(:active, :active)
|
218
|
+
@c.active.should == true
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
describe Sequel::Model, ".find" do
|
223
|
+
|
224
|
+
before(:each) do
|
225
|
+
MODEL_DB.reset
|
226
|
+
|
227
|
+
@c = Class.new(Sequel::Model(:items))
|
228
|
+
|
229
|
+
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
230
|
+
@dataset = @c.dataset
|
231
|
+
$sqls = []
|
232
|
+
@dataset.extend(Module.new {
|
233
|
+
def fetch_rows(sql)
|
234
|
+
$sqls << sql
|
235
|
+
yield $cache_dataset_row
|
236
|
+
end
|
237
|
+
})
|
238
|
+
end
|
239
|
+
|
240
|
+
it "should return the first record matching the given filter" do
|
241
|
+
@c.find(:name => 'sharon').should be_a_kind_of(@c)
|
242
|
+
$sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
|
243
|
+
|
244
|
+
@c.find(:name.like('abc%')).should be_a_kind_of(@c)
|
245
|
+
$sqls.last.should == "SELECT * FROM items WHERE (name LIKE 'abc%') LIMIT 1"
|
246
|
+
end
|
247
|
+
|
248
|
+
specify "should accept filter blocks" do
|
249
|
+
@c.find{:id.sql_number > 1}.should be_a_kind_of(@c)
|
250
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id > 1) LIMIT 1"
|
251
|
+
|
252
|
+
@c.find {(:x.sql_number > 1) & (:y.sql_number < 2)}.should be_a_kind_of(@c)
|
253
|
+
$sqls.last.should == "SELECT * FROM items WHERE ((x > 1) AND (y < 2)) LIMIT 1"
|
254
|
+
end
|
255
|
+
|
256
|
+
end
|
257
|
+
|
258
|
+
describe Sequel::Model, ".fetch" do
|
259
|
+
|
260
|
+
before(:each) do
|
261
|
+
MODEL_DB.reset
|
262
|
+
@c = Class.new(Sequel::Model(:items))
|
263
|
+
end
|
264
|
+
|
265
|
+
it "should return instances of Model" do
|
266
|
+
@c.fetch("SELECT * FROM items").first.should be_a_kind_of(@c)
|
267
|
+
end
|
268
|
+
|
269
|
+
it "should return true for .empty? and not raise an error on empty selection" do
|
270
|
+
rows = @c.fetch("SELECT * FROM items WHERE FALSE")
|
271
|
+
@c.send(:define_method, :fetch_rows){|sql| yield({:count => 0})}
|
272
|
+
proc {rows.empty?}.should_not raise_error
|
273
|
+
end
|
274
|
+
end
|
275
|
+
|
276
|
+
describe Sequel::Model, ".find_or_create" do
|
277
|
+
|
278
|
+
before(:each) do
|
279
|
+
MODEL_DB.reset
|
280
|
+
@c = Class.new(Sequel::Model(:items)) do
|
281
|
+
no_primary_key
|
282
|
+
columns :x
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
it "should find the record" do
|
287
|
+
@c.find_or_create(:x => 1)
|
288
|
+
MODEL_DB.sqls.should == ["SELECT * FROM items WHERE (x = 1) LIMIT 1"]
|
289
|
+
|
290
|
+
MODEL_DB.reset
|
291
|
+
end
|
292
|
+
|
293
|
+
it "should create the record if not found" do
|
294
|
+
@c.meta_def(:find) do |*args|
|
295
|
+
dataset.filter(*args).first
|
296
|
+
nil
|
297
|
+
end
|
298
|
+
|
299
|
+
@c.find_or_create(:x => 1)
|
300
|
+
MODEL_DB.sqls.should == [
|
301
|
+
"SELECT * FROM items WHERE (x = 1) LIMIT 1",
|
302
|
+
"INSERT INTO items (x) VALUES (1)"
|
303
|
+
]
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
describe Sequel::Model, ".all" do
|
308
|
+
|
309
|
+
before(:each) do
|
310
|
+
MODEL_DB.reset
|
311
|
+
@c = Class.new(Sequel::Model(:items)) do
|
312
|
+
no_primary_key
|
313
|
+
end
|
314
|
+
|
315
|
+
@c.dataset.meta_def(:all) {1234}
|
316
|
+
end
|
317
|
+
|
318
|
+
it "should return all records in the dataset" do
|
319
|
+
@c.all.should == 1234
|
320
|
+
end
|
321
|
+
|
322
|
+
end
|
323
|
+
|
324
|
+
class DummyModelBased < Sequel::Model(:blog)
|
325
|
+
end
|
326
|
+
|
327
|
+
describe Sequel::Model, "(:tablename)" do
|
328
|
+
|
329
|
+
it "should allow reopening of descendant classes" do
|
330
|
+
proc do
|
331
|
+
eval "class DummyModelBased < Sequel::Model(:blog); end"
|
332
|
+
end.should_not raise_error
|
333
|
+
end
|
334
|
+
|
335
|
+
end
|
336
|
+
|
337
|
+
describe Sequel::Model, "A model class without a primary key" do
|
338
|
+
|
339
|
+
before(:each) do
|
340
|
+
MODEL_DB.reset
|
341
|
+
@c = Class.new(Sequel::Model(:items)) do
|
342
|
+
columns :x
|
343
|
+
no_primary_key
|
344
|
+
end
|
345
|
+
end
|
346
|
+
|
347
|
+
it "should be able to insert records without selecting them back" do
|
348
|
+
i = nil
|
349
|
+
proc {i = @c.create(:x => 1)}.should_not raise_error
|
350
|
+
i.class.should be(@c)
|
351
|
+
i.values.to_hash.should == {:x => 1}
|
352
|
+
|
353
|
+
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (1)']
|
354
|
+
end
|
355
|
+
|
356
|
+
it "should raise when deleting" do
|
357
|
+
o = @c.new
|
358
|
+
proc {o.delete}.should raise_error
|
359
|
+
end
|
360
|
+
|
361
|
+
it "should insert a record when saving" do
|
362
|
+
o = @c.new(:x => 2)
|
363
|
+
o.should be_new
|
364
|
+
o.save
|
365
|
+
MODEL_DB.sqls.should == ['INSERT INTO items (x) VALUES (2)']
|
366
|
+
end
|
367
|
+
|
368
|
+
end
|
369
|
+
|
370
|
+
describe Sequel::Model, "attribute accessors" do
|
371
|
+
before do
|
372
|
+
MODEL_DB.reset
|
373
|
+
@dataset = Sequel::Dataset.new(MODEL_DB)
|
374
|
+
def @dataset.columns; [:x, :y]; end
|
375
|
+
@c = Class.new(Sequel::Model) do
|
376
|
+
def self.db_schema
|
377
|
+
set_columns(Array(@columns))
|
378
|
+
@db_schema = {:x=>{}, :y=>{}}
|
379
|
+
end
|
380
|
+
def self.set_dataset(ds, opts={})
|
381
|
+
@columns = ds.columns
|
382
|
+
db_schema
|
383
|
+
end
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
it "should be created on set_dataset" do
|
388
|
+
%w'x y x= y='.each do |x|
|
389
|
+
@c.instance_methods.collect{|y| y.to_s}.should_not include(x)
|
390
|
+
end
|
391
|
+
@c.set_dataset(@dataset)
|
392
|
+
%w'x y x= y='.each do |x|
|
393
|
+
@c.instance_methods.collect{|y| y.to_s}.should include(x)
|
394
|
+
end
|
395
|
+
o = @c.new
|
396
|
+
%w'x y x= y='.each do |x|
|
397
|
+
o.methods.collect{|y| y.to_s}.should include(x)
|
398
|
+
end
|
399
|
+
|
400
|
+
o.x.should be_nil
|
401
|
+
o.x = 34
|
402
|
+
o.x.should == 34
|
403
|
+
end
|
404
|
+
|
405
|
+
it "should be only accept one argument for the write accessor" do
|
406
|
+
@c.set_dataset(@dataset)
|
407
|
+
o = @c.new
|
408
|
+
|
409
|
+
o.x = 34
|
410
|
+
o.x.should == 34
|
411
|
+
proc{o.send(:x=)}.should raise_error
|
412
|
+
proc{o.send(:x=, 3, 4)}.should raise_error
|
413
|
+
end
|
414
|
+
end
|
415
|
+
|
416
|
+
describe Sequel::Model, ".[]" do
|
417
|
+
|
418
|
+
before(:each) do
|
419
|
+
MODEL_DB.reset
|
420
|
+
|
421
|
+
@c = Class.new(Sequel::Model(:items))
|
422
|
+
|
423
|
+
$cache_dataset_row = {:name => 'sharon', :id => 1}
|
424
|
+
@dataset = @c.dataset
|
425
|
+
$sqls = []
|
426
|
+
@dataset.extend(Module.new {
|
427
|
+
def fetch_rows(sql)
|
428
|
+
$sqls << sql
|
429
|
+
yield $cache_dataset_row
|
430
|
+
end
|
431
|
+
})
|
432
|
+
end
|
433
|
+
|
434
|
+
it "should return the first record for the given pk" do
|
435
|
+
@c[1].should be_a_kind_of(@c)
|
436
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 1) LIMIT 1"
|
437
|
+
@c[9999].should be_a_kind_of(@c)
|
438
|
+
$sqls.last.should == "SELECT * FROM items WHERE (id = 9999) LIMIT 1"
|
439
|
+
end
|
440
|
+
|
441
|
+
it "should work correctly for custom primary key" do
|
442
|
+
@c.set_primary_key :name
|
443
|
+
@c['sharon'].should be_a_kind_of(@c)
|
444
|
+
$sqls.last.should == "SELECT * FROM items WHERE (name = 'sharon') LIMIT 1"
|
445
|
+
end
|
446
|
+
|
447
|
+
it "should work correctly for composite primary key specified as array" do
|
448
|
+
@c.set_primary_key [:node_id, :kind]
|
449
|
+
@c[3921, 201].should be_a_kind_of(@c)
|
450
|
+
$sqls.last.should =~ \
|
451
|
+
/^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
|
452
|
+
end
|
453
|
+
|
454
|
+
it "should work correctly for composite primary key specified as separate arguments" do
|
455
|
+
@c.set_primary_key :node_id, :kind
|
456
|
+
@c[3921, 201].should be_a_kind_of(@c)
|
457
|
+
$sqls.last.should =~ \
|
458
|
+
/^SELECT \* FROM items WHERE \((\(node_id = 3921\) AND \(kind = 201\))|(\(kind = 201\) AND \(node_id = 3921\))\) LIMIT 1$/
|
459
|
+
end
|
460
|
+
end
|
461
|
+
|
462
|
+
context "Model#inspect" do
|
463
|
+
before do
|
464
|
+
@o = Sequel::Model.load(:x => 333)
|
465
|
+
end
|
466
|
+
|
467
|
+
specify "should include the class name and the values" do
|
468
|
+
@o.inspect.should == '#<Sequel::Model @values={:x=>333}>'
|
469
|
+
end
|
470
|
+
end
|
471
|
+
|
472
|
+
context "Model.db_schema" do
|
473
|
+
before do
|
474
|
+
@c = Class.new(Sequel::Model(:items)) do
|
475
|
+
def self.columns; orig_columns; end
|
476
|
+
end
|
477
|
+
@dataset = Sequel::Dataset.new(nil).from(:items)
|
478
|
+
@dataset.meta_def(:db){@db ||= Sequel::Database.new}
|
479
|
+
def @dataset.naked; self; end
|
480
|
+
def @dataset.columns; []; end
|
481
|
+
def @dataset.def_mutation_method(*names); end
|
482
|
+
end
|
483
|
+
|
484
|
+
specify "should use the database's schema_for_table and set the columns and dataset columns" do
|
485
|
+
d = @dataset.db
|
486
|
+
def d.schema(table, opts = {})
|
487
|
+
[[:x, {:type=>:integer}], [:y, {:type=>:string}]]
|
488
|
+
end
|
489
|
+
@c.dataset = @dataset
|
490
|
+
@c.db_schema.should == {:x=>{:type=>:integer}, :y=>{:type=>:string}}
|
491
|
+
@c.columns.should == [:x, :y]
|
492
|
+
@c.dataset.instance_variable_get(:@columns).should == [:x, :y]
|
493
|
+
end
|
494
|
+
|
495
|
+
specify "should restrict the schema and columns for datasets with a :select option" do
|
496
|
+
ds = @dataset.select(:x, :y___z)
|
497
|
+
d = ds.db
|
498
|
+
def d.schema(table, opts = {})
|
499
|
+
[[:x, {:type=>:integer}], [:y, {:type=>:string}]]
|
500
|
+
end
|
501
|
+
def @c.columns; [:x, :z]; end
|
502
|
+
@c.dataset = ds
|
503
|
+
@c.db_schema.should == {:x=>{:type=>:integer}, :z=>{}}
|
504
|
+
end
|
505
|
+
|
506
|
+
specify "should not use schema if the dataset uses multiple tables or custom sql" do
|
507
|
+
ds = @dataset.join(:x, :id)
|
508
|
+
d = ds.db
|
509
|
+
e = false
|
510
|
+
d.meta_def(:schema){|table, *opts| e = true}
|
511
|
+
def @c.columns; [:x]; end
|
512
|
+
@c.dataset = ds
|
513
|
+
@c.db_schema.should == {:x=>{}}
|
514
|
+
e.should == false
|
515
|
+
end
|
516
|
+
|
517
|
+
specify "should fallback to fetching records if schema raises an error" do
|
518
|
+
ds = @dataset.join(:x, :id)
|
519
|
+
d = ds.db
|
520
|
+
def d.schema(table, opts={})
|
521
|
+
raise StandardError
|
522
|
+
end
|
523
|
+
def @c.columns; [:x]; end
|
524
|
+
@c.dataset = ds
|
525
|
+
@c.db_schema.should == {:x=>{}}
|
526
|
+
end
|
527
|
+
|
528
|
+
specify "should automatically set a singular primary key based on the schema" do
|
529
|
+
ds = @dataset
|
530
|
+
d = ds.db
|
531
|
+
d.meta_def(:schema){|table, *opts| [[:x, {:primary_key=>true}]]}
|
532
|
+
@c.primary_key.should == :id
|
533
|
+
@c.dataset = ds
|
534
|
+
@c.db_schema.should == {:x=>{:primary_key=>true}}
|
535
|
+
@c.primary_key.should == :x
|
536
|
+
end
|
537
|
+
|
538
|
+
specify "should automatically set the composite primary key based on the schema" do
|
539
|
+
ds = @dataset
|
540
|
+
d = ds.db
|
541
|
+
d.meta_def(:schema){|table, *opts| [[:x, {:primary_key=>true}], [:y, {:primary_key=>true}]]}
|
542
|
+
@c.primary_key.should == :id
|
543
|
+
@c.dataset = ds
|
544
|
+
@c.db_schema.should == {:x=>{:primary_key=>true}, :y=>{:primary_key=>true}}
|
545
|
+
@c.primary_key.should == [:x, :y]
|
546
|
+
end
|
547
|
+
|
548
|
+
specify "should automatically set no primary key based on the schema" do
|
549
|
+
ds = @dataset
|
550
|
+
d = ds.db
|
551
|
+
d.meta_def(:schema){|table, *opts| [[:x, {:primary_key=>false}], [:y, {:primary_key=>false}]]}
|
552
|
+
@c.primary_key.should == :id
|
553
|
+
@c.dataset = ds
|
554
|
+
@c.db_schema.should == {:x=>{:primary_key=>false}, :y=>{:primary_key=>false}}
|
555
|
+
@c.primary_key.should == nil
|
556
|
+
end
|
557
|
+
|
558
|
+
specify "should not modify the primary key unless all column schema hashes have a :primary_key entry" do
|
559
|
+
ds = @dataset
|
560
|
+
d = ds.db
|
561
|
+
d.meta_def(:schema){|table, *opts| [[:x, {:primary_key=>false}], [:y, {}]]}
|
562
|
+
@c.primary_key.should == :id
|
563
|
+
@c.dataset = ds
|
564
|
+
@c.db_schema.should == {:x=>{:primary_key=>false}, :y=>{}}
|
565
|
+
@c.primary_key.should == :id
|
566
|
+
end
|
567
|
+
end
|
568
|
+
|
569
|
+
context "Model#use_transactions" do
|
570
|
+
before do
|
571
|
+
@c = Class.new(Sequel::Model(:items))
|
572
|
+
end
|
573
|
+
|
574
|
+
specify "should return class value by default" do
|
575
|
+
@c.use_transactions = true
|
576
|
+
@c.new.use_transactions.should == true
|
577
|
+
@c.use_transactions = false
|
578
|
+
@c.new.use_transactions.should == false
|
579
|
+
end
|
580
|
+
|
581
|
+
specify "should return set value if manually set" do
|
582
|
+
instance = @c.new
|
583
|
+
instance.use_transactions = false
|
584
|
+
instance.use_transactions.should == false
|
585
|
+
@c.use_transactions = true
|
586
|
+
instance.use_transactions.should == false
|
587
|
+
|
588
|
+
instance.use_transactions = true
|
589
|
+
instance.use_transactions.should == true
|
590
|
+
@c.use_transactions = false
|
591
|
+
instance.use_transactions.should == true
|
592
|
+
end
|
593
|
+
end
|