sequel 3.47.0 → 3.48.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 (243) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +230 -0
  3. data/README.rdoc +31 -40
  4. data/Rakefile +1 -14
  5. data/doc/active_record.rdoc +29 -29
  6. data/doc/association_basics.rdoc +4 -13
  7. data/doc/cheat_sheet.rdoc +8 -6
  8. data/doc/code_order.rdoc +89 -0
  9. data/doc/core_extensions.rdoc +3 -3
  10. data/doc/dataset_basics.rdoc +7 -8
  11. data/doc/dataset_filtering.rdoc +7 -2
  12. data/doc/mass_assignment.rdoc +2 -3
  13. data/doc/migration.rdoc +8 -8
  14. data/doc/model_hooks.rdoc +11 -7
  15. data/doc/object_model.rdoc +2 -2
  16. data/doc/opening_databases.rdoc +5 -14
  17. data/doc/prepared_statements.rdoc +5 -9
  18. data/doc/querying.rdoc +23 -28
  19. data/doc/reflection.rdoc +11 -0
  20. data/doc/release_notes/3.48.0.txt +477 -0
  21. data/doc/schema_modification.rdoc +12 -5
  22. data/doc/security.rdoc +2 -2
  23. data/doc/sharding.rdoc +1 -2
  24. data/doc/sql.rdoc +10 -13
  25. data/doc/testing.rdoc +8 -4
  26. data/doc/transactions.rdoc +2 -2
  27. data/doc/validations.rdoc +40 -17
  28. data/doc/virtual_rows.rdoc +2 -2
  29. data/lib/sequel/adapters/ado.rb +25 -20
  30. data/lib/sequel/adapters/ado/access.rb +1 -0
  31. data/lib/sequel/adapters/ado/mssql.rb +1 -0
  32. data/lib/sequel/adapters/db2.rb +9 -7
  33. data/lib/sequel/adapters/dbi.rb +16 -16
  34. data/lib/sequel/adapters/do.rb +17 -18
  35. data/lib/sequel/adapters/do/mysql.rb +1 -0
  36. data/lib/sequel/adapters/do/postgres.rb +2 -0
  37. data/lib/sequel/adapters/do/sqlite.rb +1 -0
  38. data/lib/sequel/adapters/firebird.rb +5 -7
  39. data/lib/sequel/adapters/ibmdb.rb +23 -20
  40. data/lib/sequel/adapters/informix.rb +8 -2
  41. data/lib/sequel/adapters/jdbc.rb +39 -35
  42. data/lib/sequel/adapters/jdbc/as400.rb +1 -0
  43. data/lib/sequel/adapters/jdbc/cubrid.rb +1 -0
  44. data/lib/sequel/adapters/jdbc/db2.rb +1 -0
  45. data/lib/sequel/adapters/jdbc/derby.rb +1 -0
  46. data/lib/sequel/adapters/jdbc/firebird.rb +1 -0
  47. data/lib/sequel/adapters/jdbc/h2.rb +1 -0
  48. data/lib/sequel/adapters/jdbc/hsqldb.rb +1 -0
  49. data/lib/sequel/adapters/jdbc/informix.rb +1 -0
  50. data/lib/sequel/adapters/jdbc/jtds.rb +1 -0
  51. data/lib/sequel/adapters/jdbc/mssql.rb +1 -0
  52. data/lib/sequel/adapters/jdbc/mysql.rb +1 -0
  53. data/lib/sequel/adapters/jdbc/oracle.rb +1 -0
  54. data/lib/sequel/adapters/jdbc/postgresql.rb +2 -0
  55. data/lib/sequel/adapters/jdbc/progress.rb +1 -0
  56. data/lib/sequel/adapters/jdbc/sqlite.rb +1 -0
  57. data/lib/sequel/adapters/jdbc/sqlserver.rb +1 -0
  58. data/lib/sequel/adapters/mock.rb +30 -31
  59. data/lib/sequel/adapters/mysql.rb +6 -7
  60. data/lib/sequel/adapters/mysql2.rb +5 -6
  61. data/lib/sequel/adapters/odbc.rb +22 -20
  62. data/lib/sequel/adapters/odbc/mssql.rb +1 -0
  63. data/lib/sequel/adapters/openbase.rb +4 -1
  64. data/lib/sequel/adapters/oracle.rb +10 -8
  65. data/lib/sequel/adapters/postgres.rb +12 -10
  66. data/lib/sequel/adapters/shared/access.rb +6 -0
  67. data/lib/sequel/adapters/shared/cubrid.rb +2 -0
  68. data/lib/sequel/adapters/shared/db2.rb +2 -0
  69. data/lib/sequel/adapters/shared/firebird.rb +2 -0
  70. data/lib/sequel/adapters/shared/informix.rb +2 -0
  71. data/lib/sequel/adapters/shared/mssql.rb +14 -8
  72. data/lib/sequel/adapters/shared/mysql.rb +6 -0
  73. data/lib/sequel/adapters/shared/oracle.rb +2 -0
  74. data/lib/sequel/adapters/shared/postgres.rb +14 -4
  75. data/lib/sequel/adapters/shared/progress.rb +1 -0
  76. data/lib/sequel/adapters/shared/sqlite.rb +4 -3
  77. data/lib/sequel/adapters/sqlite.rb +6 -7
  78. data/lib/sequel/adapters/swift.rb +20 -21
  79. data/lib/sequel/adapters/swift/mysql.rb +1 -0
  80. data/lib/sequel/adapters/swift/postgres.rb +2 -0
  81. data/lib/sequel/adapters/swift/sqlite.rb +1 -0
  82. data/lib/sequel/adapters/tinytds.rb +5 -6
  83. data/lib/sequel/adapters/utils/emulate_offset_with_reverse_and_count.rb +68 -0
  84. data/lib/sequel/connection_pool.rb +1 -1
  85. data/lib/sequel/core.rb +57 -50
  86. data/lib/sequel/database/connecting.rb +9 -10
  87. data/lib/sequel/database/dataset.rb +11 -6
  88. data/lib/sequel/database/dataset_defaults.rb +61 -69
  89. data/lib/sequel/database/features.rb +21 -0
  90. data/lib/sequel/database/misc.rb +23 -3
  91. data/lib/sequel/database/query.rb +13 -7
  92. data/lib/sequel/database/schema_methods.rb +6 -6
  93. data/lib/sequel/database/transactions.rb +1 -0
  94. data/lib/sequel/dataset/actions.rb +51 -38
  95. data/lib/sequel/dataset/features.rb +1 -0
  96. data/lib/sequel/dataset/graph.rb +9 -33
  97. data/lib/sequel/dataset/misc.rb +30 -5
  98. data/lib/sequel/dataset/mutation.rb +2 -3
  99. data/lib/sequel/dataset/prepared_statements.rb +1 -1
  100. data/lib/sequel/dataset/query.rb +91 -27
  101. data/lib/sequel/dataset/sql.rb +40 -6
  102. data/lib/sequel/deprecated.rb +74 -0
  103. data/lib/sequel/deprecated_core_extensions.rb +135 -0
  104. data/lib/sequel/extensions/columns_introspection.rb +1 -5
  105. data/lib/sequel/extensions/core_extensions.rb +10 -3
  106. data/lib/sequel/extensions/date_arithmetic.rb +1 -0
  107. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +33 -0
  108. data/lib/sequel/extensions/filter_having.rb +58 -0
  109. data/lib/sequel/extensions/graph_each.rb +63 -0
  110. data/lib/sequel/extensions/hash_aliases.rb +44 -0
  111. data/lib/sequel/extensions/looser_typecasting.rb +14 -3
  112. data/lib/sequel/extensions/migration.rb +2 -3
  113. data/lib/sequel/extensions/named_timezones.rb +14 -1
  114. data/lib/sequel/extensions/null_dataset.rb +7 -1
  115. data/lib/sequel/extensions/pagination.rb +15 -5
  116. data/lib/sequel/extensions/pg_auto_parameterize.rb +1 -0
  117. data/lib/sequel/extensions/pg_hstore_ops.rb +48 -14
  118. data/lib/sequel/extensions/pg_json.rb +7 -7
  119. data/lib/sequel/extensions/pg_range_ops.rb +8 -2
  120. data/lib/sequel/extensions/pg_statement_cache.rb +1 -0
  121. data/lib/sequel/extensions/pretty_table.rb +13 -4
  122. data/lib/sequel/extensions/query.rb +21 -4
  123. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +22 -0
  124. data/lib/sequel/extensions/schema_caching.rb +10 -7
  125. data/lib/sequel/extensions/schema_dumper.rb +35 -48
  126. data/lib/sequel/extensions/select_remove.rb +13 -4
  127. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +117 -0
  128. data/lib/sequel/extensions/set_overrides.rb +43 -0
  129. data/lib/sequel/extensions/to_dot.rb +6 -0
  130. data/lib/sequel/model.rb +12 -6
  131. data/lib/sequel/model/associations.rb +80 -38
  132. data/lib/sequel/model/base.rb +137 -52
  133. data/lib/sequel/model/errors.rb +7 -2
  134. data/lib/sequel/plugins/active_model.rb +13 -0
  135. data/lib/sequel/plugins/after_initialize.rb +43 -0
  136. data/lib/sequel/plugins/association_proxies.rb +63 -7
  137. data/lib/sequel/plugins/auto_validations.rb +56 -16
  138. data/lib/sequel/plugins/blacklist_security.rb +63 -0
  139. data/lib/sequel/plugins/class_table_inheritance.rb +9 -0
  140. data/lib/sequel/plugins/constraint_validations.rb +50 -8
  141. data/lib/sequel/plugins/dataset_associations.rb +2 -0
  142. data/lib/sequel/plugins/hook_class_methods.rb +7 -1
  143. data/lib/sequel/plugins/identity_map.rb +4 -0
  144. data/lib/sequel/plugins/json_serializer.rb +32 -13
  145. data/lib/sequel/plugins/optimistic_locking.rb +1 -1
  146. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  147. data/lib/sequel/plugins/scissors.rb +33 -0
  148. data/lib/sequel/plugins/serialization.rb +1 -1
  149. data/lib/sequel/plugins/single_table_inheritance.rb +6 -0
  150. data/lib/sequel/plugins/tree.rb +5 -1
  151. data/lib/sequel/plugins/validation_class_methods.rb +2 -1
  152. data/lib/sequel/plugins/validation_helpers.rb +15 -11
  153. data/lib/sequel/plugins/xml_serializer.rb +12 -3
  154. data/lib/sequel/sql.rb +12 -2
  155. data/lib/sequel/timezones.rb +1 -1
  156. data/lib/sequel/version.rb +1 -1
  157. data/lib/sequel_core.rb +1 -0
  158. data/lib/sequel_model.rb +1 -0
  159. data/spec/adapters/mssql_spec.rb +24 -57
  160. data/spec/adapters/postgres_spec.rb +27 -55
  161. data/spec/adapters/spec_helper.rb +1 -1
  162. data/spec/adapters/sqlite_spec.rb +1 -1
  163. data/spec/bin_spec.rb +251 -0
  164. data/spec/core/database_spec.rb +46 -32
  165. data/spec/core/dataset_spec.rb +233 -181
  166. data/spec/core/deprecated_spec.rb +78 -0
  167. data/spec/core/expression_filters_spec.rb +3 -4
  168. data/spec/core/mock_adapter_spec.rb +9 -9
  169. data/spec/core/object_graph_spec.rb +9 -19
  170. data/spec/core/schema_spec.rb +3 -1
  171. data/spec/core/spec_helper.rb +19 -0
  172. data/spec/core_extensions_spec.rb +80 -30
  173. data/spec/extensions/after_initialize_spec.rb +24 -0
  174. data/spec/extensions/association_proxies_spec.rb +37 -1
  175. data/spec/extensions/auto_validations_spec.rb +20 -4
  176. data/spec/extensions/blacklist_security_spec.rb +87 -0
  177. data/spec/extensions/boolean_readers_spec.rb +2 -1
  178. data/spec/extensions/class_table_inheritance_spec.rb +7 -0
  179. data/spec/extensions/columns_introspection_spec.rb +3 -3
  180. data/spec/extensions/constraint_validations_plugin_spec.rb +83 -5
  181. data/spec/extensions/core_refinements_spec.rb +7 -7
  182. data/spec/extensions/dataset_associations_spec.rb +2 -2
  183. data/spec/extensions/date_arithmetic_spec.rb +1 -1
  184. data/spec/extensions/defaults_setter_spec.rb +2 -1
  185. data/spec/extensions/empty_array_ignore_nulls_spec.rb +24 -0
  186. data/spec/extensions/filter_having_spec.rb +40 -0
  187. data/spec/extensions/graph_each_spec.rb +109 -0
  188. data/spec/extensions/hash_aliases_spec.rb +16 -0
  189. data/spec/extensions/hook_class_methods_spec.rb +2 -2
  190. data/spec/extensions/identity_map_spec.rb +3 -3
  191. data/spec/extensions/json_serializer_spec.rb +19 -19
  192. data/spec/extensions/lazy_attributes_spec.rb +1 -0
  193. data/spec/extensions/list_spec.rb +13 -13
  194. data/spec/extensions/looser_typecasting_spec.rb +10 -3
  195. data/spec/extensions/many_through_many_spec.rb +1 -1
  196. data/spec/extensions/migration_spec.rb +7 -7
  197. data/spec/extensions/named_timezones_spec.rb +6 -0
  198. data/spec/extensions/nested_attributes_spec.rb +2 -2
  199. data/spec/extensions/null_dataset_spec.rb +1 -1
  200. data/spec/extensions/pagination_spec.rb +2 -2
  201. data/spec/extensions/pg_hstore_ops_spec.rb +75 -0
  202. data/spec/extensions/pg_range_ops_spec.rb +4 -2
  203. data/spec/extensions/pg_row_plugin_spec.rb +1 -1
  204. data/spec/extensions/pretty_table_spec.rb +1 -1
  205. data/spec/extensions/query_literals_spec.rb +1 -1
  206. data/spec/extensions/query_spec.rb +3 -3
  207. data/spec/extensions/schema_caching_spec.rb +3 -3
  208. data/spec/extensions/schema_dumper_spec.rb +27 -2
  209. data/spec/extensions/schema_spec.rb +2 -2
  210. data/spec/extensions/scissors_spec.rb +26 -0
  211. data/spec/extensions/select_remove_spec.rb +1 -1
  212. data/spec/extensions/sequel_3_dataset_methods_spec.rb +102 -0
  213. data/spec/extensions/set_overrides_spec.rb +45 -0
  214. data/spec/extensions/single_table_inheritance_spec.rb +10 -0
  215. data/spec/extensions/spec_helper.rb +24 -1
  216. data/spec/extensions/static_cache_spec.rb +1 -1
  217. data/spec/extensions/string_stripper_spec.rb +2 -1
  218. data/spec/extensions/to_dot_spec.rb +1 -1
  219. data/spec/extensions/typecast_on_load_spec.rb +3 -2
  220. data/spec/extensions/update_primary_key_spec.rb +2 -2
  221. data/spec/extensions/validation_class_methods_spec.rb +19 -19
  222. data/spec/extensions/validation_helpers_spec.rb +30 -21
  223. data/spec/extensions/xml_serializer_spec.rb +5 -5
  224. data/spec/integration/associations_test.rb +10 -30
  225. data/spec/integration/dataset_test.rb +20 -24
  226. data/spec/integration/eager_loader_test.rb +5 -5
  227. data/spec/integration/model_test.rb +3 -3
  228. data/spec/integration/plugin_test.rb +7 -39
  229. data/spec/integration/schema_test.rb +4 -38
  230. data/spec/integration/spec_helper.rb +2 -1
  231. data/spec/model/association_reflection_spec.rb +70 -5
  232. data/spec/model/associations_spec.rb +11 -11
  233. data/spec/model/base_spec.rb +25 -8
  234. data/spec/model/class_dataset_methods_spec.rb +143 -0
  235. data/spec/model/dataset_methods_spec.rb +1 -1
  236. data/spec/model/eager_loading_spec.rb +25 -25
  237. data/spec/model/hooks_spec.rb +1 -1
  238. data/spec/model/model_spec.rb +22 -7
  239. data/spec/model/plugins_spec.rb +1 -6
  240. data/spec/model/record_spec.rb +37 -29
  241. data/spec/model/spec_helper.rb +23 -1
  242. data/spec/model/validations_spec.rb +15 -17
  243. metadata +32 -3
