sequel 2.11.0 → 2.12.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 (162) hide show
  1. data/CHANGELOG +168 -0
  2. data/README.rdoc +77 -95
  3. data/Rakefile +100 -80
  4. data/bin/sequel +2 -1
  5. data/doc/advanced_associations.rdoc +23 -32
  6. data/doc/cheat_sheet.rdoc +23 -40
  7. data/doc/dataset_filtering.rdoc +6 -6
  8. data/doc/prepared_statements.rdoc +22 -22
  9. data/doc/release_notes/2.12.0.txt +534 -0
  10. data/doc/schema.rdoc +3 -1
  11. data/doc/sharding.rdoc +8 -8
  12. data/doc/virtual_rows.rdoc +65 -0
  13. data/lib/sequel.rb +1 -1
  14. data/lib/{sequel_core → sequel}/adapters/ado.rb +3 -3
  15. data/lib/{sequel_core → sequel}/adapters/db2.rb +0 -0
  16. data/lib/{sequel_core → sequel}/adapters/dbi.rb +1 -1
  17. data/lib/{sequel_core → sequel}/adapters/do.rb +9 -5
  18. data/lib/{sequel_core → sequel}/adapters/do/mysql.rb +1 -1
  19. data/lib/{sequel_core → sequel}/adapters/do/postgres.rb +1 -1
  20. data/lib/{sequel_core → sequel}/adapters/do/sqlite.rb +1 -1
  21. data/lib/{sequel_core → sequel}/adapters/firebird.rb +84 -80
  22. data/lib/{sequel_core → sequel}/adapters/informix.rb +1 -1
  23. data/lib/{sequel_core → sequel}/adapters/jdbc.rb +21 -14
  24. data/lib/{sequel_core → sequel}/adapters/jdbc/h2.rb +14 -13
  25. data/lib/{sequel_core → sequel}/adapters/jdbc/mysql.rb +1 -1
  26. data/lib/{sequel_core → sequel}/adapters/jdbc/oracle.rb +1 -1
  27. data/lib/{sequel_core → sequel}/adapters/jdbc/postgresql.rb +1 -1
  28. data/lib/{sequel_core → sequel}/adapters/jdbc/sqlite.rb +1 -1
  29. data/lib/{sequel_core → sequel}/adapters/mysql.rb +60 -39
  30. data/lib/{sequel_core → sequel}/adapters/odbc.rb +8 -4
  31. data/lib/{sequel_core → sequel}/adapters/openbase.rb +0 -0
  32. data/lib/{sequel_core → sequel}/adapters/oracle.rb +38 -7
  33. data/lib/{sequel_core → sequel}/adapters/postgres.rb +24 -24
  34. data/lib/{sequel_core → sequel}/adapters/shared/mssql.rb +5 -5
  35. data/lib/{sequel_core → sequel}/adapters/shared/mysql.rb +126 -71
  36. data/lib/{sequel_core → sequel}/adapters/shared/oracle.rb +7 -10
  37. data/lib/{sequel_core → sequel}/adapters/shared/postgres.rb +159 -125
  38. data/lib/{sequel_core → sequel}/adapters/shared/progress.rb +1 -2
  39. data/lib/{sequel_core → sequel}/adapters/shared/sqlite.rb +72 -67
  40. data/lib/{sequel_core → sequel}/adapters/sqlite.rb +11 -7
  41. data/lib/{sequel_core → sequel}/adapters/utils/date_format.rb +0 -0
  42. data/lib/{sequel_core → sequel}/adapters/utils/stored_procedures.rb +0 -0
  43. data/lib/{sequel_core → sequel}/adapters/utils/unsupported.rb +19 -0
  44. data/lib/{sequel_core → sequel}/connection_pool.rb +7 -5
  45. data/lib/sequel/core.rb +221 -0
  46. data/lib/{sequel_core → sequel}/core_sql.rb +91 -49
  47. data/lib/{sequel_core → sequel}/database.rb +264 -149
  48. data/lib/{sequel_core/schema/generator.rb → sequel/database/schema_generator.rb} +6 -2
  49. data/lib/{sequel_core/database/schema.rb → sequel/database/schema_methods.rb} +12 -12
  50. data/lib/sequel/database/schema_sql.rb +224 -0
  51. data/lib/{sequel_core → sequel}/dataset.rb +78 -236
  52. data/lib/{sequel_core → sequel}/dataset/convenience.rb +99 -61
  53. data/lib/{sequel_core/object_graph.rb → sequel/dataset/graph.rb} +16 -14
  54. data/lib/{sequel_core → sequel}/dataset/prepared_statements.rb +1 -1
  55. data/lib/{sequel_core → sequel}/dataset/sql.rb +150 -99
  56. data/lib/sequel/deprecated.rb +593 -0
  57. data/lib/sequel/deprecated_migration.rb +91 -0
  58. data/lib/sequel/exceptions.rb +48 -0
  59. data/lib/sequel/extensions/blank.rb +42 -0
  60. data/lib/{sequel_model → sequel/extensions}/inflector.rb +8 -1
  61. data/lib/{sequel_core → sequel/extensions}/migration.rb +1 -1
  62. data/lib/{sequel_core/dataset → sequel/extensions}/pagination.rb +0 -0
  63. data/lib/{sequel_core → sequel/extensions}/pretty_table.rb +7 -0
  64. data/lib/{sequel_core/dataset → sequel/extensions}/query.rb +7 -0
  65. data/lib/sequel/extensions/string_date_time.rb +47 -0
  66. data/lib/sequel/metaprogramming.rb +43 -0
  67. data/lib/sequel/model.rb +110 -0
  68. data/lib/sequel/model/associations.rb +1300 -0
  69. data/lib/sequel/model/base.rb +937 -0
  70. data/lib/sequel/model/deprecated.rb +204 -0
  71. data/lib/sequel/model/deprecated_hooks.rb +103 -0
  72. data/lib/sequel/model/deprecated_inflector.rb +335 -0
  73. data/lib/sequel/model/deprecated_validations.rb +388 -0
  74. data/lib/sequel/model/errors.rb +39 -0
  75. data/lib/{sequel_model → sequel/model}/exceptions.rb +4 -4
  76. data/lib/sequel/model/inflections.rb +208 -0
  77. data/lib/sequel/model/plugins.rb +76 -0
  78. data/lib/sequel/plugins/caching.rb +122 -0
  79. data/lib/sequel/plugins/hook_class_methods.rb +122 -0
  80. data/lib/sequel/plugins/schema.rb +53 -0
  81. data/lib/sequel/plugins/serialization.rb +117 -0
  82. data/lib/sequel/plugins/single_table_inheritance.rb +63 -0
  83. data/lib/sequel/plugins/validation_class_methods.rb +384 -0
  84. data/lib/sequel/plugins/validation_helpers.rb +150 -0
  85. data/lib/{sequel_core → sequel}/sql.rb +125 -190
  86. data/lib/{sequel_core → sequel}/version.rb +2 -1
  87. data/lib/sequel_core.rb +1 -172
  88. data/lib/sequel_model.rb +1 -91
  89. data/spec/adapters/firebird_spec.rb +5 -5
  90. data/spec/adapters/informix_spec.rb +1 -1
  91. data/spec/adapters/mysql_spec.rb +128 -42
  92. data/spec/adapters/oracle_spec.rb +47 -19
  93. data/spec/adapters/postgres_spec.rb +64 -52
  94. data/spec/adapters/spec_helper.rb +1 -1
  95. data/spec/adapters/sqlite_spec.rb +12 -17
  96. data/spec/{sequel_core → core}/connection_pool_spec.rb +10 -10
  97. data/spec/{sequel_core → core}/core_ext_spec.rb +19 -19
  98. data/spec/{sequel_core → core}/core_sql_spec.rb +68 -71
  99. data/spec/{sequel_core → core}/database_spec.rb +135 -99
  100. data/spec/{sequel_core → core}/dataset_spec.rb +398 -242
  101. data/spec/{sequel_core → core}/expression_filters_spec.rb +13 -13
  102. data/spec/core/migration_spec.rb +263 -0
  103. data/spec/{sequel_core → core}/object_graph_spec.rb +10 -10
  104. data/spec/{sequel_core → core}/pretty_table_spec.rb +2 -2
  105. data/spec/{sequel_core → core}/schema_generator_spec.rb +0 -0
  106. data/spec/{sequel_core → core}/schema_spec.rb +8 -10
  107. data/spec/{sequel_core → core}/spec_helper.rb +29 -2
  108. data/spec/{sequel_core → core}/version_spec.rb +0 -0
  109. data/spec/extensions/blank_spec.rb +67 -0
  110. data/spec/extensions/caching_spec.rb +201 -0
  111. data/spec/{sequel_model/hooks_spec.rb → extensions/hook_class_methods_spec.rb} +8 -23
  112. data/spec/{sequel_model → extensions}/inflector_spec.rb +3 -0
  113. data/spec/{sequel_core → extensions}/migration_spec.rb +4 -4
  114. data/spec/extensions/pagination_spec.rb +99 -0
  115. data/spec/extensions/pretty_table_spec.rb +91 -0
  116. data/spec/extensions/query_spec.rb +85 -0
  117. data/spec/{sequel_model → extensions}/schema_spec.rb +22 -1
  118. data/spec/extensions/serialization_spec.rb +109 -0
  119. data/spec/extensions/single_table_inheritance_spec.rb +53 -0
  120. data/spec/{sequel_model → extensions}/spec_helper.rb +13 -4
  121. data/spec/extensions/string_date_time_spec.rb +93 -0
  122. data/spec/{sequel_model/validations_spec.rb → extensions/validation_class_methods_spec.rb} +15 -103
  123. data/spec/extensions/validation_helpers_spec.rb +291 -0
  124. data/spec/integration/dataset_test.rb +31 -0
  125. data/spec/integration/eager_loader_test.rb +17 -30
  126. data/spec/integration/schema_test.rb +8 -5
  127. data/spec/integration/spec_helper.rb +17 -0
  128. data/spec/integration/transaction_test.rb +68 -0
  129. data/spec/{sequel_model → model}/association_reflection_spec.rb +0 -0
  130. data/spec/{sequel_model → model}/associations_spec.rb +23 -10
  131. data/spec/{sequel_model → model}/base_spec.rb +29 -20
  132. data/spec/{sequel_model → model}/caching_spec.rb +16 -14
  133. data/spec/{sequel_model → model}/dataset_methods_spec.rb +0 -0
  134. data/spec/{sequel_model → model}/eager_loading_spec.rb +8 -8
  135. data/spec/model/hooks_spec.rb +472 -0
  136. data/spec/model/inflector_spec.rb +126 -0
  137. data/spec/{sequel_model → model}/model_spec.rb +25 -20
  138. data/spec/model/plugins_spec.rb +142 -0
  139. data/spec/{sequel_model → model}/record_spec.rb +121 -62
  140. data/spec/model/schema_spec.rb +92 -0
  141. data/spec/model/spec_helper.rb +124 -0
  142. data/spec/model/validations_spec.rb +1080 -0
  143. metadata +136 -107
  144. data/lib/sequel_core/core_ext.rb +0 -217
  145. data/lib/sequel_core/dataset/callback.rb +0 -13
  146. data/lib/sequel_core/dataset/schema.rb +0 -15
  147. data/lib/sequel_core/deprecated.rb +0 -26
  148. data/lib/sequel_core/exceptions.rb +0 -44
  149. data/lib/sequel_core/schema.rb +0 -2
  150. data/lib/sequel_core/schema/sql.rb +0 -325
  151. data/lib/sequel_model/association_reflection.rb +0 -267
  152. data/lib/sequel_model/associations.rb +0 -499
  153. data/lib/sequel_model/base.rb +0 -539
  154. data/lib/sequel_model/caching.rb +0 -82
  155. data/lib/sequel_model/dataset_methods.rb +0 -26
  156. data/lib/sequel_model/eager_loading.rb +0 -370
  157. data/lib/sequel_model/hooks.rb +0 -101
  158. data/lib/sequel_model/plugins.rb +0 -62
  159. data/lib/sequel_model/record.rb +0 -568
  160. data/lib/sequel_model/schema.rb +0 -49
  161. data/lib/sequel_model/validations.rb +0 -429
  162. data/spec/sequel_model/plugins_spec.rb +0 -80
