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.
Files changed (237) hide show
  1. data/CHANGELOG +3134 -0
  2. data/COPYING +19 -0
  3. data/README.rdoc +723 -0
  4. data/Rakefile +193 -0
  5. data/bin/sequel +196 -0
  6. data/doc/advanced_associations.rdoc +644 -0
  7. data/doc/cheat_sheet.rdoc +218 -0
  8. data/doc/dataset_basics.rdoc +106 -0
  9. data/doc/dataset_filtering.rdoc +158 -0
  10. data/doc/opening_databases.rdoc +296 -0
  11. data/doc/prepared_statements.rdoc +104 -0
  12. data/doc/reflection.rdoc +84 -0
  13. data/doc/release_notes/1.0.txt +38 -0
  14. data/doc/release_notes/1.1.txt +143 -0
  15. data/doc/release_notes/1.3.txt +101 -0
  16. data/doc/release_notes/1.4.0.txt +53 -0
  17. data/doc/release_notes/1.5.0.txt +155 -0
  18. data/doc/release_notes/2.0.0.txt +298 -0
  19. data/doc/release_notes/2.1.0.txt +271 -0
  20. data/doc/release_notes/2.10.0.txt +328 -0
  21. data/doc/release_notes/2.11.0.txt +215 -0
  22. data/doc/release_notes/2.12.0.txt +534 -0
  23. data/doc/release_notes/2.2.0.txt +253 -0
  24. data/doc/release_notes/2.3.0.txt +88 -0
  25. data/doc/release_notes/2.4.0.txt +106 -0
  26. data/doc/release_notes/2.5.0.txt +137 -0
  27. data/doc/release_notes/2.6.0.txt +157 -0
  28. data/doc/release_notes/2.7.0.txt +166 -0
  29. data/doc/release_notes/2.8.0.txt +171 -0
  30. data/doc/release_notes/2.9.0.txt +97 -0
  31. data/doc/release_notes/3.0.0.txt +221 -0
  32. data/doc/release_notes/3.1.0.txt +406 -0
  33. data/doc/release_notes/3.10.0.txt +286 -0
  34. data/doc/release_notes/3.2.0.txt +268 -0
  35. data/doc/release_notes/3.3.0.txt +192 -0
  36. data/doc/release_notes/3.4.0.txt +325 -0
  37. data/doc/release_notes/3.5.0.txt +510 -0
  38. data/doc/release_notes/3.6.0.txt +366 -0
  39. data/doc/release_notes/3.7.0.txt +179 -0
  40. data/doc/release_notes/3.8.0.txt +151 -0
  41. data/doc/release_notes/3.9.0.txt +233 -0
  42. data/doc/schema.rdoc +36 -0
  43. data/doc/sharding.rdoc +113 -0
  44. data/doc/virtual_rows.rdoc +205 -0
  45. data/lib/sequel.rb +1 -0
  46. data/lib/sequel/adapters/ado.rb +90 -0
  47. data/lib/sequel/adapters/ado/mssql.rb +30 -0
  48. data/lib/sequel/adapters/amalgalite.rb +176 -0
  49. data/lib/sequel/adapters/db2.rb +139 -0
  50. data/lib/sequel/adapters/dbi.rb +113 -0
  51. data/lib/sequel/adapters/do.rb +188 -0
  52. data/lib/sequel/adapters/do/mysql.rb +49 -0
  53. data/lib/sequel/adapters/do/postgres.rb +91 -0
  54. data/lib/sequel/adapters/do/sqlite.rb +40 -0
  55. data/lib/sequel/adapters/firebird.rb +283 -0
  56. data/lib/sequel/adapters/informix.rb +77 -0
  57. data/lib/sequel/adapters/jdbc.rb +587 -0
  58. data/lib/sequel/adapters/jdbc/as400.rb +58 -0
  59. data/lib/sequel/adapters/jdbc/h2.rb +133 -0
  60. data/lib/sequel/adapters/jdbc/mssql.rb +57 -0
  61. data/lib/sequel/adapters/jdbc/mysql.rb +78 -0
  62. data/lib/sequel/adapters/jdbc/oracle.rb +50 -0
  63. data/lib/sequel/adapters/jdbc/postgresql.rb +108 -0
  64. data/lib/sequel/adapters/jdbc/sqlite.rb +55 -0
  65. data/lib/sequel/adapters/mysql.rb +421 -0
  66. data/lib/sequel/adapters/odbc.rb +143 -0
  67. data/lib/sequel/adapters/odbc/mssql.rb +42 -0
  68. data/lib/sequel/adapters/openbase.rb +64 -0
  69. data/lib/sequel/adapters/oracle.rb +131 -0
  70. data/lib/sequel/adapters/postgres.rb +504 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +490 -0
  72. data/lib/sequel/adapters/shared/mysql.rb +498 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +195 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +830 -0
  75. data/lib/sequel/adapters/shared/progress.rb +44 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +389 -0
  77. data/lib/sequel/adapters/sqlite.rb +224 -0
  78. data/lib/sequel/adapters/utils/stored_procedures.rb +84 -0
  79. data/lib/sequel/connection_pool.rb +99 -0
  80. data/lib/sequel/connection_pool/sharded_single.rb +84 -0
  81. data/lib/sequel/connection_pool/sharded_threaded.rb +211 -0
  82. data/lib/sequel/connection_pool/single.rb +29 -0
  83. data/lib/sequel/connection_pool/threaded.rb +150 -0
  84. data/lib/sequel/core.rb +293 -0
  85. data/lib/sequel/core_sql.rb +241 -0
  86. data/lib/sequel/database.rb +1079 -0
  87. data/lib/sequel/database/schema_generator.rb +327 -0
  88. data/lib/sequel/database/schema_methods.rb +203 -0
  89. data/lib/sequel/database/schema_sql.rb +320 -0
  90. data/lib/sequel/dataset.rb +32 -0
  91. data/lib/sequel/dataset/actions.rb +441 -0
  92. data/lib/sequel/dataset/features.rb +86 -0
  93. data/lib/sequel/dataset/graph.rb +254 -0
  94. data/lib/sequel/dataset/misc.rb +119 -0
  95. data/lib/sequel/dataset/mutation.rb +64 -0
  96. data/lib/sequel/dataset/prepared_statements.rb +227 -0
  97. data/lib/sequel/dataset/query.rb +709 -0
  98. data/lib/sequel/dataset/sql.rb +996 -0
  99. data/lib/sequel/exceptions.rb +51 -0
  100. data/lib/sequel/extensions/blank.rb +43 -0
  101. data/lib/sequel/extensions/inflector.rb +242 -0
  102. data/lib/sequel/extensions/looser_typecasting.rb +21 -0
  103. data/lib/sequel/extensions/migration.rb +239 -0
  104. data/lib/sequel/extensions/named_timezones.rb +61 -0
  105. data/lib/sequel/extensions/pagination.rb +100 -0
  106. data/lib/sequel/extensions/pretty_table.rb +82 -0
  107. data/lib/sequel/extensions/query.rb +52 -0
  108. data/lib/sequel/extensions/schema_dumper.rb +271 -0
  109. data/lib/sequel/extensions/sql_expr.rb +122 -0
  110. data/lib/sequel/extensions/string_date_time.rb +46 -0
  111. data/lib/sequel/extensions/thread_local_timezones.rb +48 -0
  112. data/lib/sequel/metaprogramming.rb +9 -0
  113. data/lib/sequel/model.rb +120 -0
  114. data/lib/sequel/model/associations.rb +1514 -0
  115. data/lib/sequel/model/base.rb +1069 -0
  116. data/lib/sequel/model/default_inflections.rb +45 -0
  117. data/lib/sequel/model/errors.rb +39 -0
  118. data/lib/sequel/model/exceptions.rb +21 -0
  119. data/lib/sequel/model/inflections.rb +162 -0
  120. data/lib/sequel/model/plugins.rb +70 -0
  121. data/lib/sequel/plugins/active_model.rb +59 -0
  122. data/lib/sequel/plugins/association_dependencies.rb +103 -0
  123. data/lib/sequel/plugins/association_proxies.rb +41 -0
  124. data/lib/sequel/plugins/boolean_readers.rb +53 -0
  125. data/lib/sequel/plugins/caching.rb +141 -0
  126. data/lib/sequel/plugins/class_table_inheritance.rb +214 -0
  127. data/lib/sequel/plugins/composition.rb +138 -0
  128. data/lib/sequel/plugins/force_encoding.rb +72 -0
  129. data/lib/sequel/plugins/hook_class_methods.rb +126 -0
  130. data/lib/sequel/plugins/identity_map.rb +116 -0
  131. data/lib/sequel/plugins/instance_filters.rb +98 -0
  132. data/lib/sequel/plugins/instance_hooks.rb +57 -0
  133. data/lib/sequel/plugins/lazy_attributes.rb +77 -0
  134. data/lib/sequel/plugins/many_through_many.rb +208 -0
  135. data/lib/sequel/plugins/nested_attributes.rb +206 -0
  136. data/lib/sequel/plugins/optimistic_locking.rb +81 -0
  137. data/lib/sequel/plugins/rcte_tree.rb +281 -0
  138. data/lib/sequel/plugins/schema.rb +66 -0
  139. data/lib/sequel/plugins/serialization.rb +166 -0
  140. data/lib/sequel/plugins/single_table_inheritance.rb +74 -0
  141. data/lib/sequel/plugins/subclasses.rb +45 -0
  142. data/lib/sequel/plugins/tactical_eager_loading.rb +61 -0
  143. data/lib/sequel/plugins/timestamps.rb +87 -0
  144. data/lib/sequel/plugins/touch.rb +118 -0
  145. data/lib/sequel/plugins/typecast_on_load.rb +72 -0
  146. data/lib/sequel/plugins/validation_class_methods.rb +405 -0
  147. data/lib/sequel/plugins/validation_helpers.rb +223 -0
  148. data/lib/sequel/sql.rb +1020 -0
  149. data/lib/sequel/timezones.rb +161 -0
  150. data/lib/sequel/version.rb +12 -0
  151. data/lib/sequel_core.rb +1 -0
  152. data/lib/sequel_model.rb +1 -0
  153. data/spec/adapters/firebird_spec.rb +407 -0
  154. data/spec/adapters/informix_spec.rb +97 -0
  155. data/spec/adapters/mssql_spec.rb +403 -0
  156. data/spec/adapters/mysql_spec.rb +1019 -0
  157. data/spec/adapters/oracle_spec.rb +286 -0
  158. data/spec/adapters/postgres_spec.rb +969 -0
  159. data/spec/adapters/spec_helper.rb +51 -0
  160. data/spec/adapters/sqlite_spec.rb +432 -0
  161. data/spec/core/connection_pool_spec.rb +808 -0
  162. data/spec/core/core_sql_spec.rb +417 -0
  163. data/spec/core/database_spec.rb +1662 -0
  164. data/spec/core/dataset_spec.rb +3827 -0
  165. data/spec/core/expression_filters_spec.rb +595 -0
  166. data/spec/core/object_graph_spec.rb +296 -0
  167. data/spec/core/schema_generator_spec.rb +159 -0
  168. data/spec/core/schema_spec.rb +830 -0
  169. data/spec/core/spec_helper.rb +56 -0
  170. data/spec/core/version_spec.rb +7 -0
  171. data/spec/extensions/active_model_spec.rb +76 -0
  172. data/spec/extensions/association_dependencies_spec.rb +127 -0
  173. data/spec/extensions/association_proxies_spec.rb +50 -0
  174. data/spec/extensions/blank_spec.rb +67 -0
  175. data/spec/extensions/boolean_readers_spec.rb +92 -0
  176. data/spec/extensions/caching_spec.rb +250 -0
  177. data/spec/extensions/class_table_inheritance_spec.rb +252 -0
  178. data/spec/extensions/composition_spec.rb +194 -0
  179. data/spec/extensions/force_encoding_spec.rb +117 -0
  180. data/spec/extensions/hook_class_methods_spec.rb +470 -0
  181. data/spec/extensions/identity_map_spec.rb +202 -0
  182. data/spec/extensions/inflector_spec.rb +181 -0
  183. data/spec/extensions/instance_filters_spec.rb +55 -0
  184. data/spec/extensions/instance_hooks_spec.rb +133 -0
  185. data/spec/extensions/lazy_attributes_spec.rb +153 -0
  186. data/spec/extensions/looser_typecasting_spec.rb +39 -0
  187. data/spec/extensions/many_through_many_spec.rb +884 -0
  188. data/spec/extensions/migration_spec.rb +332 -0
  189. data/spec/extensions/named_timezones_spec.rb +72 -0
  190. data/spec/extensions/nested_attributes_spec.rb +396 -0
  191. data/spec/extensions/optimistic_locking_spec.rb +100 -0
  192. data/spec/extensions/pagination_spec.rb +99 -0
  193. data/spec/extensions/pretty_table_spec.rb +91 -0
  194. data/spec/extensions/query_spec.rb +85 -0
  195. data/spec/extensions/rcte_tree_spec.rb +205 -0
  196. data/spec/extensions/schema_dumper_spec.rb +357 -0
  197. data/spec/extensions/schema_spec.rb +127 -0
  198. data/spec/extensions/serialization_spec.rb +209 -0
  199. data/spec/extensions/single_table_inheritance_spec.rb +96 -0
  200. data/spec/extensions/spec_helper.rb +91 -0
  201. data/spec/extensions/sql_expr_spec.rb +89 -0
  202. data/spec/extensions/string_date_time_spec.rb +93 -0
  203. data/spec/extensions/subclasses_spec.rb +52 -0
  204. data/spec/extensions/tactical_eager_loading_spec.rb +65 -0
  205. data/spec/extensions/thread_local_timezones_spec.rb +45 -0
  206. data/spec/extensions/timestamps_spec.rb +150 -0
  207. data/spec/extensions/touch_spec.rb +155 -0
  208. data/spec/extensions/typecast_on_load_spec.rb +69 -0
  209. data/spec/extensions/validation_class_methods_spec.rb +984 -0
  210. data/spec/extensions/validation_helpers_spec.rb +438 -0
  211. data/spec/integration/associations_test.rb +281 -0
  212. data/spec/integration/database_test.rb +26 -0
  213. data/spec/integration/dataset_test.rb +963 -0
  214. data/spec/integration/eager_loader_test.rb +734 -0
  215. data/spec/integration/model_test.rb +130 -0
  216. data/spec/integration/plugin_test.rb +814 -0
  217. data/spec/integration/prepared_statement_test.rb +213 -0
  218. data/spec/integration/schema_test.rb +361 -0
  219. data/spec/integration/spec_helper.rb +73 -0
  220. data/spec/integration/timezone_test.rb +55 -0
  221. data/spec/integration/transaction_test.rb +122 -0
  222. data/spec/integration/type_test.rb +96 -0
  223. data/spec/model/association_reflection_spec.rb +175 -0
  224. data/spec/model/associations_spec.rb +2633 -0
  225. data/spec/model/base_spec.rb +418 -0
  226. data/spec/model/dataset_methods_spec.rb +78 -0
  227. data/spec/model/eager_loading_spec.rb +1391 -0
  228. data/spec/model/hooks_spec.rb +240 -0
  229. data/spec/model/inflector_spec.rb +26 -0
  230. data/spec/model/model_spec.rb +593 -0
  231. data/spec/model/plugins_spec.rb +236 -0
  232. data/spec/model/record_spec.rb +1500 -0
  233. data/spec/model/spec_helper.rb +97 -0
  234. data/spec/model/validations_spec.rb +153 -0
  235. data/spec/rcov.opts +6 -0
  236. data/spec/spec_config.rb.example +10 -0
  237. metadata +346 -0