@@ -76,7 +76,7 @@ describe "Sequel::Plugins::StaticCache" do
76
76
  @db.fetch = [[{:count=>1}], [{:count=>2}]]
77
77
  @c.count(:a).should == 1
78
78
  @c.count{b}.should == 2
79
- @db.sqls.should == ["SELECT COUNT(a) AS count FROM t LIMIT 1", "SELECT COUNT(b) AS count FROM t LIMIT 1"]
79
+ @db.sqls.should == ["SELECT count(a) AS count FROM t LIMIT 1", "SELECT count(b) AS count FROM t LIMIT 1"]
80
80
  end
81
81
 
82
82
  it "should have map not send a query if given an argument" do
@@ -2,7 +2,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Sequel::Plugins::StringStripper" do
4
4
  before do
5
- @db = Sequel::Database.new
5
+ @db = Sequel.mock
6
6
  @c = Class.new(Sequel::Model(@db[:test]))
7
7
  @c.columns :name, :b
8
8
  @c.db_schema[:b][:type] = :blob
@@ -53,6 +53,7 @@ describe "Sequel::Plugins::StringStripper" do
53
53
  it "should work correctly for dataset changes" do
54
54
  c = Class.new(Sequel::Model(@db[:test]))
55
55
  c.plugin :string_stripper