@@ -0,0 +1,99 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ context "A paginated dataset" do
4
+ before do
5
+ @d = Sequel::Dataset.new(nil)
6
+ @d.meta_def(:count) {153}
7
+
8
+ @paginated = @d.paginate(1, 20)
9
+ end
10
+
11
+ specify "should raise an error if the dataset already has a limit" do
12
+ proc{@d.limit(10).paginate(1,10)}.should raise_error(Sequel::Error)
13
+ proc{@paginated.paginate(2,20)}.should raise_error(Sequel::Error)
14
+ end
15
+
16
+ specify "should set the limit and offset options correctly" do
17
+ @paginated.opts[:limit].should == 20
18
+ @paginated.opts[:offset].should == 0
19
+ end
20
+
21
+ specify "should set the page count correctly" do
22
+ @paginated.page_count.should == 8
23
+ @d.paginate(1, 50).page_count.should == 4
24
+ end
25
+
26
+ specify "should set the current page number correctly" do
27
+ @paginated.current_page.should == 1
28
+ @d.paginate(3, 50).current_page.should == 3
29
+ end
30
+
31
+ specify "should return the next page number or nil if we're on the last" do
32
+ @paginated.next_page.should == 2
33
+ @d.paginate(4, 50).next_page.should be_nil
34
+ end
35
+
36
+ specify "should return the previous page number or nil if we're on the last" do
37
+ @paginated.prev_page.should be_nil
38
+ @d.paginate(4, 50).prev_page.should == 3
39
+ end
40
+
41
+ specify "should return the page range" do
42
+ @paginated.page_range.should == (1..8)
43
+ @d.paginate(4, 50).page_range.should == (1..4)
44
+ end
45
+
46
+ specify "should return the record range for the current page" do
47
+ @paginated.current_page_record_range.should == (1..20)
48
+ @d.paginate(4, 50).current_page_record_range.should == (151..153)
49
+ @d.paginate(5, 50).current_page_record_range.should == (0..0)
50
+ end
51
+
52
+ specify "should return the record count for the current page" do
53
+ @paginated.current_page_record_count.should == 20
54
+ @d.paginate(3, 50).current_page_record_count.should == 50
55
+ @d.paginate(4, 50).current_page_record_count.should == 3
56
+ @d.paginate(5, 50).current_page_record_count.should == 0
57
+ end
58
+
59
+ specify "should know if current page is last page" do
60
+ @paginated.last_page?.should be_false
61
+ @d.paginate(2, 20).last_page?.should be_false
62
+ @d.paginate(5, 30).last_page?.should be_false
63
+ @d.paginate(6, 30).last_page?.should be_true
64
+ end
65
+
66
+ specify "should know if current page is first page" do
67
+ @paginated.first_page?.should be_true
68
+ @d.paginate(1, 20).first_page?.should be_true
69
+ @d.paginate(2, 20).first_page?.should be_false
70
+ end
71
+
72
+ specify "should work with fixed sql" do
73
+ ds = @d.clone(:sql => 'select * from blah')
74
+ ds.meta_def(:count) {150}
75
+ ds.paginate(2, 50).sql.should == 'SELECT * FROM (select * from blah) AS t1 LIMIT 50 OFFSET 50'
76
+ end
77
+ end
78
+
79
+ context "Dataset#each_page" do
80
+ before do
81
+ @d = Sequel::Dataset.new(nil).from(:items)
82
+ @d.meta_def(:count) {153}
83
+ end
84
+
85
+ specify "should raise an error if the dataset already has a limit" do
86
+ proc{@d.limit(10).each_page(10){}}.should raise_error(Sequel::Error)
87
+ end
88
+
89
+ specify "should iterate over each page in the resultset as a paginated dataset" do
90
+ a = []
91
+ @d.each_page(50) {|p| a << p}
92
+ a.map {|p| p.sql}.should == [
93
+ 'SELECT * FROM items LIMIT 50 OFFSET 0',
94
+ 'SELECT * FROM items LIMIT 50 OFFSET 50',
95
+ 'SELECT * FROM items LIMIT 50 OFFSET 100',
96
+ 'SELECT * FROM items LIMIT 50 OFFSET 150',
97
+ ]
98
+ end
99
+ end
@@ -0,0 +1,91 @@
1
+ require File.join(File.dirname(__FILE__), 'spec_helper')
2
+
3
+ require 'stringio'
4
+
5
+ context "Dataset#print" do
6
+ before do
7
+ @output = StringIO.new
8
+ @orig_stdout = $stdout
9
+ $stdout = @output
10
+ @dataset = Sequel::Dataset.new(nil).from(:items)
11
+ def @dataset.fetch_rows(sql)
12
+ yield({:a=>1, :b=>2})
13
+ yield({:a=>3, :b=>4})
14
+ yield({:a=>5, :b=>6})
15
+ end
16
+ end
17
+
18
+ after do
19
+ $stdout = @orig_stdout
20
+ end
21
+
22
+ specify "should print out a table with the values" do
23
+ @dataset.print(:a, :b)
24
+ @output.rewind
25
+ @output.read.should == \
26
+ "+-+-+\n|a|b|\n+-+-+\n|1|2|\n|3|4|\n|5|6|\n+-+-+\n"
27
+ end
28
+
29
+ specify "should default to the dataset's columns" do
30
+ @dataset.meta_def(:columns) {[:a, :b]}
31
+ @dataset.print
32
+ @output.rewind
33
+ @output.read.should == \
34
+ "+-+-+\n|a|b|\n+-+-+\n|1|2|\n|3|4|\n|5|6|\n+-+-+\n"
35
+ end
36
+ end
37
+
38
+ context "PrettyTable" do
39
+ before do
40
+ @data1 = [
41
+ {:x => 3, :y => 4}
42
+ ]
43
+
44
+ @data2 = [
45
+ {:a => 23, :b => 45},
46
+ {:a => 45, :b => 2377}
47
+ ]
48
+
49
+ @data3 = [
50
+ {:aaa => 1},
51
+ {:bb => 2},
52
+ {:c => 3}
53
+ ]
54
+
55
+ @output = StringIO.new
56
+ @orig_stdout = $stdout
57
+ $stdout = @output
58
+ end
59
+
60
+ after do
61
+ $stdout = @orig_stdout
62
+ end
63
+
64
+ specify "should infer the columns if not given" do
65
+ Sequel::PrettyTable.print(@data1)
66
+ @output.rewind
67
+ @output.read.should =~ \
68
+ /\n(\|x\|y\|)|(\|y\|x\|)\n/
69
+ end
70
+
71
+ specify "should calculate the maximum width of each column correctly" do
72
+ Sequel::PrettyTable.print(@data2, [:a, :b])
73
+ @output.rewind
74
+ @output.read.should == \
75
+ "+--+----+\n|a |b |\n+--+----+\n|23| 45|\n|45|2377|\n+--+----+\n"
76
+ end
77
+
78
+ specify "should also take header width into account" do
79
+ Sequel::PrettyTable.print(@data3, [:aaa, :bb, :c])
80
+ @output.rewind
81
+ @output.read.should == \
82
+ "+---+--+-+\n|aaa|bb|c|\n+---+--+-+\n| 1| | |\n| | 2| |\n| | |3|\n+---+--+-+\n"
83
+ end
84
+
85
+ specify "should print only the specified columns" do
86
+ Sequel::PrettyTable.print(@data2, [:a])
87
+ @output.rewind
88
+ @output.read.should == \
89
+ "+--+\n|a |\n+--+\n|23|\n|45|\n+--+\n"
90
+ end
91
+ end
@@ -0,0 +1,85 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ context "Database#dataset" do
4
+ before do
5
+ @db = Sequel::Database.new
6
+ end
7
+
8
+ specify "should delegate to Dataset#query if block is provided" do
9
+ @d = @db.query {select :x; from :y}
10
+ @d.should be_a_kind_of(Sequel::Dataset)
11
+ @d.sql.should == "SELECT x FROM y"
12
+ end
13
+ end
14
+
15
+ context "Dataset#query" do
16
+ before do
17
+ @d = Sequel::Dataset.new(nil)
18
+ end
19
+
20
+ specify "should support #from" do
21
+ q = @d.query {from :xxx}
22
+ q.class.should == @d.class
23
+ q.sql.should == "SELECT * FROM xxx"
24
+ end
25
+
26
+ specify "should support #select" do
27
+ q = @d.query do
28
+ select :a, :b___mongo
29
+ from :yyy
30
+ end
31
+ q.class.should == @d.class
32
+ q.sql.should == "SELECT a, b AS mongo FROM yyy"
33
+ end
34
+
35
+ specify "should support #where" do
36
+ q = @d.query do
37
+ from :zzz
38
+ where(:x + 2 > :y + 3)
39
+ end
40
+ q.class.should == @d.class
41
+ q.sql.should == "SELECT * FROM zzz WHERE ((x + 2) > (y + 3))"
42
+
43
+ q = @d.from(:zzz).query do
44
+ where((:x.sql_number > 1) & (:y.sql_number > 2))
45
+ end
46
+ q.class.should == @d.class
47
+ q.sql.should == "SELECT * FROM zzz WHERE ((x > 1) AND (y > 2))"
48
+
49
+ q = @d.from(:zzz).query do
50
+ where :x => 33
51
+ end
52
+ q.class.should == @d.class
53
+ q.sql.should == "SELECT * FROM zzz WHERE (x = 33)"
54
+ end
55
+
56
+ specify "should support #group_by and #having" do
57
+ q = @d.query do
58
+ from :abc
59
+ group_by :id
60
+ having(:x.sql_number >= 2)
61
+ end
62
+ q.class.should == @d.class
63
+ q.sql.should == "SELECT * FROM abc GROUP BY id HAVING (x >= 2)"
64
+ end
65
+
66
+ specify "should support #order, #order_by" do
67
+ q = @d.query do
68
+ from :xyz
69
+ order_by :stamp
70
+ end
71
+ q.class.should == @d.class
72
+ q.sql.should == "SELECT * FROM xyz ORDER BY stamp"
73
+ end
74
+
75
+ specify "should raise on non-chainable method calls" do
76
+ proc {@d.query {first_source}}.should raise_error(Sequel::Error)
77
+ end
78
+
79
+ specify "should raise on each, insert, update, delete" do
80
+ proc {@d.query {each}}.should raise_error(Sequel::Error)
81
+ proc {@d.query {insert(:x => 1)}}.should raise_error(Sequel::Error)
82
+ proc {@d.query {update(:x => 1)}}.should raise_error(Sequel::Error)
83
+ proc {@d.query {delete}}.should raise_error(Sequel::Error)
84
+ end
85
+ end
@@ -1,5 +1,27 @@
1
1
  require File.join(File.dirname(__FILE__), "spec_helper")
