sequel 3.12.1 → 3.13.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +42 -0
- data/README.rdoc +137 -118
- data/Rakefile +21 -66
- data/doc/active_record.rdoc +9 -9
- data/doc/advanced_associations.rdoc +59 -188
- data/doc/association_basics.rdoc +15 -2
- data/doc/cheat_sheet.rdoc +38 -33
- data/doc/dataset_filtering.rdoc +16 -7
- data/doc/prepared_statements.rdoc +7 -7
- data/doc/querying.rdoc +5 -4
- data/doc/release_notes/3.13.0.txt +210 -0
- data/doc/sharding.rdoc +1 -1
- data/doc/sql.rdoc +5 -5
- data/doc/validations.rdoc +11 -11
- data/lib/sequel/adapters/ado.rb +1 -1
- data/lib/sequel/adapters/do.rb +3 -3
- data/lib/sequel/adapters/firebird.rb +3 -3
- data/lib/sequel/adapters/jdbc/h2.rb +39 -0
- data/lib/sequel/adapters/jdbc/mysql.rb +5 -0
- data/lib/sequel/adapters/jdbc/oracle.rb +3 -3
- data/lib/sequel/adapters/mysql.rb +7 -4
- data/lib/sequel/adapters/oracle.rb +3 -3
- data/lib/sequel/adapters/shared/mssql.rb +10 -1
- data/lib/sequel/adapters/shared/mysql.rb +63 -0
- data/lib/sequel/adapters/shared/postgres.rb +61 -3
- data/lib/sequel/adapters/sqlite.rb +105 -18
- data/lib/sequel/connection_pool.rb +31 -30
- data/lib/sequel/core.rb +58 -58
- data/lib/sequel/core_sql.rb +52 -43
- data/lib/sequel/database/misc.rb +11 -0
- data/lib/sequel/database/query.rb +55 -17
- data/lib/sequel/dataset/actions.rb +2 -1
- data/lib/sequel/dataset/query.rb +2 -3
- data/lib/sequel/dataset/sql.rb +24 -11
- data/lib/sequel/extensions/schema_dumper.rb +1 -1
- data/lib/sequel/metaprogramming.rb +4 -0
- data/lib/sequel/model.rb +37 -19
- data/lib/sequel/model/associations.rb +33 -25
- data/lib/sequel/model/base.rb +2 -2
- data/lib/sequel/model/plugins.rb +7 -2
- data/lib/sequel/plugins/active_model.rb +1 -1
- data/lib/sequel/plugins/association_pks.rb +2 -2
- data/lib/sequel/plugins/association_proxies.rb +1 -1
- data/lib/sequel/plugins/boolean_readers.rb +2 -2
- data/lib/sequel/plugins/class_table_inheritance.rb +10 -2
- data/lib/sequel/plugins/identity_map.rb +3 -3
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +212 -0
- data/lib/sequel/plugins/lazy_attributes.rb +1 -1
- data/lib/sequel/plugins/list.rb +174 -0
- data/lib/sequel/plugins/many_through_many.rb +2 -2
- data/lib/sequel/plugins/rcte_tree.rb +6 -7
- data/lib/sequel/plugins/tree.rb +118 -0
- data/lib/sequel/plugins/xml_serializer.rb +321 -0
- data/lib/sequel/sql.rb +315 -206
- data/lib/sequel/timezones.rb +40 -17
- data/lib/sequel/version.rb +8 -2
- data/spec/adapters/firebird_spec.rb +2 -2
- data/spec/adapters/informix_spec.rb +1 -1
- data/spec/adapters/mssql_spec.rb +2 -2
- data/spec/adapters/mysql_spec.rb +2 -2
- data/spec/adapters/oracle_spec.rb +1 -1
- data/spec/adapters/postgres_spec.rb +36 -6
- data/spec/adapters/spec_helper.rb +2 -2
- data/spec/adapters/sqlite_spec.rb +1 -1
- data/spec/core/connection_pool_spec.rb +3 -3
- data/spec/core/core_sql_spec.rb +31 -13
- data/spec/core/database_spec.rb +39 -2
- data/spec/core/dataset_spec.rb +24 -12
- data/spec/core/expression_filters_spec.rb +5 -1
- data/spec/core/object_graph_spec.rb +1 -1
- data/spec/core/schema_generator_spec.rb +1 -1
- data/spec/core/schema_spec.rb +1 -1
- data/spec/core/spec_helper.rb +1 -1
- data/spec/core/version_spec.rb +1 -1
- data/spec/extensions/active_model_spec.rb +82 -67
- data/spec/extensions/association_dependencies_spec.rb +1 -1
- data/spec/extensions/association_pks_spec.rb +1 -1
- data/spec/extensions/association_proxies_spec.rb +1 -1
- data/spec/extensions/blank_spec.rb +1 -1
- data/spec/extensions/boolean_readers_spec.rb +1 -1
- data/spec/extensions/caching_spec.rb +1 -1
- data/spec/extensions/class_table_inheritance_spec.rb +3 -2
- data/spec/extensions/composition_spec.rb +2 -5
- data/spec/extensions/force_encoding_spec.rb +3 -1
- data/spec/extensions/hook_class_methods_spec.rb +1 -1
- data/spec/extensions/identity_map_spec.rb +1 -1
- data/spec/extensions/inflector_spec.rb +1 -1
- data/spec/extensions/instance_filters_spec.rb +1 -1
- data/spec/extensions/instance_hooks_spec.rb +1 -1
- data/spec/extensions/json_serializer_spec.rb +154 -0
- data/spec/extensions/lazy_attributes_spec.rb +1 -2
- data/spec/extensions/list_spec.rb +251 -0
- data/spec/extensions/looser_typecasting_spec.rb +1 -1
- data/spec/extensions/many_through_many_spec.rb +3 -3
- data/spec/extensions/migration_spec.rb +1 -1
- data/spec/extensions/named_timezones_spec.rb +5 -6
- data/spec/extensions/nested_attributes_spec.rb +1 -1
- data/spec/extensions/optimistic_locking_spec.rb +1 -1
- data/spec/extensions/pagination_spec.rb +1 -1
- data/spec/extensions/pretty_table_spec.rb +1 -1
- data/spec/extensions/query_spec.rb +1 -1
- data/spec/extensions/rcte_tree_spec.rb +1 -1
- data/spec/extensions/schema_dumper_spec.rb +3 -2
- data/spec/extensions/schema_spec.rb +1 -1
- data/spec/extensions/serialization_spec.rb +6 -2
- data/spec/extensions/sharding_spec.rb +1 -1
- data/spec/extensions/single_table_inheritance_spec.rb +1 -1
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +7 -3
- data/spec/extensions/sql_expr_spec.rb +1 -1
- data/spec/extensions/string_date_time_spec.rb +1 -1
- data/spec/extensions/string_stripper_spec.rb +1 -1
- data/spec/extensions/subclasses_spec.rb +1 -1
- data/spec/extensions/tactical_eager_loading_spec.rb +1 -1
- data/spec/extensions/thread_local_timezones_spec.rb +1 -1
- data/spec/extensions/timestamps_spec.rb +1 -1
- data/spec/extensions/touch_spec.rb +1 -1
- data/spec/extensions/tree_spec.rb +119 -0
- data/spec/extensions/typecast_on_load_spec.rb +1 -1
- data/spec/extensions/update_primary_key_spec.rb +1 -1
- data/spec/extensions/validation_class_methods_spec.rb +1 -1
- data/spec/extensions/validation_helpers_spec.rb +1 -1
- data/spec/extensions/xml_serializer_spec.rb +142 -0
- data/spec/integration/associations_test.rb +1 -1
- data/spec/integration/database_test.rb +1 -1
- data/spec/integration/dataset_test.rb +29 -14
- data/spec/integration/eager_loader_test.rb +1 -1
- data/spec/integration/migrator_test.rb +1 -1
- data/spec/integration/model_test.rb +1 -1
- data/spec/integration/plugin_test.rb +316 -1
- data/spec/integration/prepared_statement_test.rb +1 -1
- data/spec/integration/schema_test.rb +8 -8
- data/spec/integration/spec_helper.rb +1 -1
- data/spec/integration/timezone_test.rb +1 -1
- data/spec/integration/transaction_test.rb +35 -20
- data/spec/integration/type_test.rb +1 -1
- data/spec/model/association_reflection_spec.rb +1 -1
- data/spec/model/associations_spec.rb +49 -34
- data/spec/model/base_spec.rb +1 -1
- data/spec/model/dataset_methods_spec.rb +4 -4
- data/spec/model/eager_loading_spec.rb +1 -1
- data/spec/model/hooks_spec.rb +1 -1
- data/spec/model/inflector_spec.rb +1 -1
- data/spec/model/model_spec.rb +7 -1
- data/spec/model/plugins_spec.rb +1 -1
- data/spec/model/record_spec.rb +1 -3
- data/spec/model/spec_helper.rb +2 -2
- data/spec/model/validations_spec.rb +1 -1
- metadata +29 -5
data/spec/core/dataset_spec.rb
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
context "Dataset" do
|
|
4
4
|
before do
|
|
@@ -465,6 +465,7 @@ context "Dataset#where" do
|
|
|
465
465
|
@dataset.filter([:id1, :id2] => @d1.select(:id1, :id2)).sql.should == "SELECT * FROM test WHERE ((id1, id2) IN (SELECT id1, id2 FROM test WHERE (region = 'Asia')))"
|
|
466
466
|
@dataset.filter([:id1, :id2] => []).sql.should == "SELECT * FROM test WHERE ((id1 != id1) AND (id2 != id2))"
|
|
467
467
|
@dataset.filter([:id1, :id2] => [[1, 2], [3,4]].sql_array).sql.should == "SELECT * FROM test WHERE ((id1, id2) IN ((1, 2), (3, 4)))"
|
|
468
|
+
@dataset.filter([:id1, :id2] => [[1, 2], [3,4]]).sql.should == "SELECT * FROM test WHERE ((id1, id2) IN ((1, 2), (3, 4)))"
|
|
468
469
|
|
|
469
470
|
@dataset.exclude(:id => @d1.select(:id)).sql.should == "SELECT * FROM test WHERE (id NOT IN (SELECT id FROM test WHERE (region = 'Asia')))"
|
|
470
471
|
@dataset.exclude(:id => []).sql.should == "SELECT * FROM test WHERE (1 = 1)"
|
|
@@ -472,6 +473,7 @@ context "Dataset#where" do
|
|
|
472
473
|
@dataset.exclude([:id1, :id2] => @d1.select(:id1, :id2)).sql.should == "SELECT * FROM test WHERE ((id1, id2) NOT IN (SELECT id1, id2 FROM test WHERE (region = 'Asia')))"
|
|
473
474
|
@dataset.exclude([:id1, :id2] => []).sql.should == "SELECT * FROM test WHERE (1 = 1)"
|
|
474
475
|
@dataset.exclude([:id1, :id2] => [[1, 2], [3,4]].sql_array).sql.should == "SELECT * FROM test WHERE ((id1, id2) NOT IN ((1, 2), (3, 4)))"
|
|
476
|
+
@dataset.exclude([:id1, :id2] => [[1, 2], [3,4]]).sql.should == "SELECT * FROM test WHERE ((id1, id2) NOT IN ((1, 2), (3, 4)))"
|
|
475
477
|
end
|
|
476
478
|
|
|
477
479
|
specify "should handle IN/NOT IN queries with multiple columns and an array where the database doesn't support it" do
|
|
@@ -1204,6 +1206,11 @@ context "Dataset#order" do
|
|
|
1204
1206
|
'SELECT * FROM test ORDER BY name, price DESC'
|
|
1205
1207
|
end
|
|
1206
1208
|
|
|
1209
|
+
specify "should accept :nulls options for asc and desc" do
|
|
1210
|
+
@dataset.order(:name.asc(:nulls=>:last), :price.desc(:nulls=>:first)).sql.should ==
|
|
1211
|
+
'SELECT * FROM test ORDER BY name ASC NULLS LAST, price DESC NULLS FIRST'
|
|
1212
|
+
end
|
|
1213
|
+
|
|
1207
1214
|
specify "should overrun a previous ordering" do
|
|
1208
1215
|
@dataset.order(:name).order(:stamp).sql.should ==
|
|
1209
1216
|
'SELECT * FROM test ORDER BY stamp'
|
|
@@ -1385,6 +1392,11 @@ context "Dataset#reverse_order" do
|
|
|
1385
1392
|
'SELECT * FROM test ORDER BY name DESC, price ASC'
|
|
1386
1393
|
end
|
|
1387
1394
|
|
|
1395
|
+
specify "should handles NULLS ordering correctly when reversing" do
|
|
1396
|
+
@dataset.reverse_order(:name.asc(:nulls=>:first), :price.desc(:nulls=>:last)).sql.should ==
|
|
1397
|
+
'SELECT * FROM test ORDER BY name DESC NULLS LAST, price ASC NULLS FIRST'
|
|
1398
|
+
end
|
|
1399
|
+
|
|
1388
1400
|
specify "should reverse a previous ordering if no arguments are given" do
|
|
1389
1401
|
@dataset.order(:name).reverse_order.sql.should ==
|
|
1390
1402
|
'SELECT * FROM test ORDER BY name DESC'
|
|
@@ -2185,12 +2197,12 @@ end
|
|
|
2185
2197
|
context "Dataset#range" do
|
|
2186
2198
|
before do
|
|
2187
2199
|
c = Class.new(Sequel::Dataset) do
|
|
2188
|
-
|
|
2200
|
+
class_variable_set(:@@sql, nil)
|
|
2189
2201
|
|
|
2190
|
-
def last_sql;
|
|
2202
|
+
def last_sql; self.class.send(:class_variable_get, :@@sql); end
|
|
2191
2203
|
|
|
2192
2204
|
def fetch_rows(sql)
|
|
2193
|
-
|
|
2205
|
+
self.class.send(:class_variable_set, :@@sql, sql)
|
|
2194
2206
|
yield(:v1 => 1, :v2 => 10)
|
|
2195
2207
|
end
|
|
2196
2208
|
end
|
|
@@ -2218,12 +2230,12 @@ end
|
|
|
2218
2230
|
context "Dataset#interval" do
|
|
2219
2231
|
before do
|
|
2220
2232
|
c = Class.new(Sequel::Dataset) do
|
|
2221
|
-
|
|
2233
|
+
class_variable_set(:@@sql, nil)
|
|
2222
2234
|
|
|
2223
|
-
def last_sql;
|
|
2235
|
+
def last_sql; self.class.send(:class_variable_get, :@@sql); end
|
|
2224
2236
|
|
|
2225
2237
|
def fetch_rows(sql)
|
|
2226
|
-
|
|
2238
|
+
self.class.send(:class_variable_set, :@@sql, sql)
|
|
2227
2239
|
yield(:v => 1234)
|
|
2228
2240
|
end
|
|
2229
2241
|
end
|
|
@@ -2428,14 +2440,14 @@ end
|
|
|
2428
2440
|
context "Dataset#[]" do
|
|
2429
2441
|
before do
|
|
2430
2442
|
@c = Class.new(Sequel::Dataset) do
|
|
2431
|
-
|
|
2443
|
+
class_variable_set(:@@last_dataset, nil)
|
|
2432
2444
|
|
|
2433
2445
|
def self.last_dataset
|
|
2434
|
-
|
|
2446
|
+
class_variable_get(:@@last_dataset)
|
|
2435
2447
|
end
|
|
2436
2448
|
|
|
2437
2449
|
def single_record
|
|
2438
|
-
|
|
2450
|
+
self.class.send(:class_variable_set, :@@last_dataset, opts ? clone(opts) : self)
|
|
2439
2451
|
{1 => 2, 3 => 4}
|
|
2440
2452
|
end
|
|
2441
2453
|
end
|
|
@@ -3443,8 +3455,8 @@ context "Sequel::Dataset#qualify_to_first_source" do
|
|
|
3443
3455
|
@ds.filter{(a+b)<(c-3)}.qualify_to_first_source.sql.should == 'SELECT t.* FROM t WHERE ((t.a + t.b) < (t.c - 3))'
|
|
3444
3456
|
end
|
|
3445
3457
|
|
|
3446
|
-
specify "should handle SQL::
|
|
3447
|
-
@ds.filter(:a=>[:b, :c].
|
|
3458
|
+
specify "should handle SQL::ValueLists" do
|
|
3459
|
+
@ds.filter(:a=>[:b, :c].sql_value_list).qualify_to_first_source.sql.should == 'SELECT t.* FROM t WHERE (t.a IN (t.b, t.c))'
|
|
3448
3460
|
end
|
|
3449
3461
|
|
|
3450
3462
|
specify "should handle SQL::Subscripts" do
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), 'spec_helper')
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
2
|
|
|
3
3
|
Regexp.send(:include, Sequel::SQL::StringMethods)
|
|
4
4
|
String.send(:include, Sequel::SQL::StringMethods)
|
|
@@ -556,6 +556,10 @@ context Sequel::SQL::VirtualRow do
|
|
|
556
556
|
@d.l{rank(:over, :frame=>:rows){}}.should == 'rank() OVER (ROWS UNBOUNDED PRECEDING)'
|
|
557
557
|
end
|
|
558
558
|
|
|
559
|
+
it "should support :frame=>'some string' option for window function calls" do
|
|
560
|
+
@d.l{rank(:over, :frame=>'RANGE BETWEEN 3 PRECEDING AND CURRENT ROW'){}}.should == 'rank() OVER (RANGE BETWEEN 3 PRECEDING AND CURRENT ROW)'
|
|
561
|
+
end
|
|
562
|
+
|
|
559
563
|
it "should raise an error if an invalid :frame option is used" do
|
|
560
564
|
proc{@d.l{rank(:over, :frame=>:blah){}}}.should raise_error(Sequel::Error)
|
|
561
565
|
end
|
data/spec/core/schema_spec.rb
CHANGED
data/spec/core/spec_helper.rb
CHANGED
data/spec/core/version_spec.rb
CHANGED
|
@@ -1,76 +1,91 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
2
|
-
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'active_model'
|
|
5
|
+
require 'test/unit'
|
|
6
|
+
if Test::Unit.respond_to?(:run=)
|
|
7
|
+
Test::Unit.run = false
|
|
8
|
+
require 'test/unit/testresult'
|
|
9
|
+
elsif defined?(MiniTest::Unit)
|
|
10
|
+
class << MiniTest::Unit
|
|
11
|
+
def autorun; end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
rescue LoadError => e
|
|
15
|
+
skip_warn "active_model plugin: can't load active_model (#{e.class}: #{e})"
|
|
16
|
+
else
|
|
3
17
|
describe "ActiveModel plugin" do
|
|
4
18
|
specify "should be compliant to the ActiveModel spec" do
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
end
|
|
25
|
-
@c.plugin :active_model
|
|
26
|
-
@m = @model = @c.new
|
|
27
|
-
@o = @c.load({})
|
|
28
|
-
end
|
|
29
|
-
include ActiveModel::Lint::Tests
|
|
19
|
+
tc = Class.new(Test::Unit::TestCase)
|
|
20
|
+
tc.class_eval do
|
|
21
|
+
define_method(:setup) do
|
|
22
|
+
class ::AMLintTest < Sequel::Model
|
|
23
|
+
set_primary_key :id
|
|
24
|
+
columns :id, :id2
|
|
25
|
+
def delete; end
|
|
26
|
+
end
|
|
27
|
+
@c = AMLintTest
|
|
28
|
+
@c.plugin :active_model
|
|
29
|
+
@m = @model = @c.new
|
|
30
|
+
@o = @c.load({})
|
|
31
|
+
super()
|
|
32
|
+
end
|
|
33
|
+
def teardown
|
|
34
|
+
super
|
|
35
|
+
Object.send(:remove_const, :AMLintTest)
|
|
36
|
+
end
|
|
37
|
+
include ActiveModel::Lint::Tests
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
39
|
+
# Should return self, not a proxy object
|
|
40
|
+
def test__to_model
|
|
41
|
+
assert_equal @m.to_model.object_id.should, @m.object_id
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def test__to_key
|
|
45
|
+
assert_equal nil, @m.to_key
|
|
46
|
+
@o.id = 1
|
|
47
|
+
assert_equal [1], @o.to_key
|
|
48
|
+
@c.set_primary_key [:id2, :id]
|
|
49
|
+
@o.id2 = 2
|
|
50
|
+
assert_equal [2, 1], @o.to_key
|
|
51
|
+
@o.destroy
|
|
52
|
+
assert_equal nil, @o.to_key
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test__to_param
|
|
56
|
+
assert_equal nil, @m.to_param
|
|
57
|
+
@o.id = 1
|
|
58
|
+
assert_equal '1', @o.to_param
|
|
59
|
+
@c.set_primary_key [:id2, :id]
|
|
60
|
+
@o.id2 = 2
|
|
61
|
+
assert_equal '2-1', @o.to_param
|
|
62
|
+
@o.meta_def(:to_param_joiner){'|'}
|
|
63
|
+
assert_equal '2|1', @o.to_param
|
|
64
|
+
@o.destroy
|
|
65
|
+
assert_equal nil, @o.to_param
|
|
66
|
+
end
|
|
59
67
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
68
|
+
def test__persisted?
|
|
69
|
+
assert_equal false, @m.persisted?
|
|
70
|
+
assert_equal true, @o.persisted?
|
|
71
|
+
@m.destroy
|
|
72
|
+
@o.destroy
|
|
73
|
+
assert_equal false, @m.persisted?
|
|
74
|
+
assert_equal false, @o.persisted?
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
if defined?(MiniTest::Unit)
|
|
78
|
+
tc.instance_methods.map{|x| x.to_s}.reject{|n| n !~ /\Atest_/}.each do |m|
|
|
79
|
+
i = tc.new(m)
|
|
80
|
+
i.setup
|
|
81
|
+
i.send(m)
|
|
82
|
+
i.teardown
|
|
71
83
|
end
|
|
84
|
+
else
|
|
85
|
+
res = ::Test::Unit::TestResult.new
|
|
86
|
+
tc.suite.run(res){}
|
|
87
|
+
res.failure_count.should == 0
|
|
72
88
|
end
|
|
73
|
-
s.should =~ /0 failures, 0 errors/
|
|
74
89
|
end
|
|
75
90
|
end
|
|
76
91
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
3
|
describe "class_table_inheritance plugin" do
|
|
4
4
|
before do
|
|
@@ -88,7 +88,8 @@ describe "class_table_inheritance plugin" do
|
|
|
88
88
|
|
|
89
89
|
it "should return rows with the current class if cti_key is nil" do
|
|
90
90
|
Employee.plugin(:class_table_inheritance)
|
|
91
|
-
|
|
91
|
+
ds = Employee.dataset
|
|
92
|
+
def ds.fetch_rows(sql)
|
|
92
93
|
yield({:kind=>'Employee'})
|
|
93
94
|
yield({:kind=>'Manager'})
|
|
94
95
|
yield({:kind=>'Executive'})
|
|
@@ -1,9 +1,6 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
require 'json'
|
|
5
|
-
|
|
6
|
-
describe "Serialization plugin" do
|
|
3
|
+
describe "Composition plugin" do
|
|
7
4
|
before do
|
|
8
5
|
@c = Class.new(Sequel::Model(:items))
|
|
9
6
|
@c.plugin :composition
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
require File.join(File.dirname(__FILE__), "spec_helper")
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
2
|
if RUBY_VERSION >= '1.9.0'
|
|
3
3
|
describe "force_encoding plugin" do
|
|
4
4
|
before do
|
|
@@ -114,4 +114,6 @@ describe "force_encoding plugin" do
|
|
|
114
114
|
end
|
|
115
115
|
end
|
|
116
116
|
end
|
|
117
|
+
else
|
|
118
|
+
skip_warn "force_encoding plugin: only works on ruby 1.9"
|
|
117
119
|
end
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
begin
|
|
4
|
+
require 'json'
|
|
5
|
+
rescue LoadError => e
|
|
6
|
+
skip_warn "json_serializer plugin: can't load json (#{e.class}: #{e})"
|
|
7
|
+
else
|
|
8
|
+
describe "Sequel::Plugins::JsonSerializer" do
|
|
9
|
+
before do
|
|
10
|
+
class ::Artist < Sequel::Model
|
|
11
|
+
plugin :json_serializer
|
|
12
|
+
columns :id, :name
|
|
13
|
+
one_to_many :albums
|
|
14
|
+
end
|
|
15
|
+
class ::Album < Sequel::Model
|
|
16
|
+
attr_accessor :blah
|
|
17
|
+
plugin :json_serializer
|
|
18
|
+
columns :id, :name, :artist_id
|
|
19
|
+
many_to_one :artist
|
|
20
|
+
end
|
|
21
|
+
@artist = Artist.load(:id=>2, :name=>'YJM')
|
|
22
|
+
@artist.associations[:albums] = []
|
|
23
|
+
@album = Album.load(:id=>1, :name=>'RF')
|
|
24
|
+
@album.artist = @artist
|
|
25
|
+
@album.blah = 'Blah'
|
|
26
|
+
end
|
|
27
|
+
after do
|
|
28
|
+
Object.send(:remove_const, :Artist)
|
|
29
|
+
Object.send(:remove_const, :Album)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
it "should round trip successfully" do
|
|
33
|
+
JSON.parse(@artist.to_json).should == @artist
|
|
34
|
+
JSON.parse(@album.to_json).should == @album
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
it "should handle the :only option" do
|
|
38
|
+
JSON.parse(@artist.to_json(:only=>:name)).should == Artist.load(:name=>@artist.name)
|
|
39
|
+
JSON.parse(@album.to_json(:only=>[:id, :name])).should == Album.load(:id=>@album.id, :name=>@album.name)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
it "should handle the :except option" do
|
|
43
|
+
JSON.parse(@artist.to_json(:except=>:id)).should == Artist.load(:name=>@artist.name)
|
|
44
|
+
JSON.parse(@album.to_json(:except=>[:id, :artist_id])).should == Album.load(:name=>@album.name)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should handle the :include option for associations" do
|
|
48
|
+
JSON.parse(@artist.to_json(:include=>:albums)).albums.should == [@album]
|
|
49
|
+
JSON.parse(@album.to_json(:include=>:artist)).artist.should == @artist
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should handle the :include option for arbitrary attributes" do
|
|
53
|
+
JSON.parse(@album.to_json(:include=>:blah)).blah.should == @album.blah
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
it "should handle multiple inclusions using an array for the :include option" do
|
|
57
|
+
a = JSON.parse(@album.to_json(:include=>[:blah, :artist]))
|
|
58
|
+
a.blah.should == @album.blah
|
|
59
|
+
a.artist.should == @artist
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should handle cascading using a hash for the :include option" do
|
|
63
|
+
JSON.parse(@artist.to_json(:include=>{:albums=>{:include=>:artist}})).albums.map{|a| a.artist}.should == [@artist]
|
|
64
|
+
JSON.parse(@album.to_json(:include=>{:artist=>{:include=>:albums}})).artist.albums.should == [@album]
|
|
65
|
+
|
|
66
|
+
JSON.parse(@artist.to_json(:include=>{:albums=>{:only=>:name}})).albums.should == [Album.load(:name=>@album.name)]
|
|
67
|
+
JSON.parse(@album.to_json(:include=>{:artist=>{:except=>:name}})).artist.should == Artist.load(:id=>@artist.id)
|
|
68
|
+
|
|
69
|
+
JSON.parse(@artist.to_json(:include=>{:albums=>{:include=>{:artist=>{:include=>:albums}}}})).albums.map{|a| a.artist.albums}.should == [[@album]]
|
|
70
|
+
JSON.parse(@album.to_json(:include=>{:artist=>{:include=>{:albums=>{:only=>:name}}}})).artist.albums.should == [Album.load(:name=>@album.name)]
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
it "should handle the :include option cascading with an empty hash" do
|
|
74
|
+
JSON.parse(@album.to_json(:include=>{:artist=>{}})).artist.should == @artist
|
|
75
|
+
JSON.parse(@album.to_json(:include=>{:blah=>{}})).blah.should == @album.blah
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
it "should accept a :naked option to not include the JSON.create_id, so parsing yields a plain hash" do
|
|
79
|
+
JSON.parse(@album.to_json(:naked=>true)).should == @album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
it "should support #from_json to set column values" do
|
|
83
|
+
@artist.from_json('{"name": "AS"}')
|
|
84
|
+
@artist.name.should == 'AS'
|
|
85
|
+
@artist.id.should == 2
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
it "should raise an exception for json keys that aren't associations, columns, or setter methods" do
|
|
89
|
+
Album.send(:undef_method, :blah=)
|
|
90
|
+
proc{JSON.parse(@album.to_json(:include=>:blah))}.should raise_error(Sequel::Error)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
it "should support a to_json class and dataset method" do
|
|
94
|
+
album = @album
|
|
95
|
+
Album.dataset.meta_def(:all){[album]}
|
|
96
|
+
JSON.parse(Album.to_json).should == [@album]
|
|
97
|
+
JSON.parse(Album.to_json(:include=>:artist)).map{|x| x.artist}.should == [@artist]
|
|
98
|
+
JSON.parse(Album.dataset.to_json(:only=>:name)).should == [Album.load(:name=>@album.name)]
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should have dataset to_json method work with naked datasets" do
|
|
102
|
+
album = @album
|
|
103
|
+
ds = Album.dataset.naked
|
|
104
|
+
ds.meta_def(:all){[album.values]}
|
|
105
|
+
JSON.parse(ds.to_json).should == [@album.values.inject({}){|h, (k, v)| h[k.to_s] = v; h}]
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
it "should propagate class default options to instance to_json output" do
|
|
109
|
+
class ::Album2 < Sequel::Model
|
|
110
|
+
attr_accessor :blah
|
|
111
|
+
plugin :json_serializer, :naked => true, :except => :id
|
|
112
|
+
columns :id, :name, :artist_id
|
|
113
|
+
many_to_one :artist
|
|
114
|
+
end
|
|
115
|
+
@album2 = Album2.load(:id=>2, :name=>'JK')
|
|
116
|
+
@album2.artist = @artist
|
|
117
|
+
@album2.blah = 'Gak'
|
|
118
|
+
JSON.parse(@album2.to_json).should == @album2.values.reject{|k,v| k.to_s == 'id'}.inject({}){|h, (k, v)| h[k.to_s] = v; h}
|
|
119
|
+
JSON.parse(@album2.to_json(:only => :name)).should == @album2.values.reject{|k,v| k.to_s != 'name'}.inject({}){|h, (k, v)| h[k.to_s] = v; h}
|
|
120
|
+
JSON.parse(@album2.to_json(:except => :artist_id)).should == @album2.values.reject{|k,v| k.to_s == 'artist_id'}.inject({}){|h, (k, v)| h[k.to_s] = v; h}
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
it "should handle the :root option to qualify single records" do
|
|
124
|
+
@album.to_json(:root=>true, :except => [:name, :artist_id]).to_s.should == '{"album":{"id":1}}'
|
|
125
|
+
@album.to_json(:root=>true, :only => :name).to_s.should == '{"album":{"name":"RF"}}'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
it "should handle the :root option to qualify a dataset of records" do
|
|
129
|
+
album = @album
|
|
130
|
+
Album.dataset.meta_def(:all){[album, album]}
|
|
131
|
+
Album.dataset.to_json(:root=>true, :only => :id).to_s.should == '{"albums":[{"album":{"id":1}},{"album":{"id":1}}]}'
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
it "should store the default options in json_serializer_opts" do
|
|
135
|
+
Album.json_serializer_opts.should == {}
|
|
136
|
+
c = Class.new(Album)
|
|
137
|
+
c.plugin :json_serializer, :naked=>true
|
|
138
|
+
c.json_serializer_opts.should == {:naked=>true}
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
it "should work correctly when subclassing" do
|
|
142
|
+
class ::Artist2 < Artist
|
|
143
|
+
plugin :json_serializer, :only=>:name
|
|
144
|
+
end
|
|
145
|
+
JSON.parse(Artist2.load(:id=>2, :name=>'YYY').to_json).should == Artist2.load(:name=>'YYY')
|
|
146
|
+
class ::Artist3 < Artist2
|
|
147
|
+
plugin :json_serializer, :naked=>:true
|
|
148
|
+
end
|
|
149
|
+
JSON.parse(Artist3.load(:id=>2, :name=>'YYY').to_json).should == {"name"=>'YYY'}
|
|
150
|
+
Object.send(:remove_const, :Artist2)
|
|
151
|
+
Object.send(:remove_const, :Artist3)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
end
|