56
+ def @db.supports_schema_parsing?() true end
56
57
  def @db.schema(*) [[:name, {}], [:b, {:type=>:blob}]] end
57
58
  c.set_dataset(@db[:test2])
58
59
  o = c.new
@@ -11,7 +11,7 @@ describe Sequel::Model, "to_dot extension" do
11
11
  end
12
12
 
13
13
  it "should output a string suitable for input to the graphviz dot program" do
14
- @ds.to_dot.should == (<<END).strip
14
+ @ds.extension(:to_dot).to_dot.should == (<<END).strip
15
15
  digraph G {
16
16
  0 [label="self"];
17
17
  0 -> 1 [label=""];
@@ -3,6 +3,7 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
3
3
  describe Sequel::Model, "TypecastOnLoad plugin" do
4
4
  before do
5
5
  @db = Sequel.mock(:fetch=>{:id=>1, :b=>"1", :y=>"0"}, :columns=>[:id, :b, :y], :numrows=>1)
6
+ def @db.supports_schema_parsing?() true end
6
7
  def @db.schema(*args)
7
8
  [[:id, {}], [:y, {:type=>:boolean, :db_type=>'tinyint(1)'}], [:b, {:type=>:integer, :db_type=>'integer'}]]
8
9
  end
@@ -24,7 +25,7 @@ describe Sequel::Model, "TypecastOnLoad plugin" do
24
25
 
25
26
  specify "should call setter method with value when reloading the object, for all given columns" do
26
27
  @c.plugin :typecast_on_load, :b
27
- o = @c.new({:id=>1, :b=>"1", :y=>"0"}, true)
28
+ o = @c.load(:id=>1, :b=>"1", :y=>"0")
28
29
  o.refresh
29
30
  o.values.should == {:id=>1, :b=>1, :y=>"0"}
30
31
  o.bset.should == true
@@ -33,7 +34,7 @@ describe Sequel::Model, "TypecastOnLoad plugin" do
33
34
  specify "should call setter method with value when automatically reloading the object on creation via insert_select" do
34
35
  @c.plugin :typecast_on_load, :b
35
36
  @c.dataset.meta_def(:insert_select){|h| insert(h); first}
36
- o = @c.new({:id=>1, :b=>"1", :y=>"0"}, true)
37
+ o = @c.load(:id=>1, :b=>"1", :y=>"0")
37
38
  o.save.values.should == {:id=>1, :b=>1, :y=>"0"}
38
39
  o.bset.should == true
39
40
  end
@@ -19,7 +19,7 @@ describe "Sequel::Plugins::UpdatePrimaryKey" do
19
19
  @c.first.set(:b=>5).save
20
20
  @c.all.should == [@c.load(:a=>1, :b=>5)]
21
21
  MODEL_DB.sqls.should == ["SELECT * FROM a LIMIT 1", "UPDATE a SET b = 5 WHERE (a = 1)", "SELECT * FROM a"]
22
- @c.first.set(:b=>6).save(:b)
22
+ @c.first.set(:b=>6).save(:columns=>:b)
23
23
  @c.all.should == [@c.load(:a=>1, :b=>6)]
24
24
  MODEL_DB.sqls.should == ["SELECT * FROM a LIMIT 1", "UPDATE a SET b = 6 WHERE (a = 1)", "SELECT * FROM a"]
25
25
  end
@@ -38,7 +38,7 @@ describe "Sequel::Plugins::UpdatePrimaryKey" do
38
38
  @c.first.update(:a=>2)
39
39
  @c.all.should == [@c.load(:a=>2, :b=>3)]
40
40
  MODEL_DB.sqls.should == ["SELECT * FROM a LIMIT 1", "UPDATE a SET a = 2 WHERE (a = 1)", "SELECT * FROM a"]
41
- @c.first.set(:a=>3).save(:a)
41
+ @c.first.set(:a=>3).save(:columns=>:a)
42
42
  @c.all.should == [@c.load(:a=>3, :b=>3)]
43
43
  MODEL_DB.sqls.should == ["SELECT * FROM a LIMIT 1", "UPDATE a SET a = 3 WHERE (a = 2)", "SELECT * FROM a"]
44
44
  end
@@ -11,7 +11,7 @@ describe Sequel::Model do
11
11
  before do
12
12
  @c = model_class.call Sequel::Model do
13
13
  def self.validates_coolness_of(attr)
14
- validates_each(attr) {|o, a, v| o.errors[a] << 'is not cool' if v != :cool}
14
+ validates_each(attr) {|o, a, v| o.errors.add(a, 'is not cool') if v != :cool}
15
15
  end
16
16
  end
17
17
  end
@@ -41,7 +41,7 @@ describe Sequel::Model do
41
41
  end
42
42
 
43
43
  specify "should acccept validation definitions using validates_each" do
44
- @c.validates_each(:xx, :yy) {|o, a, v| o.errors[a] << 'too low' if v < 50}
44
+ @c.validates_each(:xx, :yy) {|o, a, v| o.errors.add(a, 'too low') if v < 50}
45
45
  o = @c.new
46
46
  o.should_receive(:xx).once.and_return(40)
47
47
  o.should_receive(:yy).once.and_return(60)
@@ -105,8 +105,8 @@ describe Sequel::Model do
105
105
  end
106
106
 
107
107
  specify "should overwrite existing validation with the same tag and attribute" do
108
- @c.validates_each(:xx, :xx, :tag=>:low) {|o, a, v| o.xxx; o.errors[a] << 'too low' if v < 50}
109
- @c.validates_each(:yy, :yy) {|o, a, v| o.yyy; o.errors[a] << 'too low' if v < 50}
108
+ @c.validates_each(:xx, :xx, :tag=>:low) {|o, a, v| o.xxx; o.errors.add(a, 'too low') if v < 50}
109
+ @c.validates_each(:yy, :yy) {|o, a, v| o.yyy; o.errors.add(a, 'too low') if v < 50}
110
110
  @c.validates_presence_of(:zz, :zz)
111
111
  @c.validates_length_of(:aa, :aa, :tag=>:blah)
112
112
  o = @c.new
@@ -153,7 +153,7 @@ describe Sequel::Model do
153
153
  @c = model_class.call Sequel::Model do
154
154
  columns :score
155
155
  validates_each :score do |o, a, v|
156
- o.errors[a] << 'too low' if v < 87
156
+ o.errors.add(a, 'too low') if v < 87
157
157
  end
158
158
  end
159
159
 
@@ -175,17 +175,17 @@ describe Sequel::Model do
175
175
  @o.score = 86
176
176
  @o.should_not be_valid
177
177
  @o.errors[:score].should == ['too low']
178
- @o.errors[:blah].should be_empty
178
+ @o.errors.on(:blah).should be_nil
179
179
  end
180
180
  end
181
181
 
182
182
  describe "Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator" do
183
183
  before do
184
- $testit = nil
184
+ @testit = testit = []
185
185
 
186
186
  @c = model_class.call Sequel::Model do
187
- def self.validates_blah
188
- $testit = 1324
187
+ (class << self; self end).send(:define_method, :validates_blah) do
188
+ testit << 1324
189
189
  end
190
190
  end
191
191
  end
@@ -194,7 +194,7 @@ describe "Sequel::Plugins::ValidationClassMethods::ClassMethods::Generator" do
194
194
  @c.validates do
195
195
  blah
196
196
  end
197
- $testit.should == 1324
197
+ @testit.should == [1324]
198
198
  end
199
199
  end
200
200
 
@@ -641,7 +641,7 @@ describe ".validates with block" do
641
641
  columns :vvv
642
642
  validates do
643
643
  each :vvv do |o, a, v|
644
- o.errors[a] << "is less than zero" if v.to_i < 0
644
+ o.errors.add(a, "is less than zero") if v.to_i < 0
645
645
  end
646
646
  end
647
647
  end
@@ -764,7 +764,7 @@ describe Sequel::Model, "Validations" do
764
764
  @person.should be_valid
765
765
  end
766
766
 
767
- it "should validate that a column doesn't have a string value" do
767
+ qspecify "should validate that a column doesn't have a string value" do
768
768
  p = model_class.call Sequel::Model do
769
769
  columns :age, :price, :confirmed
770
770
  self.raise_on_typecast_failure = false
@@ -861,11 +861,11 @@ describe Sequel::Model, "Validations" do
861
861
  end
862
862
  User.dataset._fetch = proc do |sql|
863
863
  case sql
864
- when /COUNT.*username = '0records'/
864
+ when /count.*username = '0records'/
865
865
  {:v => 0}
866
- when /COUNT.*username = '2records'/
866
+ when /count.*username = '2records'/
867
867
  {:v => 2}
868
- when /COUNT.*username = '1record'/
868
+ when /count.*username = '1record'/
869
869
  {:v => 1}
870
870
  when /username = '1record'/
871
871
  {:id => 3, :username => "1record", :password => "test"}
@@ -908,11 +908,11 @@ describe Sequel::Model, "Validations" do
908
908
  end
909
909
  User.dataset._fetch = proc do |sql|
910
910
  case sql
911
- when /COUNT.*username = '0records'/
911
+ when /count.*username = '0records'/
912
912
  {:v => 0}
913
- when /COUNT.*username = '2records'/
913
+ when /count.*username = '2records'/
914
914
  {:v => 2}
915
- when /COUNT.*username = '1record'/
915
+ when /count.*username = '1record'/
916
916
  {:v => 1}
917
917
  when /username = '1record'/
918
918
  if sql =~ /password = 'anothertest'/
@@ -1022,7 +1022,7 @@ describe "Model#save" do
1022
1022
  columns :id, :x
1023
1023
 
1024
1024
  validates_each :x do |o, a, v|
1025
- o.errors[a] << 'blah' unless v == 7
1025
+ o.errors.add(a, 'blah') unless v == 7
1026
1026
  end
1027
1027
  end
1028
1028
  @m = @c.load(:id => 4, :x=>6)
@@ -235,7 +235,7 @@ describe "Sequel::Plugins::ValidationHelpers" do
235
235
  @m.should_not be_valid
236
236
  end
237
237
 
238
- specify "should support validates_not_string" do
238
+ qspecify "should support validates_not_string" do
239
239
  @c.set_validations{validates_not_string(:value)}
240
240
  @m.value = 123
241
241
  @m.should be_valid
@@ -261,6 +261,11 @@ describe "Sequel::Plugins::ValidationHelpers" do
261
261
  @m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
262
262
  @m.should_not be_valid
263
263
  @m.errors.full_messages.should == ['value is not a valid integer']
264
+
265
+ @c.set_validations{validates_schema_types(:value, :message=>'is bad')}
266
+ @m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
267
+ @m.should_not be_valid
268
+ @m.errors.full_messages.should == ['value is bad']
264
269
  end
265
270
 
266
271
  specify "should support validates_numeric" do
@@ -312,14 +317,12 @@ describe "Sequel::Plugins::ValidationHelpers" do
312
317
  @m.errors.full_messages.should == ['value is not a valid integer']
313
318
 
314
319
  @c.set_validations{validates_type(Integer, :value)}
315
- @m.value = nil
320
+ @m.value = 1
316
321
  @m.should be_valid
317
322
  @m.value = false
318
323
  @m.should_not be_valid
319
324
 
320
325
  @c.set_validations{validates_type([Integer, Float], :value)}
321
- @m.value = nil
322
- @m.should be_valid
323
326
  @m.value = 1
324
327
  @m.should be_valid
325
328
  @m.value = 1.0
@@ -329,6 +332,12 @@ describe "Sequel::Plugins::ValidationHelpers" do
329
332
  @m.errors.full_messages.should == ['value is not a valid integer or float']
330
333
  end
331
334
 
335
+ qspecify "should have validates_type skip nil values by default" do
336
+ @c.set_validations{validates_type([Integer, Float], :value)}
337
+ @m.value = nil
338
+ @m.should be_valid
339
+ end
340
+
332
341
  specify "should support validates_not_null" do
333
342
  @c.set_validations{validates_not_null(:value)}
334
343
  @m.should_not be_valid
@@ -369,9 +378,9 @@ describe "Sequel::Plugins::ValidationHelpers" do
369
378
  @c.set_validations{validates_unique(:username)}
370
379
  @c.dataset._fetch = proc do |sql|
371
380
  case sql
372
- when /COUNT.*username = '0records'/
381
+ when /count.*username = '0records'/
373
382
  {:v => 0}
374
- when /COUNT.*username = '1record'/
383
+ when /count.*username = '1record'/
375
384
  {:v => 1}
376
385
  end
377
386
  end
@@ -400,10 +409,10 @@ describe "Sequel::Plugins::ValidationHelpers" do
400
409
 
401
410
  @user = @c.load(:id=>1, :username => "0records", :password => "anothertest")
402
411
  @user.should be_valid
403
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (id != 1)) LIMIT 1"
412
+ MODEL_DB.sqls.last.should == "SELECT count(*) AS count FROM items WHERE ((username = '0records') AND (id != 1)) LIMIT 1"
404
413
  @user = @c.new(:username => "0records", :password => "anothertest")
