sequel 4.47.0 → 4.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 (177) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +134 -0
  3. data/Rakefile +1 -1
  4. data/doc/release_notes/4.48.0.txt +293 -0
  5. data/lib/sequel/adapters/ado/access.rb +2 -1
  6. data/lib/sequel/adapters/do/postgres.rb +5 -2
  7. data/lib/sequel/adapters/ibmdb.rb +24 -7
  8. data/lib/sequel/adapters/jdbc.rb +36 -22
  9. data/lib/sequel/adapters/jdbc/db2.rb +12 -3
  10. data/lib/sequel/adapters/jdbc/derby.rb +4 -5
  11. data/lib/sequel/adapters/jdbc/oracle.rb +16 -2
  12. data/lib/sequel/adapters/jdbc/postgresql.rb +43 -18
  13. data/lib/sequel/adapters/jdbc/sqlanywhere.rb +9 -7
  14. data/lib/sequel/adapters/jdbc/sqlserver.rb +11 -4
  15. data/lib/sequel/adapters/mock.rb +24 -19
  16. data/lib/sequel/adapters/mysql.rb +17 -16
  17. data/lib/sequel/adapters/mysql2.rb +4 -5
  18. data/lib/sequel/adapters/oracle.rb +5 -9
  19. data/lib/sequel/adapters/postgres.rb +89 -102
  20. data/lib/sequel/adapters/shared/db2.rb +22 -6
  21. data/lib/sequel/adapters/shared/mssql.rb +5 -4
  22. data/lib/sequel/adapters/shared/mysql.rb +75 -24
  23. data/lib/sequel/adapters/shared/postgres.rb +196 -94
  24. data/lib/sequel/adapters/shared/sqlanywhere.rb +23 -10
  25. data/lib/sequel/adapters/shared/sqlite.rb +72 -82
  26. data/lib/sequel/adapters/sqlanywhere.rb +4 -1
  27. data/lib/sequel/adapters/sqlite.rb +5 -3
  28. data/lib/sequel/adapters/swift/postgres.rb +5 -2
  29. data/lib/sequel/adapters/tinytds.rb +0 -5
  30. data/lib/sequel/adapters/utils/mysql_mysql2.rb +1 -1
  31. data/lib/sequel/adapters/utils/pg_types.rb +2 -76
  32. data/lib/sequel/core.rb +2 -2
  33. data/lib/sequel/database/connecting.rb +5 -5
  34. data/lib/sequel/database/dataset.rb +6 -3
  35. data/lib/sequel/database/misc.rb +1 -1
  36. data/lib/sequel/database/query.rb +3 -0
  37. data/lib/sequel/database/schema_methods.rb +1 -1
  38. data/lib/sequel/dataset/actions.rb +18 -10
  39. data/lib/sequel/dataset/graph.rb +1 -1
  40. data/lib/sequel/dataset/misc.rb +1 -0
  41. data/lib/sequel/dataset/prepared_statements.rb +3 -3
  42. data/lib/sequel/dataset/query.rb +19 -8
  43. data/lib/sequel/extensions/core_extensions.rb +4 -1
  44. data/lib/sequel/extensions/duplicate_columns_handler.rb +1 -1
  45. data/lib/sequel/extensions/empty_array_ignore_nulls.rb +3 -0
  46. data/lib/sequel/extensions/filter_having.rb +2 -0
  47. data/lib/sequel/extensions/freeze_datasets.rb +2 -0
  48. data/lib/sequel/extensions/from_block.rb +1 -1
  49. data/lib/sequel/extensions/graph_each.rb +2 -2
  50. data/lib/sequel/extensions/hash_aliases.rb +2 -0
  51. data/lib/sequel/extensions/identifier_mangling.rb +0 -7
  52. data/lib/sequel/extensions/meta_def.rb +2 -0
  53. data/lib/sequel/extensions/migration.rb +6 -6
  54. data/lib/sequel/extensions/no_auto_literal_strings.rb +1 -1
  55. data/lib/sequel/extensions/pagination.rb +1 -1
  56. data/lib/sequel/extensions/pg_array.rb +207 -130
  57. data/lib/sequel/extensions/pg_hstore.rb +38 -20
  58. data/lib/sequel/extensions/pg_inet.rb +18 -6
  59. data/lib/sequel/extensions/pg_interval.rb +19 -12
  60. data/lib/sequel/extensions/pg_json.rb +25 -14
  61. data/lib/sequel/extensions/pg_json_ops.rb +2 -2
  62. data/lib/sequel/extensions/pg_range.rb +133 -100
  63. data/lib/sequel/extensions/pg_range_ops.rb +4 -3
  64. data/lib/sequel/extensions/pg_row.rb +68 -39
  65. data/lib/sequel/extensions/pg_row_ops.rb +11 -5
  66. data/lib/sequel/extensions/query_literals.rb +2 -0
  67. data/lib/sequel/extensions/ruby18_symbol_extensions.rb +2 -0
  68. data/lib/sequel/extensions/s.rb +1 -1
  69. data/lib/sequel/extensions/schema_dumper.rb +24 -24
  70. data/lib/sequel/extensions/sequel_3_dataset_methods.rb +3 -1
  71. data/lib/sequel/extensions/sequel_4_dataset_methods.rb +83 -0
  72. data/lib/sequel/extensions/set_overrides.rb +2 -2
  73. data/lib/sequel/extensions/string_agg.rb +0 -1
  74. data/lib/sequel/extensions/symbol_aref.rb +0 -4
  75. data/lib/sequel/model.rb +25 -57
  76. data/lib/sequel/model/associations.rb +14 -5
  77. data/lib/sequel/model/base.rb +96 -32
  78. data/lib/sequel/plugins/association_pks.rb +73 -46
  79. data/lib/sequel/plugins/association_proxies.rb +1 -1
  80. data/lib/sequel/plugins/auto_validations.rb +6 -2
  81. data/lib/sequel/plugins/boolean_readers.rb +1 -1
  82. data/lib/sequel/plugins/caching.rb +19 -13
  83. data/lib/sequel/plugins/class_table_inheritance.rb +19 -10
  84. data/lib/sequel/plugins/column_conflicts.rb +7 -2
  85. data/lib/sequel/plugins/column_select.rb +1 -1
  86. data/lib/sequel/plugins/csv_serializer.rb +8 -8
  87. data/lib/sequel/plugins/defaults_setter.rb +10 -0
  88. data/lib/sequel/plugins/eager_each.rb +1 -1
  89. data/lib/sequel/plugins/force_encoding.rb +2 -2
  90. data/lib/sequel/plugins/hook_class_methods.rb +9 -12
  91. data/lib/sequel/plugins/identifier_columns.rb +2 -0
  92. data/lib/sequel/plugins/instance_filters.rb +3 -1
  93. data/lib/sequel/plugins/instance_hooks.rb +17 -9
  94. data/lib/sequel/plugins/json_serializer.rb +17 -10
  95. data/lib/sequel/plugins/lazy_attributes.rb +8 -7
  96. data/lib/sequel/plugins/modification_detection.rb +3 -0
  97. data/lib/sequel/plugins/nested_attributes.rb +5 -1
  98. data/lib/sequel/plugins/pg_array_associations.rb +5 -0
  99. data/lib/sequel/plugins/prepared_statements.rb +1 -0
  100. data/lib/sequel/plugins/rcte_tree.rb +4 -4
  101. data/lib/sequel/plugins/serialization.rb +3 -10
  102. data/lib/sequel/plugins/single_table_inheritance.rb +2 -2
  103. data/lib/sequel/plugins/split_values.rb +6 -5
  104. data/lib/sequel/plugins/static_cache.rb +31 -25
  105. data/lib/sequel/plugins/subset_conditions.rb +3 -1
  106. data/lib/sequel/plugins/table_select.rb +1 -1
  107. data/lib/sequel/plugins/touch.rb +2 -1
  108. data/lib/sequel/plugins/validation_class_methods.rb +5 -6
  109. data/lib/sequel/plugins/validation_helpers.rb +2 -4
  110. data/lib/sequel/plugins/xml_serializer.rb +4 -4
  111. data/lib/sequel/sql.rb +2 -2
  112. data/lib/sequel/version.rb +1 -1
  113. data/spec/adapters/db2_spec.rb +115 -14
  114. data/spec/adapters/mysql_spec.rb +78 -28
  115. data/spec/adapters/oracle_spec.rb +24 -24
  116. data/spec/adapters/postgres_spec.rb +38 -24
  117. data/spec/adapters/sqlanywhere_spec.rb +88 -86
  118. data/spec/adapters/sqlite_spec.rb +29 -24
  119. data/spec/core/connection_pool_spec.rb +17 -0
  120. data/spec/core/database_spec.rb +6 -0
  121. data/spec/core/dataset_spec.rb +46 -36
  122. data/spec/core/schema_spec.rb +16 -0
  123. data/spec/core/spec_helper.rb +1 -0
  124. data/spec/core_extensions_spec.rb +6 -2
  125. data/spec/extensions/active_model_spec.rb +1 -1
  126. data/spec/extensions/arbitrary_servers_spec.rb +1 -1
  127. data/spec/extensions/association_pks_spec.rb +34 -2
  128. data/spec/extensions/auto_literal_strings_spec.rb +5 -1
  129. data/spec/extensions/auto_validations_spec.rb +2 -0
  130. data/spec/extensions/boolean_readers_spec.rb +1 -1
  131. data/spec/extensions/boolean_subsets_spec.rb +1 -1
  132. data/spec/extensions/class_table_inheritance_spec.rb +48 -2
  133. data/spec/extensions/column_conflicts_spec.rb +11 -0
  134. data/spec/extensions/connection_validator_spec.rb +1 -1
  135. data/spec/extensions/dataset_associations_spec.rb +8 -8
  136. data/spec/extensions/defaults_setter_spec.rb +1 -1
  137. data/spec/extensions/filter_having_spec.rb +5 -3
  138. data/spec/extensions/hash_aliases_spec.rb +3 -1
  139. data/spec/extensions/identifier_columns_spec.rb +3 -1
  140. data/spec/extensions/implicit_subquery_spec.rb +4 -2
  141. data/spec/extensions/json_serializer_spec.rb +18 -0
  142. data/spec/extensions/lazy_attributes_spec.rb +3 -3
  143. data/spec/extensions/meta_def_spec.rb +9 -0
  144. data/spec/extensions/migration_spec.rb +3 -3
  145. data/spec/extensions/nested_attributes_spec.rb +14 -3
  146. data/spec/extensions/no_auto_literal_strings_spec.rb +8 -4
  147. data/spec/extensions/pg_array_associations_spec.rb +29 -18
  148. data/spec/extensions/pg_array_spec.rb +44 -25
  149. data/spec/extensions/pg_hstore_spec.rb +10 -0
  150. data/spec/extensions/pg_inet_spec.rb +26 -0
  151. data/spec/extensions/pg_interval_spec.rb +20 -0
  152. data/spec/extensions/pg_json_spec.rb +24 -0
  153. data/spec/extensions/pg_range_spec.rb +98 -14
  154. data/spec/extensions/pg_row_spec.rb +14 -4
  155. data/spec/extensions/prepared_statements_safe_spec.rb +1 -1
  156. data/spec/extensions/query_literals_spec.rb +3 -1
  157. data/spec/extensions/schema_dumper_spec.rb +96 -98
  158. data/spec/extensions/sequel_3_dataset_methods_spec.rb +10 -6
  159. data/spec/extensions/sequel_4_dataset_methods_spec.rb +121 -0
  160. data/spec/extensions/single_table_inheritance_spec.rb +1 -1
  161. data/spec/extensions/spec_helper.rb +7 -1
  162. data/spec/extensions/static_cache_spec.rb +75 -24
  163. data/spec/extensions/string_agg_spec.rb +1 -1
  164. data/spec/extensions/touch_spec.rb +9 -0
  165. data/spec/extensions/validation_helpers_spec.rb +9 -3
  166. data/spec/extensions/whitelist_security_spec.rb +26 -0
  167. data/spec/integration/dataset_test.rb +45 -44
  168. data/spec/integration/plugin_test.rb +20 -0
  169. data/spec/integration/prepared_statement_test.rb +3 -0
  170. data/spec/integration/schema_test.rb +21 -1
  171. data/spec/integration/transaction_test.rb +40 -40
  172. data/spec/model/class_dataset_methods_spec.rb +14 -4
  173. data/spec/model/dataset_methods_spec.rb +12 -3
  174. data/spec/model/model_spec.rb +8 -0
  175. metadata +6 -4
  176. data/spec/adapters/firebird_spec.rb +0 -405
  177. data/spec/adapters/informix_spec.rb +0 -100