@@ -0,0 +1,93 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ context "String#to_time" do
4
+ specify "should convert the string into a Time object" do
5
+ "2007-07-11".to_time.should == Time.parse("2007-07-11")
6
+ "06:30".to_time.should == Time.parse("06:30")
7
+ end
8
+
9
+ specify "should raise InvalidValue for an invalid time" do
10
+ proc {'0000-00-00'.to_time}.should raise_error(Sequel::InvalidValue)
11
+ end
12
+ end
13
+
14
+ context "String#to_date" do
15
+ after do
16
+ Sequel.convert_two_digit_years = true
17
+ end
18
+
19
+ specify "should convert the string into a Date object" do
20
+ "2007-07-11".to_date.should == Date.parse("2007-07-11")
21
+ end
22
+
23
+ specify "should convert 2 digit years by default" do
24
+ "July 11, 07".to_date.should == Date.parse("2007-07-11")
25
+ end
26
+
27
+ specify "should not convert 2 digit years if set not to" do
28
+ Sequel.convert_two_digit_years = false
29
+ "July 11, 07".to_date.should == Date.parse("0007-07-11")
30
+ end
31
+
32
+ specify "should raise InvalidValue for an invalid date" do
33
+ proc {'0000-00-00'.to_date}.should raise_error(Sequel::InvalidValue)
34
+ end
35
+ end
36
+
37
+ context "String#to_datetime" do
38
+ after do
39
+ Sequel.convert_two_digit_years = true
40
+ end
41
+
42
+ specify "should convert the string into a DateTime object" do
43
+ "2007-07-11 10:11:12a".to_datetime.should == DateTime.parse("2007-07-11 10:11:12a")
44
+ end
45
+
46
+ specify "should convert 2 digit years by default" do
47
+ "July 11, 07 10:11:12a".to_datetime.should == DateTime.parse("2007-07-11 10:11:12a")
48
+ end
49
+
50
+ specify "should not convert 2 digit years if set not to" do
51
+ Sequel.convert_two_digit_years = false
52
+ "July 11, 07 10:11:12a".to_datetime.should == DateTime.parse("0007-07-11 10:11:12a")
53
+ end
54
+
55
+ specify "should raise InvalidValue for an invalid date" do
56
+ proc {'0000-00-00'.to_datetime}.should raise_error(Sequel::InvalidValue)
57
+ end
58
+ end
59
+
60
+ context "String#to_sequel_time" do
61
+ after do
62
+ Sequel.datetime_class = Time
63
+ Sequel.convert_two_digit_years = true
64
+ end
65
+
66
+ specify "should convert the string into a Time object by default" do
67
+ "2007-07-11 10:11:12a".to_sequel_time.class.should == Time
68
+ "2007-07-11 10:11:12a".to_sequel_time.should == Time.parse("2007-07-11 10:11:12a")
69
+ end
70
+
71
+ specify "should convert the string into a DateTime object if that is set" do
72
+ Sequel.datetime_class = DateTime
73
+ "2007-07-11 10:11:12a".to_sequel_time.class.should == DateTime
74
+ "2007-07-11 10:11:12a".to_sequel_time.should == DateTime.parse("2007-07-11 10:11:12a")
75
+ end
76
+
77
+ specify "should convert 2 digit years by default if using DateTime class" do
78
+ Sequel.datetime_class = DateTime
79
+ "July 11, 07 10:11:12a".to_sequel_time.should == DateTime.parse("2007-07-11 10:11:12a")
80
+ end
81
+
82
+ specify "should not convert 2 digit years if set not to when using DateTime class" do
83
+ Sequel.datetime_class = DateTime
84
+ Sequel.convert_two_digit_years = false
85
+ "July 11, 07 10:11:12a".to_sequel_time.should == DateTime.parse("0007-07-11 10:11:12a")
86
+ end
87
+
88
+ specify "should raise InvalidValue for an invalid time" do
89
+ proc {'0000-00-00'.to_sequel_time}.should raise_error(Sequel::InvalidValue)
90
+ Sequel.datetime_class = DateTime
91
+ proc {'0000-00-00'.to_sequel_time}.should raise_error(Sequel::InvalidValue)
92
+ end
93
+ end
@@ -0,0 +1,52 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Sequel::Model, "Subclasses plugin" do
4
+ before do
5
+ @c = Class.new(Sequel::Model)
6
+ @c.plugin :subclasses
7
+ end
8
+
9
+ specify "#subclasses should record direct subclasses of the given model" do
10
+ @c.subclasses.should == []
11
+
12
+ sc1 = Class.new(@c)
13
+ @c.subclasses.should == [sc1]
14
+ sc1.subclasses.should == []
15
+
16
+ sc2 = Class.new(@c)
17
+ @c.subclasses.should == [sc1, sc2]
18
+ sc1.subclasses.should == []
19
+ sc2.subclasses.should == []
20
+
21
+ ssc1 = Class.new(sc1)
22
+ @c.subclasses.should == [sc1, sc2]
23
+ sc1.subclasses.should == [ssc1]
24
+ sc2.subclasses.should == []
25
+ end
26
+
27
+ specify "#descendents should record all descendent subclasses of the given model" do
28
+ @c.descendents.should == []
29
+
30
+ sc1 = Class.new(@c)
31
+ @c.descendents.should == [sc1]
32
+ sc1.descendents.should == []
33
+
34
+ sc2 = Class.new(@c)
35
+ @c.descendents.should == [sc1, sc2]
36
+ sc1.descendents.should == []
37
+ sc2.descendents.should == []
38
+
39
+ ssc1 = Class.new(sc1)
40
+ @c.descendents.should == [sc1, ssc1, sc2]
41
+ sc1.descendents.should == [ssc1]
42
+ sc2.descendents.should == []
43
+ ssc1.descendents.should == []
44
+
45
+ sssc1 = Class.new(ssc1)
46
+ @c.descendents.should == [sc1, ssc1, sssc1, sc2]
47
+ sc1.descendents.should == [ssc1, sssc1]
48
+ sc2.descendents.should == []
49
+ ssc1.descendents.should == [sssc1]
50
+ sssc1.descendents.should == []
51
+ end
52
+ end
@@ -0,0 +1,65 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::TacticalEagerLoading" do
4
+ before do
5
+ class ::TaticalEagerLoadingModel < Sequel::Model
6
+ plugin :tactical_eager_loading
7
+ columns :id, :parent_id
8
+ many_to_one :parent, :class=>self
9
+ one_to_many :children, :class=>self, :key=>:parent_id
10
+ ds = dataset
11
+ def ds.fetch_rows(sql)
12
+ execute(sql)
13
+ where = @opts[:where]
14
+ if !where
15
+ yield(:id=>1, :parent_id=>101)
16
+ yield(:id=>2, :parent_id=>102)
17
+ yield(:id=>101, :parent_id=>nil)
18
+ yield(:id=>102, :parent_id=>nil)
19
+ elsif where.args.first.column == :id
20
+ Array(where.args.last).each do |x|
21
+ yield(:id=>x, :parent_id=>nil)
22
+ end
23
+ elsif where.args.first.column == :parent_id
24
+ Array(where.args.last).each do |x|
25
+ yield(:id=>x-100, :parent_id=>x) if x > 100
26
+ end
27
+ end
28
+ end
29
+ end
30
+ @c = ::TaticalEagerLoadingModel
31
+ @ds = TaticalEagerLoadingModel.dataset
32
+ MODEL_DB.reset
33
+ end
34
+ after do
35
+ Object.send(:remove_const, :TaticalEagerLoadingModel)
36
+ end
37
+
38
+ it "Dataset#all should set the retrieved_by and reteived_with attributes" do
39
+ ts = @c.all
40
+ ts.map{|x| [x.retrieved_by, x.retrieved_with]}.should == [[@ds,ts], [@ds,ts], [@ds,ts], [@ds,ts]]
41
+ end
42
+
43
+ it "Dataset#all shouldn't raise an error if a Sequel::Model instance is not returned" do
44
+ proc{@c.naked.all}.should_not raise_error
45
+ end
46
+
47
+ it "association getter methods should eagerly load the association if the association isn't cached" do
48
+ MODEL_DB.sqls.length.should == 0
49
+ ts = @c.all
50
+ MODEL_DB.sqls.length.should == 1
51
+ ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
52
+ MODEL_DB.sqls.length.should == 2
53
+ ts.map{|x| x.children}.should == [[], [], [ts[0]], [ts[1]]]
54
+ MODEL_DB.sqls.length.should == 3
55
+ end
56
+
57
+ it "association getter methods should not eagerly load the association if the association is cached" do
58
+ MODEL_DB.sqls.length.should == 0
59
+ ts = @c.all
60
+ MODEL_DB.sqls.length.should == 1
61
+ ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
62
+ @ds.should_not_receive(:eager_load)
63
+ ts.map{|x| x.parent}.should == [ts[2], ts[3], nil, nil]
64
+ end
65
+ end
@@ -0,0 +1,45 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Sequel thread_local_timezones extension" do
4
+ after do
5
+ Sequel.default_timezone = nil
6
+ Sequel.thread_application_timezone = nil
7
+ Sequel.thread_database_timezone = nil
8
+ Sequel.thread_typecast_timezone = nil
9
+ end
10
+
11
+ it "should allow specifying thread local timezones via thread_*_timezone=" do
12
+ proc{Sequel.thread_application_timezone = :local}.should_not raise_error
13
+ proc{Sequel.thread_database_timezone = :utc}.should_not raise_error
14
+ proc{Sequel.thread_typecast_timezone = nil}.should_not raise_error
15
+ end
16
+
17
+ it "should use thread local timezone if available" do
18
+ Sequel.thread_application_timezone = :local
19
+ Sequel.application_timezone.should == :local
20
+ Sequel.thread_database_timezone = :utc
21
+ Sequel.database_timezone.should == :utc
22
+ Sequel.thread_typecast_timezone = nil
23
+ Sequel.typecast_timezone.should == nil
24
+ end
25
+
26
+ it "should fallback to default timezone if no thread_local timezone" do
27
+ Sequel.default_timezone = :utc
28
+ Sequel.application_timezone.should == :utc
29
+ Sequel.database_timezone.should == :utc
30
+ Sequel.typecast_timezone.should == :utc
31
+ end
32
+
33
+ it "should use a nil thread_local_timezone if set instead of falling back to the default timezone if thread_local_timezone is set to :nil" do
34
+ Sequel.typecast_timezone = :utc
35
+ Sequel.thread_typecast_timezone = nil
36
+ Sequel.typecast_timezone.should == :utc
37
+ Sequel.thread_typecast_timezone = :nil
38
+ Sequel.typecast_timezone.should == nil
39
+ end
40
+
41
+ it "should be thread safe" do
42
+ [Thread.new{Sequel.thread_application_timezone = :utc; sleep 0.03; Sequel.application_timezone.should == :utc},
43
+ Thread.new{sleep 0.01; Sequel.thread_application_timezone = :local; sleep 0.01; Sequel.application_timezone.should == :local}].each{|x| x.join}
44
+ end
45
+ end
@@ -0,0 +1,150 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Sequel::Plugins::Timestamps" do
4
+ before do
5
+ dc = Object.new
6
+ dc.instance_eval do
7
+ def now
8
+ '2009-08-01'
9
+ end
10
+ end
11
+ Sequel.datetime_class = dc
12
+ @c = Class.new(Sequel::Model(:t))
13
+ @c.class_eval do
14
+ columns :id, :created_at, :updated_at
15
+ plugin :timestamps
16
+ db.reset
17
+ def _refresh(ds); self end
18
+ end
19
+ end
20
+ after do
21
+ Sequel.datetime_class = Time
22
+ end
23
+
24
+ it "should set the create timestamp field on creation" do
25
+ o = @c.create
26
+ @c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
27
+ o.created_at.should == '2009-08-01'
28
+ end
29
+
30
+ it "should set the update timestamp field on update" do
31
+ o = @c.load(:id=>1).save
32
+ @c.db.sqls.should == ["UPDATE t SET updated_at = '2009-08-01' WHERE (id = 1)"]
33
+ o.updated_at.should == '2009-08-01'
34
+ end
35
+
36
+ it "should not update the update timestamp on creation" do
37
+ @c.create.updated_at.should == nil
38
+ end
39
+
40
+ it "should use the same value for the creation and update timestamps when creating if the :update_on_create option is given" do
41
+ @c.plugin :timestamps, :update_on_create=>true
42
+ o = @c.create
43
+ @c.db.sqls.length.should == 1
44
+ @c.db.sqls.first.should =~ /INSERT INTO t \((creat|updat)ed_at, (creat|updat)ed_at\) VALUES \('2009-08-01', '2009-08-01'\)/
45
+ o.created_at.should === o.updated_at
46
+ end
47
+
48
+ it "should allow specifying the create timestamp field via the :create option" do
49
+ c = Class.new(Sequel::Model(:t))
50
+ c.class_eval do
51
+ columns :id, :c
52
+ plugin :timestamps, :create=>:c
53
+ db.reset
54
+ def _refresh(ds); self end
55
+ end
56
+ o = c.create
57
+ c.db.sqls.should == ["INSERT INTO t (c) VALUES ('2009-08-01')"]
58
+ o.c.should == '2009-08-01'
59
+ end
60
+
61
+ it "should allow specifying the update timestamp field via the :update option" do
62
+ c = Class.new(Sequel::Model(:t))
63
+ c.class_eval do
64
+ columns :id, :u
65
+ plugin :timestamps, :update=>:u
66
+ db.reset
67
+ def _refresh(ds); self end
68
+ end
69
+ o = c.load(:id=>1).save
70
+ c.db.sqls.should == ["UPDATE t SET u = '2009-08-01' WHERE (id = 1)"]
71
+ o.u.should == '2009-08-01'
72
+ end
73
+
74
+ it "should not raise an error if the model doesn't have the timestamp columns" do
75
+ c = Class.new(Sequel::Model(:t))
76
+ c.class_eval do
77
+ columns :id, :x
78
+ plugin :timestamps
79
+ db.reset
80
+ def _refresh(ds); self end
81
+ end
82
+ c.create(:x=>2)
83
+ c.load(:id=>1, :x=>2).save
84
+ c.db.sqls.should == ["INSERT INTO t (x) VALUES (2)", "UPDATE t SET x = 2 WHERE (id = 1)"]
85
+ end
86
+
87
+ it "should not overwrite an existing create timestamp" do
88
+ o = @c.create(:created_at=>'2009-08-03')
89
+ @c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-03')"]
90
+ o.created_at.should == '2009-08-03'
91
+ end
92
+
93
+ it "should overwrite an existing create timestamp if the :force option is used" do
94
+ @c.plugin :timestamps, :force=>true
95
+ o = @c.create(:created_at=>'2009-08-03')
96
+ @c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')"]
97
+ o.created_at.should == '2009-08-01'
98
+ end
99
+
100
+ it "should have create_timestamp_field give the create timestamp field" do
101
+ @c.create_timestamp_field.should == :created_at
102
+ @c.plugin :timestamps, :create=>:c
103
+ @c.create_timestamp_field.should == :c
104
+ end
105
+
106
+ it "should have update_timestamp_field give the update timestamp field" do
107
+ @c.update_timestamp_field.should == :updated_at
108
+ @c.plugin :timestamps, :update=>:u
109
+ @c.update_timestamp_field.should == :u
110
+ end
111
+
112
+ it "should have create_timestamp_overwrite? give the whether to overwrite an existing create timestamp" do
113
+ @c.create_timestamp_overwrite?.should == false
114
+ @c.plugin :timestamps, :force=>true
115
+ @c.create_timestamp_overwrite?.should == true
116
+ end
117
+
118
+ it "should have set_update_timestamp_on_create? give whether to set the update timestamp on create" do
119
+ @c.set_update_timestamp_on_create?.should == false
120
+ @c.plugin :timestamps, :update_on_create=>true
121
+ @c.set_update_timestamp_on_create?.should == true
122
+ end
123
+
124
+ it "should work with subclasses" do
125
+ c = Class.new(@c)
126
+ o = c.create
127
+ o.created_at.should == '2009-08-01'
128
+ o.updated_at.should == nil
129
+ o = c.load(:id=>1).save
130
+ o.updated_at.should == '2009-08-01'
131
+ c.db.sqls.should == ["INSERT INTO t (created_at) VALUES ('2009-08-01')", "UPDATE t SET updated_at = '2009-08-01' WHERE (id = 1)"]
132
+ c.create(:created_at=>'2009-08-03').created_at.should == '2009-08-03'
133
+
134
+ c.class_eval do
135
+ columns :id, :c, :u
136
+ plugin :timestamps, :create=>:c, :update=>:u, :force=>true, :update_on_create=>true
137
+ end
138
+ c2 = Class.new(c)
139
+ c2.db.reset
140
+ o = c2.create
141
+ o.c.should == '2009-08-01'
142
+ o.u.should === o.c
143
+ c2.db.sqls.first.should =~ /INSERT INTO t \([cu], [cu]\) VALUES \('2009-08-01', '2009-08-01'\)/
144
+ c2.db.reset
145
+ o = c2.load(:id=>1).save
146
+ o.u.should == '2009-08-01'
147
+ c2.db.sqls.should == ["UPDATE t SET u = '2009-08-01' WHERE (id = 1)"]
148
+ c2.create(:c=>'2009-08-03').c.should == '2009-08-01'
149
+ end
150
+ end
@@ -0,0 +1,155 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Touch plugin" do
4
+ before do
5
+ @c = Class.new(Sequel::Model) do
6
+ def _refresh(*); end
7
+ end
8
+ p = proc{def touch_instance_value; touch_association_value; end}
9
+ @Artist = Class.new(@c, &p).set_dataset(:artists)
10
+ @Album = Class.new(@c, &p).set_dataset(:albums)
11
+
12
+ @Artist.columns :id, :updated_at, :modified_on
13
+ @Artist.one_to_many :albums, :class=>@Album, :key=>:artist_id
14
+
15
+ @Album.columns :id, :updated_at, :modified_on, :artist_id, :original_album_id
16
+ @Album.one_to_many :followup_albums, :class=>@Album, :key=>:original_album_id
17
+ @Album.many_to_one :artist, :class=>@Artist
18
+
19
+ @a = @Artist.load(:id=>1)
20
+ MODEL_DB.reset
21
+ end
22
+
23
+ specify "should default to using Time.now when setting the column values for model instances" do
24
+ c = Class.new(Sequel::Model).set_dataset(:a)
25
+ c.plugin :touch
26
+ c.columns :id, :updated_at
27
+ c.load(:id=>1).touch
28
+ MODEL_DB.sqls.first.should =~ /UPDATE a SET updated_at = '[-0-9 :.]+' WHERE \(id = 1\)/
29
+ end
30
+
31
+ specify "should allow #touch instance method for updating the updated_at column" do
32
+ @Artist.plugin :touch
33
+ @a.touch
34
+ MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
35
+ end
36
+
37
+ specify "should have #touch take an argument for the column to touch" do
38
+ @Artist.plugin :touch
39
+ @a.touch(:modified_on)
40
+ MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)"]
41
+ end
42
+
43
+ specify "should be able to specify the default column to touch in the plugin call using the :column option" do
44
+ @Artist.plugin :touch, :column=>:modified_on
45
+ @a.touch
46
+ MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)"]
47
+ end
48
+
49
+ specify "should be able to specify the default column to touch using the touch_column model accessor" do
50
+ @Artist.plugin :touch
51
+ @Artist.touch_column = :modified_on
52
+ @a.touch
53
+ MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)"]
54
+ end
55
+
56
+ specify "should be able to specify the associations to touch in the plugin call using the :associations option" do
57
+ @Artist.plugin :touch, :associations=>:albums
58
+ @a.touch
59
+ MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
60
+ "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
61
+ end
62
+
63
+ specify "should be able to give an array to the :associations option specifying multiple associations" do
64
+ @Album.plugin :touch, :associations=>[:artist, :followup_albums]
65
+ @Album.load(:id=>4, :artist_id=>1).touch
66
+ MODEL_DB.sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
67
+ MODEL_DB.sqls.sort.should == ["UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
68
+ "UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
69
+ end
70
+
71
+ specify "should be able to give a hash to the :associations option specifying the column to use for each association" do
72
+ @Artist.plugin :touch, :associations=>{:albums=>:modified_on}
73
+ @a.touch
74
+ MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
75
+ "UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
76
+ end
77
+
78
+ specify "should default to using the touch_column as the default touch column for associations" do
79
+ @Artist.plugin :touch, :column=>:modified_on, :associations=>:albums
80
+ @a.touch
81
+ MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)",
82
+ "UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
83
+ end
84
+
85
+ specify "should allow the mixed use of symbols and hashes inside an array for the :associations option" do
86
+ @Album.plugin :touch, :associations=>[:artist, {:followup_albums=>:modified_on}]
87
+ @Album.load(:id=>4, :artist_id=>1).touch
88
+ MODEL_DB.sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
89
+ MODEL_DB.sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
90
+ "UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
91
+ end
92
+
93
+ specify "should be able to specify the associations to touch via a touch_associations_method" do
94
+ @Album.plugin :touch
95
+ @Album.touch_associations(:artist, {:followup_albums=>:modified_on})
96
+ @Album.load(:id=>4, :artist_id=>1).touch
97
+ MODEL_DB.sqls.shift.should == "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"
98
+ MODEL_DB.sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
99
+ "UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
100
+ end
101
+
102
+ specify "should touch associated objects when destroying an object" do
103
+ @Album.plugin :touch
104
+ @Album.touch_associations(:artist, {:followup_albums=>:modified_on})
105
+ @Album.load(:id=>4, :artist_id=>1).destroy
106
+ MODEL_DB.sqls.shift.should == "DELETE FROM albums WHERE (id = 4)"
107
+ MODEL_DB.sqls.sort.should == ["UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.original_album_id = 4)",
108
+ "UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (artists.id = 1)"]
109
+ end
110
+
111
+ specify "should not update a column that doesn't exist" do
112
+ @Album.plugin :touch, :column=>:x
113
+ a = @Album.load(:id=>1)
114
+ a.touch
115
+ MODEL_DB.sqls.should == []
116
+ a.artist_id = 1
117
+ a.touch
118
+ MODEL_DB.sqls.should == ['UPDATE albums SET artist_id = 1 WHERE (id = 1)']
119
+ end
120
+
121
+ specify "should raise an error if given a column argument in touch that doesn't exist" do
122
+ @Artist.plugin :touch
123
+ proc{@a.touch(:x)}.should raise_error(Sequel::Error)
124
+ end
125
+
126
+ specify "should raise an Error when a nonexistent association is given" do
127
+ @Artist.plugin :touch
128
+ proc{@Artist.plugin :touch, :associations=>:blah}.should raise_error(Sequel::Error)
129
+ end
130
+
131
+ specify "should work correctly in subclasses" do
132
+ @Artist.plugin :touch
133
+ c1 = Class.new(@Artist)
134
+ c1.load(:id=>4).touch
135
+ MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 4)"]
136
+ MODEL_DB.reset
137
+
138
+ c1.touch_column = :modified_on
139
+ c1.touch_associations :albums
140
+ c1.load(:id=>1).touch
141
+ MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 1)",
142
+ "UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
143
+ MODEL_DB.reset
144
+
145
+ @a.touch
146
+ MODEL_DB.sqls.should == ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)"]
147
+ MODEL_DB.reset
148
+
149
+ @Artist.plugin :touch, :column=>:modified_on, :associations=>:albums
150
+ c2 = Class.new(@Artist)
151
+ c2.load(:id=>4).touch
152
+ MODEL_DB.sqls.should == ["UPDATE artists SET modified_on = CURRENT_TIMESTAMP WHERE (id = 4)",
153
+ "UPDATE albums SET modified_on = CURRENT_TIMESTAMP WHERE (albums.artist_id = 4)"]
154
+ end
155
+ end