405
414
  @user.should be_valid
406
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE (username = '0records') LIMIT 1"
415
+ MODEL_DB.sqls.last.should == "SELECT count(*) AS count FROM items WHERE (username = '0records') LIMIT 1"
407
416
  end
408
417
 
409
418
  it "should support validates_unique with multiple attributes" do
@@ -412,9 +421,9 @@ describe "Sequel::Plugins::ValidationHelpers" do
412
421
  @c.set_validations{validates_unique([:username, :password])}
413
422
  @c.dataset._fetch = proc do |sql|
414
423
  case sql
415
- when /COUNT.*username = '0records'/
424
+ when /count.*username = '0records'/
416
425
  {:v => 0}
417
- when /COUNT.*username = '1record'/
426
+ when /count.*username = '1record'/
418
427
  {:v => 1}
419
428
  end
420
429
  end
@@ -450,10 +459,10 @@ describe "Sequel::Plugins::ValidationHelpers" do
450
459
 
451
460
  @user = @c.load(:id=>1, :username => "0records", :password => "anothertest")
452
461
  @user.should be_valid
453
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest') AND (id != 1)) LIMIT 1"
462
+ MODEL_DB.sqls.last.should == "SELECT count(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest') AND (id != 1)) LIMIT 1"
454
463
  @user = @c.new(:username => "0records", :password => "anothertest")