@@ -2,7 +2,9 @@ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
2
 
3
3
  describe "Dataset#to_csv" do
4
4
  before do
5
- @ds = Sequel.mock(:fetch=>[{:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}, {:a=>7, :b=>8, :c=>9}])[:items].columns(:a, :b, :c).extension(:sequel_3_dataset_methods)
5
+ deprecated do
6
+ @ds = Sequel.mock(:fetch=>[{:a=>1, :b=>2, :c=>3}, {:a=>4, :b=>5, :c=>6}, {:a=>7, :b=>8, :c=>9}])[:items].columns(:a, :b, :c).extension(:sequel_3_dataset_methods)
7
+ end
6
8
  end
7
9
 
8
10
  it "should format a CSV representation of the records" do
@@ -15,7 +17,7 @@ describe "Dataset#to_csv" do
15
17
  end
16
18
 
17
19
  describe "Dataset#[]=" do
18
- it "should perform an update on the specified filter" do
20
+ deprecated "should perform an update on the specified filter" do
19
21
  db = Sequel.mock
20
22
  ds = db[:items].extension(:sequel_3_dataset_methods)
21
23
  ds[:a => 1] = {:x => 3}
@@ -26,7 +28,9 @@ end
26
28
  describe "Dataset#insert_multiple" do
27
29
  before do