2
2
 
3
+ describe Sequel::Model, "dataset & schema" do
4
+ before do
5
+ @model = Class.new(Sequel::Model(:items))
6
+ end
7
+
8
+ specify "sets schema with implicit table name" do
9
+ @model.set_schema do
10
+ primary_key :ssn, :string
11
+ end
12
+ @model.primary_key.should == :ssn
13
+ @model.table_name.should == :items
14
+ end
15
+
16
+ specify "sets schema with explicit table name" do
17
+ @model.set_schema :foo do
18
+ primary_key :id
19
+ end
20
+ @model.primary_key.should == :id
21
+ @model.table_name.should == :foo
22
+ end
23
+ end
24
+
3
25
  describe Sequel::Model, "table_exists?" do
4
26
 
5
27
  before(:each) do
@@ -12,7 +34,6 @@ describe Sequel::Model, "table_exists?" do
12
34
  @model.db.should_receive(:table_exists?)
13
35
  @model.table_exists?
14
36
  end
15
-
16
37
  end
17
38
 
18
39
  describe Sequel::Model, "create_table and schema" do
@@ -0,0 +1,109 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe "Serialization plugin" do
4
+ before do
5
+ @c = Class.new(Sequel::Model(:items)) do
6
+ include(Module.new do
7
+ def before_save
8
+ end
9
+ end)
10
+ no_primary_key
11
+ columns :id, :abc, :def
12
+ end
13
+ MODEL_DB.reset
14
+ end
15
+
16
+ it "should allow serializing attributes to yaml" do
17
+ @c.plugin :serialization, :yaml, :abc
18
+ @c.create(:abc => 1)
19
+ @c.create(:abc => "hello")
20
+
21
+ MODEL_DB.sqls.should == [ \
22
+ "INSERT INTO items (abc) VALUES ('--- 1\n')", \
23
+ "INSERT INTO items (abc) VALUES ('--- hello\n')", \
24
+ ]
25
+ end
26
+
27
+ it "should allow serializing attributes to marshal" do
28
+ @c.plugin :serialization, :marshal, :abc
29
+ @c.create(:abc => 1)
30
+ @c.create(:abc => "hello")
31
+ x = [Marshal.dump("hello")].pack('m')
32
+
33
+ MODEL_DB.sqls.should == [ \
34
+ "INSERT INTO items (abc) VALUES ('BAhpBg==\n')", \
35
+ "INSERT INTO items (abc) VALUES ('#{x}')", \
36
+ ]
37
+ end
38
+
39
+ it "should translate values to and from yaml serialization format using accessor methods" do
40
+ @c.set_primary_key :id
41
+ @c.plugin :serialization, :yaml, :abc, :def
42
+ vals = nil
43
+
44
+ ds = @c.dataset
45
+ def ds.fetch_rows(sql, &block)
46
+ block.call(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
47
+ end
48
+
49
+ o = @c.first
50
+ o.id.should == 1
51
+ o.abc.should == 1
52
+ o.def.should == "hello"
53
+
54
+ o.update(:abc => 23)
55
+ @c.create(:abc => [1, 2, 3])
56
+ MODEL_DB.sqls.should == ["UPDATE items SET abc = '--- 23\n' WHERE (id = 1)",
57
+ "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')"]
58
+ end
59
+
60
+ it "should translate values to and from marshal serialization format using accessor methods" do
61
+ @c.set_primary_key :id
62
+ @c.plugin :serialization, :marshal, :abc, :def
63
+
64
+ ds = @c.dataset
65
+ def ds.fetch_rows(sql, &block)
66
+ block.call(:id => 1, :abc =>[Marshal.dump(1)].pack('m'), :def =>[Marshal.dump('hello')].pack('m'))
67
+ end
68
+
69
+ o = @c.first
70
+ o.id.should == 1
71
+ o.abc.should == 1
72
+ o.def.should == "hello"
73
+
74
+ o.update(:abc => 23)
75
+ @c.create(:abc => [1, 2, 3])
76
+ MODEL_DB.sqls.should == ["UPDATE items SET abc = '#{[Marshal.dump(23)].pack('m')}' WHERE (id = 1)",
77
+ "INSERT INTO items (abc) VALUES ('#{[Marshal.dump([1, 2, 3])].pack('m')}')"]
78
+ end
79
+
80
+ it "should copy serialization formats and columns to subclasses" do
81
+ @c.set_primary_key :id
82
+ @c.plugin :serialization, :yaml, :abc, :def
83
+
84
+ ds = @c.dataset
85
+ def ds.fetch_rows(sql, &block)
86
+ block.call(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
87
+ end
88
+
89
+ o = Class.new(@c).first
90
+ o.id.should == 1
91
+ o.abc.should == 1
92
+ o.def.should == "hello"
93
+
94
+ o.update(:abc => 23)
95
+ Class.new(@c).create(:abc => [1, 2, 3])
96
+ MODEL_DB.sqls.should == ["UPDATE items SET abc = '--- 23\n' WHERE (id = 1)",
97
+ "INSERT INTO items (abc) VALUES ('#{[1, 2, 3].to_yaml}')"]
98
+ end
99
+
100
+ it "should clear the deserialized columns when refreshing" do
101
+ @c.set_primary_key :id
102
+ @c.plugin :serialization, :yaml, :abc, :def
103
+ o = @c.load(:id => 1, :abc => "--- 1\n", :def => "--- hello\n")
104
+ o.abc = 23
105
+ o.deserialized_values.length.should == 1
106
+ o.refresh
107
+ o.deserialized_values.length.should == 0
108
+ end
109
+ end
@@ -0,0 +1,53 @@
1
+ require File.join(File.dirname(__FILE__), "spec_helper")
2
+
3
+ describe Sequel::Model, "#sti_key" do
4
+ before do
5
+ class ::StiTest < Sequel::Model
6
+ def kind=(x); self[:kind] = x; end
7
+ def refresh; end
8
+ plugin :single_table_inheritance, :kind
9
+ end
10
+ class ::StiTestSub1 < StiTest
11
+ end
12
+ class ::StiTestSub2 < StiTest
13
+ end
14
+ @ds = StiTest.dataset
15
+ MODEL_DB.reset
16
+ end
17
+
18
+ it "should return rows with the correct class based on the polymorphic_key value" do
19
+ def @ds.fetch_rows(sql)
20
+ yield({:kind=>'StiTest'})
21
+ yield({:kind=>'StiTestSub1'})
22
+ yield({:kind=>'StiTestSub2'})
23
+ end
24
+ StiTest.all.collect{|x| x.class}.should == [StiTest, StiTestSub1, StiTestSub2]
25
+ end
26
+
27
+ it "should fallback to the main class if polymophic_key value is NULL" do
28
+ def @ds.fetch_rows(sql)
29
+ yield({:kind=>nil})
30
+ end
31
+ StiTest.all.collect{|x| x.class}.should == [StiTest]
32
+ end
33
+
34
+ it "should fallback to the main class if the given class does not exist" do
35
+ def @ds.fetch_rows(sql)
36
+ yield({:kind=>'StiTestSub3'})
37
+ end
38
+ StiTest.all.collect{|x| x.class}.should == [StiTest]
39
+ end
40
+
41
+ it "should add a before_create hook that sets the model class name for the key" do
42
+ StiTest.new.save
43
+ StiTestSub1.new.save
44
+ StiTestSub2.new.save
45
+ MODEL_DB.sqls.should == ["INSERT INTO sti_tests (kind) VALUES ('StiTest')", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub1')", "INSERT INTO sti_tests (kind) VALUES ('StiTestSub2')"]
46
+ end
47
+
48
+ it "should add a filter to model datasets inside subclasses hook to only retreive objects with the matching key" do
49
+ StiTest.dataset.sql.should == "SELECT * FROM sti_tests"
50
+ StiTestSub1.dataset.sql.should == "SELECT * FROM sti_tests WHERE (kind = 'StiTestSub1')"
51
+ StiTestSub2.dataset.sql.should == "SELECT * FROM sti_tests WHERE (kind = 'StiTestSub2')"
52
+ end
53
+ end