455
464
  @user.should be_valid
456
- MODEL_DB.sqls.last.should == "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"
465
+ MODEL_DB.sqls.last.should == "SELECT count(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"
457
466
  end
458
467
 
459
468
  it "should support validates_unique with a block" do
@@ -465,8 +474,8 @@ describe "Sequel::Plugins::ValidationHelpers" do
465
474
  MODEL_DB.reset
466
475
  @c.new(:username => "0records", :password => "anothertest").should be_valid
467
476
  @c.load(:id=>3, :username => "0records", :password => "anothertest").should be_valid
468
- MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND active) LIMIT 1",
469
- "SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND active AND (id != 3)) LIMIT 1"]
477
+ MODEL_DB.sqls.should == ["SELECT count(*) AS count FROM items WHERE ((username = '0records') AND active) LIMIT 1",
478
+ "SELECT count(*) AS count FROM items WHERE ((username = '0records') AND active AND (id != 3)) LIMIT 1"]
470
479
  end
471
480
 
472
481
  it "should support validates_unique with a custom filter" do
@@ -478,8 +487,8 @@ describe "Sequel::Plugins::ValidationHelpers" do
478
487
  MODEL_DB.reset
479
488
  @c.new(:username => "0RECORDS", :password => "anothertest").should be_valid