28
30
  @db = Sequel.mock(:autoid=>2)
29
- @ds = @db[:items].extension(:sequel_3_dataset_methods)
31
+ deprecated do
32
+ @ds = @db[:items].extension(:sequel_3_dataset_methods)
33
+ end
30
34
  end
31
35
 
32
36
  it "should insert all items in the supplied array" do
@@ -92,7 +96,7 @@ unless Sequel.mock.dataset.frozen?
92
96
  end
93
97
 
94
98
  describe "Dataset#set" do
95
- it "should act as alias to #update" do
99
+ deprecated "should act as alias to #update" do
96
100
  db = Sequel.mock
97
101
  ds = db[:items].extension(:sequel_3_dataset_methods)
98
102
  ds.set({:x => 3})
@@ -101,13 +105,13 @@ describe "Dataset#set" do
101
105
  end
102
106
 
103
107
  describe "Sequel::Dataset#qualify_to_first_source" do
104
- it "should qualify to the first source" do
108
+ deprecated "should qualify to the first source" do
105
109
  Sequel.mock.dataset.extension(:sequel_3_dataset_methods).from(:t).filter{a<b}.qualify_to_first_source.sql.must_equal 'SELECT t.* FROM t WHERE (t.a < t.b)'
106
110
  end
107
111
  end