480
489
  @c.load(:id=>3, :username => "0RECORDS", :password => "anothertest").should be_valid
481
- MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE (lower(username) = '0records') LIMIT 1",
482
- "SELECT COUNT(*) AS count FROM items WHERE ((lower(username) = '0records') AND (id != 3)) LIMIT 1"]
490
+ MODEL_DB.sqls.should == ["SELECT count(*) AS count FROM items WHERE (lower(username) = '0records') LIMIT 1",
491
+ "SELECT count(*) AS count FROM items WHERE ((lower(username) = '0records') AND (id != 3)) LIMIT 1"]
483
492
  end
484
493
 
485
494
  it "should support :only_if_modified option for validates_unique, and not check uniqueness for existing records if values haven't changed" do
@@ -490,7 +499,7 @@ describe "Sequel::Plugins::ValidationHelpers" do
490
499
 
491
500
  MODEL_DB.reset
492
501
  @c.new(:username => "0records", :password => "anothertest").should be_valid
493
- MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"]
502
+ MODEL_DB.sqls.should == ["SELECT count(*) AS count FROM items WHERE ((username = '0records') AND (password = 'anothertest')) LIMIT 1"]
494
503
  MODEL_DB.reset
495
504
  m = @c.load(:id=>3, :username => "0records", :password => "anothertest")
496
505
  m.should be_valid
@@ -498,23 +507,23 @@ describe "Sequel::Plugins::ValidationHelpers" do
498
507
 
499
508
  m.username = '1'
500
509
  m.should be_valid
501
- MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '1') AND (password = 'anothertest') AND (id != 3)) LIMIT 1"]
510
+ MODEL_DB.sqls.should == ["SELECT count(*) AS count FROM items WHERE ((username = '1') AND (password = 'anothertest') AND (id != 3)) LIMIT 1"]
502
511
 
503
512
  m = @c.load(:id=>3, :username => "0records", :password => "anothertest")
504
513
  MODEL_DB.reset
505
514
  m.password = '1'
506
515
  m.should be_valid
507
- MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '0records') AND (password = '1') AND (id != 3)) LIMIT 1"]
516
+ MODEL_DB.sqls.should == ["SELECT count(*) AS count FROM items WHERE ((username = '0records') AND (password = '1') AND (id != 3)) LIMIT 1"]
508
517
  MODEL_DB.reset
509
518
  m.username = '2'
510
519
  m.should be_valid
511
- MODEL_DB.sqls.should == ["SELECT COUNT(*) AS count FROM items WHERE ((username = '2') AND (password = '1') AND (id != 3)) LIMIT 1"]
520
+ MODEL_DB.sqls.should == ["SELECT count(*) AS count FROM items WHERE ((username = '2') AND (password = '1') AND (id != 3)) LIMIT 1"]
512
521
  end
513
522
 
514
523
  it "should not attempt a database query if the underlying columns have validation errors" do
515
524
  @c.columns(:id, :username, :password)
516
525
  @c.set_dataset MODEL_DB[:items]
517
- @c.set_validations{validates_not_string(:username); validates_unique([:username, :password])}
526
+ @c.set_validations{errors.add(:username, 'foo'); validates_unique([:username, :password])}
518
527
  @c.dataset._fetch = {:v=>0}
519
528
 
520
529
  MODEL_DB.reset
@@ -97,7 +97,7 @@ describe "Sequel::Plugins::XmlSerializer" do
97
97
  Album.from_xml(@album.to_xml(:include=>{:artist=>{:include=>{:albums=>{:only=>:name}}}}), :associations=>{:artist=>{:associations=>{:albums=>{:fields=>%w'name'}}}}).artist.albums.should == [Album.load(:name=>@album.name)]
98
98
  end
99
99
 
100
- it "should automatically cascade parsing for all associations if :all_associations is used" do
100
+ qspecify "should automatically cascade parsing for all associations if :all_associations is used" do
101
101
  Artist.from_xml(@artist.to_xml(:include=>{:albums=>{:include=>:artist}}), :all_associations=>true).albums.map{|a| a.artist}.should == [@artist]
102
102
  end
103
103
 
@@ -181,16 +181,16 @@ describe "Sequel::Plugins::XmlSerializer" do
181
181
  proc{Album.dataset.naked.to_xml}.should raise_error(Sequel::Error)
182
182
  end
183
183
 
184
- it "should have :associations option take precedence over :all_assocations" do
184
+ qspecify "should have :associations option take precedence over :all_assocations" do
185
185
  Artist.from_xml(@artist.to_xml(:include=>:albums), :associations=>[], :all_associations=>true, :fields=>[]).associations.should == {}
186
186
  end
187
187
 
188
- it "should allow overriding of :all_columns options in associated objects" do
188
+ qspecify "should allow overriding of :all_columns options in associated objects" do
189
189
  Album.restrict_primary_key
190
190
  Artist.from_xml(@artist.to_xml(:include=>:albums), :associations=>{:albums=>{:fields=>[:id, :name, :artist_id], :missing=>:raise}}, :all_columns=>true).albums
191
191
  end
192
192
 
193
- it "should allow setting columns that are restricted if :all_columns is used" do
193
+ qspecify "should allow setting columns that are restricted if :all_columns is used" do
194
194
  Artist.restrict_primary_key
195
195
  Artist.from_xml(@artist.to_xml, :all_columns=>true).should == @artist
196
196
  end
@@ -200,7 +200,7 @@ describe "Sequel::Plugins::XmlSerializer" do
200
200
  proc{Artist.array_from_xml("<?xml version=\"1.0\"?>\n")}.should raise_error(Sequel::Error)
201
201
  end
202
202
 
203
- it "should raise an error if using :all_columns and non-column is in the XML" do
203
+ qspecify "should raise an error if using :all_columns and non-column is in the XML" do
204
204
  proc{Artist.from_xml("<?xml version=\"1.0\"?>\n<artist>\n <foo>bar</foo>\n <id>2</id>\n</artist>\n", :all_columns=>true)}.should raise_error(Sequel::Error)
205
205
  end
206
206
 
@@ -51,9 +51,6 @@ shared_examples_for "eager limit strategies" do
51
51
  end
52
52
 
53
53
  specify "should correctly handle limits and offsets when eager loading many_to_many associations" do
54
- if @els == {:eager_limit_strategy=>:correlated_subquery} && Sequel.guarded?(:derby, :mssql)
55
- pending("correlated subqueries on many_to_many associations not supported")
56
- end
57
54
  Album.many_to_many :first_two_tags, {:clone=>:first_two_tags}.merge(@els) if @els
58
55
  Album.many_to_many :second_two_tags, {:clone=>:second_two_tags}.merge(@els) if @els
59
56
  Album.many_to_many :last_two_tags, {:clone=>:last_two_tags}.merge(@els) if @els
@@ -76,9 +73,6 @@ shared_examples_for "eager limit strategies" do
76
73
  end
77
74
 
78
75
  specify "should correctly handle limits and offsets when eager loading many_through_many associations" do
79
- if @els == {:eager_limit_strategy=>:correlated_subquery} && Sequel.guarded?(:derby, :mssql)
80
- pending("correlated subqueries on many_through_many associations not supported")
81
- end
82
76
  Artist.many_through_many :first_two_tags, {:clone=>:first_two_tags}.merge(@els) if @els
83
77
  Artist.many_through_many :second_two_tags, {:clone=>:second_two_tags}.merge(@els) if @els
84
78
  Artist.many_through_many :last_two_tags, {:clone=>:last_two_tags}.merge(@els) if @els
@@ -573,7 +567,7 @@ describe "Sequel::Model Simple Associations" do
573
567
  end