108
112
 
109
113
  describe "Sequel::Dataset#qualify_to" do
110
- it "should qualify to the given table" do
114
+ deprecated "should qualify to the given table" do
111
115
  Sequel.mock.dataset.extension(:sequel_3_dataset_methods).from(:t).filter{a<b}.qualify_to(:e).sql.must_equal 'SELECT e.* FROM t WHERE (e.a < e.b)'
112
116
  end
113
117
  end
@@ -0,0 +1,121 @@
1
+ require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
2
+
3
+ describe "Dataset#and" do
4
+ before do
5
+ @dataset = Sequel.mock.dataset.from(:test).extension(:sequel_4_dataset_methods)
6
+ @d1 = @dataset.where(:x => 1)
7
+ end
8
+
9
+ it "should add a WHERE filter if none exists" do
10
+ @dataset.and(:a => 1).sql.must_equal 'SELECT * FROM test WHERE (a = 1)'
11
+ end
12
+
13
+ it "should add an expression to the where clause" do
14
+ @d1.and(:y => 2).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y = 2))'
15
+ end
16
+
17
+ it "should accept placeholder literal string filters" do
18
+ @d1.and(Sequel.lit('y > ?', 2)).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
19
+ end
20
+
21
+ it "should accept expression filters" do
22
+ @d1.and(Sequel.expr(:yy) > 3).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
23
+ end
24
+
25
+ it "should accept string filters with placeholders" do
26
+ @d1.extension(:auto_literal_strings).and('y > ?', 2).sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (y > 2))'
27
+ end
28
+
29
+ it "should accept blocks passed to filter" do
30
+ @d1.and{yy > 3}.sql.must_equal 'SELECT * FROM test WHERE ((x = 1) AND (yy > 3))'
31
+ end
32
+
33
+ it "should correctly add parens to give predictable results" do
34
+ @d1.or(:y => 2).and(:z => 3).sql.must_equal 'SELECT * FROM test WHERE (((x = 1) OR (y = 2)) AND (z = 3))'
35
+ @d1.and(:y => 2).or(:z => 3).sql.must_equal 'SELECT * FROM test WHERE (((x = 1) AND (y = 2)) OR (z = 3))'
36
+ end
37
+ end
38
+
39
+ describe "Dataset#exclude_where" do
40
+ before do
41
+ @dataset = Sequel.mock.dataset.from(:test).extension(:sequel_4_dataset_methods)
42
+ end
43
+
44
+ it "should correctly negate the expression and add it to the where clause" do
45
+ @dataset.exclude_where(:region=>'Asia').sql.must_equal "SELECT * FROM test WHERE (region != 'Asia')"
46
+ @dataset.exclude_where(:region=>'Asia').exclude_where(:region=>'NA').sql.must_equal "SELECT * FROM test WHERE ((region != 'Asia') AND (region != 'NA'))"
47
+ end
48
+
49
+ it "should affect the where clause even if having clause is already used" do
50
+ @dataset.group_and_count(:name).having{count > 2}.exclude_where(:region=>'Asia').sql.
51
+ must_equal "SELECT name, count(*) AS count FROM test WHERE (region != 'Asia') GROUP BY name HAVING (count > 2)"
52
+ end
53
+ end
54
+
55
+ describe "Dataset#interval" do
56
+ before do
57
+ @db = Sequel.mock(:fetch=>{:v => 1234}).extension(:sequel_4_dataset_methods)
58
+ @ds = @db[:test].freeze
59
+ end
60
+
61
+ it "should generate the correct SQL statement" do
62
+ 5.times do
63
+ @ds.interval(:stamp)
64
+ @db.sqls.must_equal ["SELECT (max(stamp) - min(stamp)) AS interval FROM test LIMIT 1"]
65
+ end
66
+
67
+ @ds.filter(Sequel.expr(:price) > 100).interval(:stamp)
68
+ @db.sqls.must_equal ["SELECT (max(stamp) - min(stamp)) AS interval FROM test WHERE (price > 100) LIMIT 1"]
69
+ end
70
+
71
+ it "should use a subselect for the same conditions as count" do
72
+ ds = @ds.order(:stamp).limit(5)
73
+ 5.times do
74
+ ds.interval(:stamp).must_equal 1234
75
+ @db.sqls.must_equal ['SELECT (max(stamp) - min(stamp)) AS interval FROM (SELECT * FROM test ORDER BY stamp LIMIT 5) AS t1 LIMIT 1']
76
+ end
77
+ end
78
+
79
+ it "should accept virtual row blocks" do
80
+ 5.times do
81
+ @ds.interval{a(b)}
82
+ @db.sqls.must_equal ["SELECT (max(a(b)) - min(a(b))) AS interval FROM test LIMIT 1"]
83
+ end
84
+ end
85
+ end
86
+
87
+ describe "Dataset#range" do
88
+ before do
89
+ @db = Sequel.mock(:fetch=>{:v1 => 1, :v2 => 10}).extension(:sequel_4_dataset_methods)
90
+ @ds = @db[:test].freeze
91
+ end
92
+
93
+ it "should generate a correct SQL statement" do
94
+ 5.times do
95
+ @ds.range(:stamp)
96
+ @db.sqls.must_equal ["SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test LIMIT 1"]
97
+ end
98
+
99
+ @ds.filter(Sequel.expr(:price) > 100).range(:stamp)
100
+ @db.sqls.must_equal ["SELECT min(stamp) AS v1, max(stamp) AS v2 FROM test WHERE (price > 100) LIMIT 1"]
101
+ end
102
+
103
+ it "should return a range object" do
104
+ 5.times do
105
+ @ds.range(:tryme).must_equal(1..10)
106
+ end
107
+ end
108
+
109
+ it "should use a subselect for the same conditions as count" do
110
+ @ds.order(:stamp).limit(5).range(:stamp).must_equal(1..10)
111
+ @db.sqls.must_equal ['SELECT min(stamp) AS v1, max(stamp) AS v2 FROM (SELECT * FROM test ORDER BY stamp LIMIT 5) AS t1 LIMIT 1']
112
+ end
113
+
114
+ it "should accept virtual row blocks" do
115
+ 5.times do
116
+ @ds.range{a(b)}
117
+ @db.sqls.must_equal ["SELECT min(a(b)) AS v1, max(a(b)) AS v2 FROM test LIMIT 1"]
118
+ end
119
+ end
120
+ end
121
+
@@ -90,7 +90,7 @@ describe Sequel::Model, "single table inheritance plugin" do
90
90
 
91
91
  it "should fallback to the main class if the sti_key field is empty or nil without calling constantize" do
92
92
  called = false
93
- StiTest.meta_def(:constantize) do |s|
93
+ def StiTest.constantize(s)
94
94
  called = true
95
95
  Object
96
96
  end
@@ -28,13 +28,19 @@ rescue LoadError
28
28
  nil
29
29
  end
30
30
 
31
- Sequel.extension :meta_def
32
31
  Sequel.extension :core_refinements if RUBY_VERSION >= '2.0.0' && RUBY_ENGINE == 'ruby'
33
32
 
34
33
  def skip_warn(s)
35
34
  warn "Skipping test of #{s}" if ENV["SKIPPED_TEST_WARN"]
36
35
  end
37
36
 
37
+ class Minitest::HooksSpec
38
+ # SEQUEL5: Replace with define_singleton_method
39
+ def meta_def(obj, name, &block)
40
+ (class << obj; self end).send(:define_method, name, &block)
41
+ end
42
+ end
43
+
38
44
  # SEQUEL5: Remove
39
45
  output = Sequel::Deprecation.output
40
46
  Sequel::Deprecation.output = nil
@@ -113,35 +113,58 @@ describe "Sequel::Plugins::StaticCache" do
113
113
  @c.all.must_equal [@c1, @c2]