574
568
  class ::Album < Sequel::Model(@db)
575
569
  plugin :dataset_associations
576
- many_to_one :artist
570
+ many_to_one :artist, :reciprocal=>nil
577
571
  many_to_many :tags, :right_key=>:tag_id
578
572
  many_to_many :alias_tags, :clone=>:tags, :join_table=>:albums_tags___at
579
573
  many_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
@@ -603,13 +597,6 @@ describe "Sequel::Model Simple Associations" do
603
597
 
604
598
  it_should_behave_like "regular and composite key associations"
605
599
 
606
- describe "with :eager_limit_strategy=>:correlated_subquery" do
607
- before do
608
- @els = {:eager_limit_strategy=>:correlated_subquery}
609
- end
610
- it_should_behave_like "eager limit strategies"
611
- end unless Sequel.guarded?(:mysql, :db2, :oracle, :h2, :cubrid, :hsqldb)
612
-
613
600
  specify "should handle many_to_one associations with same name as :key" do
614
601
  Album.def_column_alias(:artist_id_id, :artist_id)
615
602
  Album.many_to_one :artist_id, :key_column =>:artist_id, :class=>Artist
@@ -632,7 +619,7 @@ describe "Sequel::Model Simple Associations" do
632
619
  Artist.set_dataset(:artists___ar)
633
620
  Album.set_dataset(:albums___a)
634
621
  Tag.set_dataset(:tags___t)
635
- Artist.one_to_many :balbums, :class=>Album, :key=>:artist_id
622
+ Artist.one_to_many :balbums, :class=>Album, :key=>:artist_id, :reciprocal=>nil
636
623
  Album.many_to_many :btags, :class=>Tag, :join_table=>:albums_tags, :right_key=>:tag_id
637
624
  Album.many_to_one :bartist, :class=>Artist, :key=>:artist_id
638
625
  Tag.many_to_many :balbums, :class=>Album, :join_table=>:albums_tags, :right_key=>:album_id
@@ -650,13 +637,13 @@ describe "Sequel::Model Simple Associations" do
650
637
 
651
638
  specify "should have add method accept hashes and create new records" do
652
639
  @artist.remove_all_albums
653
- Album.delete
640
+ Album.dataset.delete
654
641
  @album = @artist.add_album(:name=>'Al2')
655
642
  Album.first[:name].should == 'Al2'
656
643
  @artist.albums_dataset.first[:name].should == 'Al2'
657
644
 
658
645
  @album.remove_all_tags
659
- Tag.delete
646
+ Tag.dataset.delete
660
647
  @album.add_tag(:name=>'T2')
661
648
  Tag.first[:name].should == 'T2'
662
649
  @album.tags_dataset.first[:name].should == 'T2'
@@ -766,7 +753,7 @@ describe "Sequel::Model Composite Key Associations" do
766
753
  [:albums_tags, :tags, :albums, :artists].each{|t| @db[t].delete}
767
754
  class ::Artist < Sequel::Model(@db)
768
755
  plugin :dataset_associations
769
- set_primary_key :id1, :id2
756
+ set_primary_key [:id1, :id2]
770
757
  unrestrict_primary_key
771
758
  one_to_many :albums, :key=>[:artist_id1, :artist_id2], :order=>:name
772
759
  one_to_one :first_album, :clone=>:albums, :order=>:name
@@ -782,9 +769,9 @@ describe "Sequel::Model Composite Key Associations" do
782
769
  end
783
770
  class ::Album < Sequel::Model(@db)
784
771
  plugin :dataset_associations
785
- set_primary_key :id1, :id2
772
+ set_primary_key [:id1, :id2]
786
773
  unrestrict_primary_key
787
- many_to_one :artist, :key=>[:artist_id1, :artist_id2]
774
+ many_to_one :artist, :key=>[:artist_id1, :artist_id2], :reciprocal=>nil
788
775
  many_to_many :tags, :left_key=>[:album_id1, :album_id2], :right_key=>[:tag_id1, :tag_id2]
789
776
  many_to_many :alias_tags, :clone=>:tags, :join_table=>:albums_tags___at
790
777
  many_to_many :first_two_tags, :clone=>:tags, :order=>:name, :limit=>2
@@ -793,7 +780,7 @@ describe "Sequel::Model Composite Key Associations" do
793
780
  end
794
781
  class ::Tag < Sequel::Model(@db)
795
782
  plugin :dataset_associations
796
- set_primary_key :id1, :id2
783
+ set_primary_key [:id1, :id2]
797
784
  unrestrict_primary_key
798
785
  many_to_many :albums, :right_key=>[:album_id1, :album_id2], :left_key=>[:tag_id1, :tag_id2]
799
786
  end
@@ -816,22 +803,15 @@ describe "Sequel::Model Composite Key Associations" do
816
803
 
817
804
  it_should_behave_like "regular and composite key associations"
818
805
 
819
- describe "with :eager_limit_strategy=>:correlated_subquery" do
820
- before do
821
- @els = {:eager_limit_strategy=>:correlated_subquery}
822
- end
823
- it_should_behave_like "eager limit strategies"
824
- end if INTEGRATION_DB.dataset.supports_multiple_column_in? && !Sequel.guarded?(:mysql, :db2, :oracle, :hsqldb)
825
-
826
806
  specify "should have add method accept hashes and create new records" do
827
807
  @artist.remove_all_albums
828
- Album.delete
808
+ Album.dataset.delete
829
809
  @artist.add_album(:id1=>1, :id2=>2, :name=>'Al2')
830
810
  Album.first[:name].should == 'Al2'
831
811
  @artist.albums_dataset.first[:name].should == 'Al2'
832
812
 
833
813
  @album.remove_all_tags
834
- Tag.delete
814
+ Tag.dataset.delete
835
815
  @album.add_tag(:id1=>1, :id2=>2, :name=>'T2')
836
816
  Tag.first[:name].should == 'T2'
837
817
  @album.tags_dataset.first[:name].should == 'T2'