114
114
  end
115
115
 
116
- it "should have to_hash without arguments run without a query" do
116
+ it "should have as_hash/to_hash without arguments run without a query" do
117
117
  a = @c.to_hash
118
118
  a.must_equal(1=>@c1, 2=>@c2)
119
119
  a[1].must_equal @c1
120
120
  a[2].must_equal @c2
121
+
122
+ a = @c.as_hash
123
+ a.must_equal(1=>@c1, 2=>@c2)
124
+ a[1].must_equal @c1
125
+ a[2].must_equal @c2
126
+ @db.sqls.must_equal []
127
+ end
128
+
129
+ it "should have as_hash handle :hash option" do
130
+ h = {}
131
+ a = @c.as_hash(nil, nil, :hash=>h)
132
+ a.must_be_same_as h
133
+ a.must_equal(1=>@c1, 2=>@c2)
134
+ a[1].must_equal @c1
135
+ a[2].must_equal @c2
136
+
137
+ h = {}
138
+ a = @c.as_hash(:id, nil, :hash=>h)
139
+ a.must_be_same_as h
140
+ a.must_equal(1=>@c1, 2=>@c2)
141
+ a[1].must_equal @c1
142
+ a[2].must_equal @c2
143
+
121
144
  @db.sqls.must_equal []
122
145
  end
123
146
 
124
- it "should have to_hash with arguments return results without a query" do
125
- a = @c.to_hash(:id)
147
+ it "should have as_hash with arguments return results without a query" do
148
+ a = @c.as_hash(:id)
126
149
  a.must_equal(1=>@c1, 2=>@c2)
127
150
  a[1].must_equal @c1
128
151
  a[2].must_equal @c2
129
152
 
130
- a = @c.to_hash([:id])
153
+ a = @c.as_hash([:id])
131
154
  a.must_equal([1]=>@c1, [2]=>@c2)
132
155
  a[[1]].must_equal @c1
133
156
  a[[2]].must_equal @c2
134
157
 
135
- @c.to_hash(:id, :id).must_equal(1=>1, 2=>2)
136
- @c.to_hash([:id], :id).must_equal([1]=>1, [2]=>2)
137
- @c.to_hash(:id, [:id]).must_equal(1=>[1], 2=>[2])
138
- @c.to_hash([:id], [:id]).must_equal([1]=>[1], [2]=>[2])
158
+ @c.as_hash(:id, :id).must_equal(1=>1, 2=>2)
159
+ @c.as_hash([:id], :id).must_equal([1]=>1, [2]=>2)
160
+ @c.as_hash(:id, [:id]).must_equal(1=>[1], 2=>[2])
161
+ @c.as_hash([:id], [:id]).must_equal([1]=>[1], [2]=>[2])
139
162
 
140
163
  @db.sqls.must_equal []
141
164
  end
142
165
 
143
- it "should have to_hash not return a frozen object" do
144
- @c.to_hash.frozen?.must_equal false
166
+ it "should have as_hash not return a frozen object" do
167
+ @c.as_hash.frozen?.must_equal false
145
168
  end
146
169
 
147
170
  it "should have to_hash_groups without arguments return the cached objects without a query" do
@@ -163,10 +186,38 @@ describe "Sequel::Plugins::StaticCache" do
163
186
  @db.sqls.must_equal []
164
187
  end
165
188
 
189
+ it "should have to_hash_groups handle :hash option" do
190
+ h = {}
191
+ a = @c.to_hash_groups(:id, nil, :hash=>h)
192
+ a.must_be_same_as h
193
+ a.must_equal(1=>[@c1], 2=>[@c2])
194
+ a[1].first.must_equal @c1
195
+ a[2].first.must_equal @c2
196
+ end
197
+
198
+ it "should have as_hash_groups without arguments return the cached objects without a query" do
199
+ a = @c.to_hash_groups(:id)
200
+ a.must_equal(1=>[@c1], 2=>[@c2])
201
+ a[1].first.must_equal @c1
202
+ a[2].first.must_equal @c2
203
+
204
+ a = @c.to_hash_groups([:id])
205
+ a.must_equal([1]=>[@c1], [2]=>[@c2])
206
+ a[[1]].first.must_equal @c1
207
+ a[[2]].first.must_equal @c2
208
+
209
+ @c.to_hash_groups(:id, :id).must_equal(1=>[1], 2=>[2])
210
+ @c.to_hash_groups([:id], :id).must_equal([1]=>[1], [2]=>[2])
211
+ @c.to_hash_groups(:id, [:id]).must_equal(1=>[[1]], 2=>[[2]])
212
+ @c.to_hash_groups([:id], [:id]).must_equal([1]=>[[1]], [2]=>[[2]])
213
+
214
+ @db.sqls.must_equal []
215
+ end
216
+
166
217
  it "subclasses should work correctly" do
167
218
  c = Class.new(@c)
168
219
  c.all.must_equal [c.load(:id=>1), c.load(:id=>2)]
169
- c.to_hash.must_equal(1=>c.load(:id=>1), 2=>c.load(:id=>2))
220
+ c.as_hash.must_equal(1=>c.load(:id=>1), 2=>c.load(:id=>2))
170
221
  @db.sqls.must_equal ['SELECT * FROM t']
171
222
  end
172
223
 
@@ -174,8 +225,8 @@ describe "Sequel::Plugins::StaticCache" do
174
225
  ds = @c.dataset.from(:t2).columns(:id).with_fetch(:id=>3)
175
226
  @c.dataset = ds
176
227
  @c.all.must_equal [@c.load(:id=>3)]
177
- @c.to_hash.must_equal(3=>@c.load(:id=>3))
178
- @c.to_hash[3].must_equal @c.all.first
228
+ @c.as_hash.must_equal(3=>@c.load(:id=>3))
229
+ @c.as_hash[3].must_equal @c.all.first
179
230
  @db.sqls.must_equal ['SELECT * FROM t2']
180
231
  end
181
232
  end
@@ -238,18 +289,18 @@ describe "Sequel::Plugins::StaticCache" do
238
289
  a.last.must_be_same_as(@c2)
239
290
  end
240
291
 
241
- it "should have to_hash without arguments use cached instances" do
242
- a = @c.to_hash
292
+ it "should have as_hash without arguments use cached instances" do
293
+ a = @c.as_hash
243
294
  a[1].must_be_same_as(@c1)
244
295
  a[2].must_be_same_as(@c2)
245
296
  end
246
297
 
247
- it "should have to_hash with arguments return cached instances" do
248
- a = @c.to_hash(:id)
298
+ it "should have as_hash with arguments return cached instances" do
299
+ a = @c.as_hash(:id)
249
300
  a[1].must_be_same_as(@c1)
250
301
  a[2].must_be_same_as(@c2)
251
302
 
252
- a = @c.to_hash([:id])
303
+ a = @c.as_hash([:id])
253
304
  a[[1]].must_be_same_as(@c1)
254
305
  a[[2]].must_be_same_as(@c2)
255
306
  end
@@ -313,16 +364,16 @@ describe "Sequel::Plugins::StaticCache" do
313
364
  @c.map.all?{|o| !o.frozen?}.must_equal true
314
365
  end
315
366
 
316
- it "none of values in the hash returned by to_hash without an argument should be frozen" do
317
- @c.to_hash.values.all?{|o| !o.frozen?}.must_equal true
367
+ it "none of values in the hash returned by as_hash without an argument should be frozen" do
368
+ @c.as_hash.values.all?{|o| !o.frozen?}.must_equal true
318
369
  end
319
370
 
320
- it "none of values in the hash returned by to_hash with a single argument should be frozen" do
321
- @c.to_hash(:id).values.all?{|o| !o.frozen?}.must_equal true
371
+ it "none of values in the hash returned by as_hash with a single argument should be frozen" do
372
+ @c.as_hash(:id).values.all?{|o| !o.frozen?}.must_equal true
322
373
  end
323
374
 
324
- it "none of values in the hash returned by to_hash with a single array argument should be frozen" do
325
- @c.to_hash([:id, :id]).values.all?{|o| !o.frozen?}.must_equal true
375
+ it "none of values in the hash returned by as_hash with a single array argument should be frozen" do
376
+ @c.as_hash([:id, :id]).values.all?{|o| !o.frozen?}.must_equal true
326
377
  end
327
378
 
328
379
  it "none of values in the hash returned by to_hash_groups with a single argument should be frozen" do
@@ -48,7 +48,7 @@ describe "string_agg extension" do
48
48
  it "should correctly literalize on MySQL, H2, HSQLDB" do
49
49
  [:mysql, :h2, :hsqldb].each do |type|
50
50
  db = dbf.call(type)
51
- db.meta_def(:database_type){type}
51
+ meta_def(db, :database_type){type}
52
52
  ds = db.dataset.with_quote_identifiers(false).with_extend{def input_identifier(v) v.to_s end}
53
53
  ds.literal(@sa1).upcase.must_equal "GROUP_CONCAT(C SEPARATOR ',')"
54
54
  ds.literal(@sa2).upcase.must_equal "GROUP_CONCAT(C SEPARATOR '-')"
@@ -67,6 +67,15 @@ describe "Touch plugin" do
67
67
  "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
68
68
  end
69
69
 
70
+ it "should clear associations after touching them :associations option" do
71
+ @Artist.plugin :touch, :associations=>:albums
72
+ @a.associations[:albums] = [@Album.call(:id=>1)]
73
+ @a.touch
74
+ @a.associations[:albums].must_be_nil
75
+ DB.sqls.must_equal ["UPDATE artists SET updated_at = CURRENT_TIMESTAMP WHERE (id = 1)",
76
+ "UPDATE albums SET updated_at = CURRENT_TIMESTAMP WHERE (albums.artist_id = 1)"]
77
+ end
78
+
70
79
  it "should be able to give an array to the :associations option specifying multiple associations" do
71
80
  @Album.plugin :touch, :associations=>[:artist, :followup_albums]
72
81
  @Album.load(:id=>4, :artist_id=>1).touch
@@ -18,6 +18,12 @@ describe "Sequel::Plugins::ValidationHelpers" do
18
18
  @m.wont_be :valid?
19
19
  @m.value = '1_1'
20
20
  @m.must_be :valid?
21
+ o = String.new
22
+ class << o
23
+ undef_method :blank?
24
+ end
25
+ @m.value = o
26
+ @m.must_be :valid?
21
27
  o = Object.new
22
28
  @m.value = o
23
29
  @m.wont_be :valid?
@@ -248,17 +254,17 @@ describe "Sequel::Plugins::ValidationHelpers" do
248
254
  @m.must_be :valid?
249
255
  @m.value = '123'
250
256
  @m.must_be :valid?
251
- @m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
257
+ def @m.db_schema; {:value=>{:type=>:integer}} end
252
258
  @m.wont_be :valid?
253
259
  @m.errors.full_messages.must_equal ['value is not a valid integer']
254
260
 
255
261
  @c.set_validations{validates_schema_types(:value)}
256
- @m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
262
+ def @m.db_schema; {:value=>{:type=>:integer}} end
257
263
  @m.wont_be :valid?
258
264
  @m.errors.full_messages.must_equal ['value is not a valid integer']
259
265
 
260
266
  @c.set_validations{validates_schema_types(:value, :message=>'is bad')}
261
- @m.meta_def(:db_schema){{:value=>{:type=>:integer}}}
267
+ def @m.db_schema; {:value=>{:type=>:integer}} end
262
268
  @m.wont_be :valid?
263
269
  @m.errors.full_messages.must_equal ['value is bad']
264
270
  end
@@ -64,6 +64,19 @@ describe Sequel::Model, "#(set|update)_(all|only)" do
64
64
  end
65
65
  end
66
66
 
67
+ describe Sequel::Model, "#(set|update)_(all|only) without set_allowed_columns" do
68
+ before do
69
+ @c = Class.new(Sequel::Model(:items)) do
70
+ set_primary_key :id
71
+ columns :x, :y, :z, :id
72
+ end
73
+ @c.plugin :whitelist_security
74
+ @c.strict_param_setting = false
75
+ @o1 = @c.new
76
+ DB.reset
77
+ end
78
+ end
79
+
67
80
  describe Sequel::Model, ".strict_param_setting" do
68
81
  before do
69
82
  @c = Class.new(Sequel::Model(:blahblah)) do
@@ -105,6 +118,19 @@ describe Sequel::Model, ".allowed_columns " do
105
118
  @c.allowed_columns.must_equal [:x, :y]
106
119
  end
107
120
 
121
+ it "should not change behavior if allowed_columns are not set" do
122
+ i = @c.new(:x => 1, :y => 2, :z => 3)
123
+ i.values.must_equal(:x => 1, :y => 2, :z => 3)
124
+ i.set(:x => 4, :y => 5, :z => 6)
125
+ i.values.must_equal(:x => 4, :y => 5, :z => 6)
126
+
127
+ @c.dataset = @c.dataset.with_fetch(:x => 7)
128
+ i = @c.new
129
+ i.update(:x => 7)
130
+ i.values.must_equal(:x => 7)
131
+ DB.sqls.must_equal ["INSERT INTO blahblah (x) VALUES (7)", "SELECT * FROM blahblah WHERE id = 10"]
132
+ end
133
+
108
134
  it "should only set allowed columns by default" do
109
135
  @c.set_allowed_columns :x, :y
110
136
  i = @c.new(:x => 1, :y => 2, :z => 3)