sequel 3.21.0 → 3.32.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 +539 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +20 -6
- data/Rakefile +37 -19
- data/bin/sequel +1 -5
- data/doc/advanced_associations.rdoc +17 -0
- data/doc/association_basics.rdoc +293 -43
- data/doc/dataset_basics.rdoc +4 -4
- data/doc/dataset_filtering.rdoc +8 -0
- data/doc/mass_assignment.rdoc +54 -0
- data/doc/migration.rdoc +15 -538
- data/doc/model_hooks.rdoc +72 -27
- data/doc/opening_databases.rdoc +89 -50
- data/doc/prepared_statements.rdoc +40 -13
- data/doc/reflection.rdoc +8 -2
- data/doc/release_notes/3.22.0.txt +39 -0
- data/doc/release_notes/3.23.0.txt +172 -0
- data/doc/release_notes/3.24.0.txt +420 -0
- data/doc/release_notes/3.25.0.txt +88 -0
- data/doc/release_notes/3.26.0.txt +88 -0
- data/doc/release_notes/3.27.0.txt +82 -0
- data/doc/release_notes/3.28.0.txt +304 -0
- data/doc/release_notes/3.29.0.txt +459 -0
- data/doc/release_notes/3.30.0.txt +135 -0
- data/doc/release_notes/3.31.0.txt +146 -0
- data/doc/release_notes/3.32.0.txt +202 -0
- data/doc/schema_modification.rdoc +547 -0
- data/doc/sharding.rdoc +7 -1
- data/doc/testing.rdoc +129 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/virtual_rows.rdoc +2 -2
- data/lib/sequel/adapters/ado/mssql.rb +18 -6
- data/lib/sequel/adapters/ado.rb +40 -18
- data/lib/sequel/adapters/amalgalite.rb +17 -9
- data/lib/sequel/adapters/db2.rb +175 -86
- data/lib/sequel/adapters/dbi.rb +15 -15
- data/lib/sequel/adapters/do/mysql.rb +5 -7
- data/lib/sequel/adapters/do/postgres.rb +0 -5
- data/lib/sequel/adapters/do/sqlite.rb +0 -5
- data/lib/sequel/adapters/do.rb +17 -36
- data/lib/sequel/adapters/firebird.rb +27 -208
- data/lib/sequel/adapters/ibmdb.rb +448 -0
- data/lib/sequel/adapters/informix.rb +6 -23
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/db2.rb +52 -0
- data/lib/sequel/adapters/jdbc/derby.rb +260 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +29 -0
- data/lib/sequel/adapters/jdbc/h2.rb +66 -30
- data/lib/sequel/adapters/jdbc/hsqldb.rb +177 -0
- data/lib/sequel/adapters/jdbc/informix.rb +26 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +34 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +11 -11
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +9 -13
- data/lib/sequel/adapters/jdbc/sqlite.rb +2 -6
- data/lib/sequel/adapters/jdbc/sqlserver.rb +71 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +231 -78
- data/lib/sequel/adapters/mock.rb +339 -0
- data/lib/sequel/adapters/mysql.rb +85 -184
- data/lib/sequel/adapters/mysql2.rb +26 -25
- data/lib/sequel/adapters/odbc/db2.rb +17 -0
- data/lib/sequel/adapters/odbc/mssql.rb +1 -6
- data/lib/sequel/adapters/odbc.rb +28 -9
- data/lib/sequel/adapters/openbase.rb +3 -5
- data/lib/sequel/adapters/oracle.rb +355 -53
- data/lib/sequel/adapters/postgres.rb +194 -33
- data/lib/sequel/adapters/shared/access.rb +32 -9
- data/lib/sequel/adapters/shared/db2.rb +328 -0
- data/lib/sequel/adapters/shared/firebird.rb +221 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +278 -107
- data/lib/sequel/adapters/shared/mysql.rb +203 -65
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +149 -0
- data/lib/sequel/adapters/shared/oracle.rb +237 -46
- data/lib/sequel/adapters/shared/postgres.rb +214 -82
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +200 -50
- data/lib/sequel/adapters/sqlite.rb +29 -21
- data/lib/sequel/adapters/swift/mysql.rb +12 -7
- data/lib/sequel/adapters/swift/postgres.rb +0 -5
- data/lib/sequel/adapters/swift/sqlite.rb +8 -6
- data/lib/sequel/adapters/swift.rb +5 -5
- data/lib/sequel/adapters/tinytds.rb +160 -19
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +66 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +190 -0
- data/lib/sequel/connection_pool/threaded.rb +3 -2
- data/lib/sequel/connection_pool.rb +1 -1
- data/lib/sequel/core.rb +68 -5
- data/lib/sequel/database/connecting.rb +5 -6
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +59 -1
- data/lib/sequel/database/logging.rb +1 -1
- data/lib/sequel/database/misc.rb +104 -19
- data/lib/sequel/database/query.rb +163 -59
- data/lib/sequel/database/schema_generator.rb +17 -7
- data/lib/sequel/database/schema_methods.rb +59 -29
- data/lib/sequel/dataset/actions.rb +240 -76
- data/lib/sequel/dataset/features.rb +91 -8
- data/lib/sequel/dataset/graph.rb +38 -11
- data/lib/sequel/dataset/misc.rb +50 -23
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +59 -27
- data/lib/sequel/dataset/query.rb +236 -43
- data/lib/sequel/dataset/sql.rb +676 -267
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +61 -0
- data/lib/sequel/extensions/migration.rb +6 -4
- data/lib/sequel/extensions/named_timezones.rb +5 -0
- data/lib/sequel/extensions/query.rb +1 -1
- data/lib/sequel/extensions/thread_local_timezones.rb +1 -1
- data/lib/sequel/extensions/to_dot.rb +95 -83
- data/lib/sequel/model/associations.rb +1081 -344
- data/lib/sequel/model/base.rb +420 -133
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +5 -1
- data/lib/sequel/model.rb +20 -10
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +22 -4
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +43 -10
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +58 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/identity_map.rb +114 -7
- data/lib/sequel/plugins/many_through_many.rb +68 -7
- data/lib/sequel/plugins/nested_attributes.rb +65 -10
- data/lib/sequel/plugins/prepared_statements.rb +151 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +84 -0
- data/lib/sequel/plugins/prepared_statements_safe.rb +82 -0
- data/lib/sequel/plugins/prepared_statements_with_pk.rb +59 -0
- data/lib/sequel/plugins/rcte_tree.rb +29 -15
- data/lib/sequel/plugins/serialization.rb +98 -49
- data/lib/sequel/plugins/serialization_modification_detection.rb +63 -0
- data/lib/sequel/plugins/sharding.rb +21 -54
- data/lib/sequel/plugins/single_table_inheritance.rb +3 -1
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/xml_serializer.rb +3 -3
- data/lib/sequel/sql.rb +109 -52
- data/lib/sequel/timezones.rb +57 -38
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/mssql_spec.rb +135 -30
- data/spec/adapters/mysql_spec.rb +244 -212
- data/spec/adapters/oracle_spec.rb +67 -77
- data/spec/adapters/postgres_spec.rb +267 -78
- data/spec/adapters/spec_helper.rb +6 -5
- data/spec/adapters/sqlite_spec.rb +35 -21
- data/spec/core/connection_pool_spec.rb +71 -92
- data/spec/core/core_sql_spec.rb +21 -30
- data/spec/core/database_spec.rb +789 -512
- data/spec/core/dataset_spec.rb +1176 -1061
- data/spec/core/expression_filters_spec.rb +159 -42
- data/spec/core/mock_adapter_spec.rb +419 -0
- data/spec/core/object_graph_spec.rb +86 -114
- data/spec/core/schema_generator_spec.rb +3 -3
- data/spec/core/schema_spec.rb +298 -38
- data/spec/core/spec_helper.rb +6 -48
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/association_autoreloading_spec.rb +1 -10
- data/spec/extensions/association_dependencies_spec.rb +2 -12
- data/spec/extensions/association_pks_spec.rb +66 -32
- data/spec/extensions/caching_spec.rb +23 -50
- data/spec/extensions/class_table_inheritance_spec.rb +31 -83
- data/spec/extensions/columns_introspection_spec.rb +91 -0
- data/spec/extensions/composition_spec.rb +18 -13
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +64 -0
- data/spec/extensions/hook_class_methods_spec.rb +65 -91
- data/spec/extensions/identity_map_spec.rb +114 -22
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +53 -0
- data/spec/extensions/json_serializer_spec.rb +4 -5
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +17 -39
- data/spec/extensions/many_through_many_spec.rb +283 -250
- data/spec/extensions/migration_spec.rb +35 -32
- data/spec/extensions/named_timezones_spec.rb +23 -3
- data/spec/extensions/nested_attributes_spec.rb +97 -88
- data/spec/extensions/optimistic_locking_spec.rb +9 -20
- data/spec/extensions/prepared_statements_associations_spec.rb +111 -0
- data/spec/extensions/prepared_statements_safe_spec.rb +61 -0
- data/spec/extensions/prepared_statements_spec.rb +53 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +1 -6
- data/spec/extensions/query_spec.rb +6 -0
- data/spec/extensions/rcte_tree_spec.rb +41 -43
- data/spec/extensions/schema_dumper_spec.rb +5 -8
- data/spec/extensions/schema_spec.rb +13 -21
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +81 -43
- data/spec/extensions/sharding_spec.rb +66 -140
- data/spec/extensions/single_table_inheritance_spec.rb +18 -29
- data/spec/extensions/spec_helper.rb +13 -61
- data/spec/extensions/sql_expr_spec.rb +20 -60
- data/spec/extensions/tactical_eager_loading_spec.rb +9 -19
- data/spec/extensions/thread_local_timezones_spec.rb +22 -2
- data/spec/extensions/timestamps_spec.rb +6 -6
- data/spec/extensions/to_dot_spec.rb +4 -7
- data/spec/extensions/touch_spec.rb +13 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +1 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +30 -51
- data/spec/extensions/validation_helpers_spec.rb +16 -35
- data/spec/extensions/xml_serializer_spec.rb +16 -4
- data/spec/integration/associations_test.rb +661 -21
- data/spec/integration/database_test.rb +4 -2
- data/spec/integration/dataset_test.rb +500 -67
- data/spec/integration/eager_loader_test.rb +19 -21
- data/spec/integration/model_test.rb +80 -1
- data/spec/integration/plugin_test.rb +367 -119
- data/spec/integration/prepared_statement_test.rb +222 -125
- data/spec/integration/schema_test.rb +217 -39
- data/spec/integration/spec_helper.rb +39 -30
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +182 -5
- data/spec/integration/type_test.rb +17 -3
- data/spec/model/association_reflection_spec.rb +201 -7
- data/spec/model/associations_spec.rb +955 -662
- data/spec/model/base_spec.rb +275 -95
- data/spec/model/dataset_methods_spec.rb +7 -27
- data/spec/model/eager_loading_spec.rb +677 -676
- data/spec/model/hooks_spec.rb +349 -67
- data/spec/model/model_spec.rb +222 -168
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +381 -218
- data/spec/model/spec_helper.rb +13 -71
- data/spec/model/validations_spec.rb +11 -0
- metadata +117 -73
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), 'spec_helper')
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Dataset.introspect_all_columns" do
|
|
4
|
+
before do
|
|
5
|
+
@db = MODEL_DB
|
|
6
|
+
@ds = @db[:a]
|
|
7
|
+
class Sequel::Dataset
|
|
8
|
+
# Handle case where introspect_all_columns has already been called
|
|
9
|
+
alias columns columns_without_introspection unless instance_methods(false).map{|x| x.to_s}.include?('columns')
|
|
10
|
+
end
|
|
11
|
+
Sequel::Dataset.introspect_all_columns
|
|
12
|
+
@db.reset
|
|
13
|
+
end
|
|
14
|
+
after do
|
|
15
|
+
class Sequel::Dataset
|
|
16
|
+
alias columns columns_without_introspection
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
specify "should turn on column introspection by default" do
|
|
21
|
+
@ds.select(:x).columns.should == [:x]
|
|
22
|
+
@db.sqls.length.should == 0
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
describe "columns_introspection extension" do
|
|
27
|
+
before do
|
|
28
|
+
@db = MODEL_DB
|
|
29
|
+
@ds = @db[:a]
|
|
30
|
+
@ds.extend(Sequel::ColumnsIntrospection.dup) # dup to allow multiple places in class hierarchy
|
|
31
|
+
@db.reset
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
specify "should not issue a database query if the columns are already loaded" do
|
|
35
|
+
@ds.instance_variable_set(:@columns, [:x])
|
|
36
|
+
@ds.columns.should == [:x]
|
|
37
|
+
@db.sqls.length.should == 0
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
specify "should handle plain symbols without a database query" do
|
|
41
|
+
@ds.select(:x).columns.should == [:x]
|
|
42
|
+
@db.sqls.length.should == 0
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
specify "should handle qualified symbols without a database query" do
|
|
46
|
+
@ds.select(:t__x).columns.should == [:x]
|
|
47
|
+
@db.sqls.length.should == 0
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
specify "should handle aliased symbols without a database query" do
|
|
51
|
+
@ds.select(:x___a).columns.should == [:a]
|
|
52
|
+
@db.sqls.length.should == 0
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
specify "should handle qualified and aliased symbols without a database query" do
|
|
56
|
+
@ds.select(:t__x___a).columns.should == [:a]
|
|
57
|
+
@db.sqls.length.should == 0
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
specify "should handle SQL::Identifiers " do
|
|
61
|
+
@ds.select(:x.identifier).columns.should == [:x]
|
|
62
|
+
@db.sqls.length.should == 0
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
specify "should handle SQL::QualifiedIdentifiers" do
|
|
66
|
+
@ds.select(:x.qualify(:t)).columns.should == [:x]
|
|
67
|
+
@ds.select(:x.identifier.qualify(:t)).columns.should == [:x]
|
|
68
|
+
@db.sqls.length.should == 0
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
specify "should handle SQL::AliasedExpressions" do
|
|
72
|
+
@ds.select(:x.as(:a)).columns.should == [:a]
|
|
73
|
+
@ds.select(:x.as(:a.identifier)).columns.should == [:a]
|
|
74
|
+
@db.sqls.length.should == 0
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
specify "should issue a database query if the wildcard is selected" do
|
|
78
|
+
@ds.columns
|
|
79
|
+
@db.sqls.length.should == 1
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
specify "should issue a database query if an unsupported type is used" do
|
|
83
|
+
@ds.select(1).columns
|
|
84
|
+
@db.sqls.length.should == 1
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
specify "should not have column introspection on by default" do
|
|
88
|
+
@db[:a].select(:x).columns
|
|
89
|
+
@db.sqls.length.should == 1
|
|
90
|
+
end
|
|
91
|
+
end
|
|
@@ -48,9 +48,10 @@ describe "Composition plugin" do
|
|
|
48
48
|
@c.composition :date, :composer=>proc{Date.new(year+1, month+2, day+3)}, :decomposer=>proc{[:year, :month, :day].each{|s| self.send("#{s}=", date.send(s) * 2)}}
|
|
49
49
|
@o.date.should == Date.new(2, 4, 6)
|
|
50
50
|
@o.save
|
|
51
|
-
MODEL_DB.sqls.last
|
|
52
|
-
|
|
53
|
-
|
|
51
|
+
sql = MODEL_DB.sqls.last
|
|
52
|
+
sql.should include("year = 4")
|
|
53
|
+
sql.should include("month = 8")
|
|
54
|
+
sql.should include("day = 12")
|
|
54
55
|
end
|
|
55
56
|
|
|
56
57
|
it "should allow call super in composition getter and setter method definition in class" do
|
|
@@ -139,8 +140,9 @@ describe "Composition plugin" do
|
|
|
139
140
|
@o.date.month.should == 6
|
|
140
141
|
@o.date = c.new(3, 4)
|
|
141
142
|
@o.save
|
|
142
|
-
MODEL_DB.sqls.last
|
|
143
|
-
|
|
143
|
+
sql = MODEL_DB.sqls.last
|
|
144
|
+
sql.should include("year = 6")
|
|
145
|
+
sql.should include("month = 12")
|
|
144
146
|
end
|
|
145
147
|
|
|
146
148
|
it ":mapping option should work with an array of two pairs of symbols" do
|
|
@@ -160,8 +162,9 @@ describe "Composition plugin" do
|
|
|
160
162
|
@o.date.m.should == 6
|
|
161
163
|
@o.date = c.new(3, 4)
|
|
162
164
|
@o.save
|
|
163
|
-
MODEL_DB.sqls.last
|
|
164
|
-
|
|
165
|
+
sql = MODEL_DB.sqls.last
|
|
166
|
+
sql.should include("year = 6")
|
|
167
|
+
sql.should include("month = 12")
|
|
165
168
|
end
|
|
166
169
|
|
|
167
170
|
it ":mapping option :composer should return nil if all values are nil" do
|
|
@@ -173,9 +176,10 @@ describe "Composition plugin" do
|
|
|
173
176
|
@c.composition :date, :mapping=>[:year, :month, :day]
|
|
174
177
|
@o.date = nil
|
|
175
178
|
@o.save
|
|
176
|
-
MODEL_DB.sqls.last
|
|
177
|
-
|
|
178
|
-
|
|
179
|
+
sql = MODEL_DB.sqls.last
|
|
180
|
+
sql.should include("year = NULL")
|
|
181
|
+
sql.should include("month = NULL")
|
|
182
|
+
sql.should include("day = NULL")
|
|
179
183
|
end
|
|
180
184
|
|
|
181
185
|
it "should work correctly with subclasses" do
|
|
@@ -184,8 +188,9 @@ describe "Composition plugin" do
|
|
|
184
188
|
o = c.load(:id=>1, :year=>1, :month=>2, :day=>3)
|
|
185
189
|
o.date.should == Date.new(1, 2, 3)
|
|
186
190
|
o.save
|
|
187
|
-
MODEL_DB.sqls.last
|
|
188
|
-
|
|
189
|
-
|
|
191
|
+
sql = MODEL_DB.sqls.last
|
|
192
|
+
sql.should include("year = 1")
|
|
193
|
+
sql.should include("month = 2")
|
|
194
|
+
sql.should include("day = 3")
|
|
190
195
|
end
|
|
191
196
|
end
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::DatasetAssociations" do
|
|
4
|
+
before do
|
|
5
|
+
@db = Sequel::Database.new
|
|
6
|
+
@Base = Class.new(Sequel::Model)
|
|
7
|
+
@Base.plugin :dataset_associations
|
|
8
|
+
|
|
9
|
+
@Artist = Class.new(@Base)
|
|
10
|
+
@Album = Class.new(@Base)
|
|
11
|
+
@Tag = Class.new(@Base)
|
|
12
|
+
|
|
13
|
+
@Artist.meta_def(:name){'Artist'}
|
|
14
|
+
@Album.meta_def(:name){'Album'}
|
|
15
|
+
@Tag.meta_def(:name){'Tag'}
|
|
16
|
+
|
|
17
|
+
@Artist.dataset = @db[:artists]
|
|
18
|
+
@Album.dataset = @db[:albums]
|
|
19
|
+
@Tag.dataset = @db[:tags]
|
|
20
|
+
|
|
21
|
+
@Artist.columns :id, :name
|
|
22
|
+
@Album.columns :id, :name, :artist_id
|
|
23
|
+
@Tag.columns :id, :name
|
|
24
|
+
|
|
25
|
+
@Artist.plugin :many_through_many
|
|
26
|
+
@Artist.one_to_many :albums, :class=>@Album
|
|
27
|
+
@Artist.one_to_one :first_album, :class=>@Album
|
|
28
|
+
@Album.many_to_one :artist, :class=>@Artist
|
|
29
|
+
@Album.many_to_many :tags, :class=>@Tag
|
|
30
|
+
@Tag.many_to_many :albums, :class=>@Album
|
|
31
|
+
@Artist.many_through_many :tags, [[:albums, :artist_id, :id], [:albums_tags, :album_id, :tag_id]], :class=>@Tag
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "should work for many_to_one associations" do
|
|
35
|
+
ds = @Album.artists
|
|
36
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
37
|
+
ds.model.should == @Artist
|
|
38
|
+
ds.sql.should == "SELECT * FROM artists WHERE (artists.id IN (SELECT albums.artist_id FROM albums))"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should work for one_to_many associations" do
|
|
42
|
+
ds = @Artist.albums
|
|
43
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
44
|
+
ds.model.should == @Album
|
|
45
|
+
ds.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
it "should work for one_to_one associations" do
|
|
49
|
+
ds = @Artist.first_albums
|
|
50
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
51
|
+
ds.model.should == @Album
|
|
52
|
+
ds.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
it "should work for many_to_many associations" do
|
|
56
|
+
ds = @Album.tags
|
|
57
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
58
|
+
ds.model.should == @Tag
|
|
59
|
+
ds.sql.should == "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM albums INNER JOIN albums_tags ON (albums_tags.album_id = albums.id)))"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should work for many_through_many associations" do
|
|
63
|
+
ds = @Artist.tags
|
|
64
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
65
|
+
ds.model.should == @Tag
|
|
66
|
+
ds.sql.should == "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM artists INNER JOIN albums ON (albums.artist_id = artists.id) INNER JOIN albums_tags ON (albums_tags.album_id = albums.id)))"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
it "should have an associated method that takes an association symbol" do
|
|
70
|
+
ds = @Album.associated(:artist)
|
|
71
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
72
|
+
ds.model.should == @Artist
|
|
73
|
+
ds.sql.should == "SELECT * FROM artists WHERE (artists.id IN (SELECT albums.artist_id FROM albums))"
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
it "should raise an Error if an invalid association is given to associated" do
|
|
77
|
+
proc{@Album.associated(:foo)}.should raise_error(Sequel::Error)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
it "should raise an Error if an unrecognized association type is used" do
|
|
81
|
+
@Album.association_reflection(:artist)[:type] = :foo
|
|
82
|
+
proc{@Album.artists}.should raise_error(Sequel::Error)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "should work correctly when chaining" do
|
|
86
|
+
ds = @Artist.albums.tags
|
|
87
|
+
ds.should be_a_kind_of(Sequel::Dataset)
|
|
88
|
+
ds.model.should == @Tag
|
|
89
|
+
ds.sql.should == "SELECT tags.* FROM tags WHERE (tags.id IN (SELECT albums_tags.tag_id FROM albums INNER JOIN albums_tags ON (albums_tags.album_id = albums.id) WHERE (albums.artist_id IN (SELECT artists.id FROM artists))))"
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
it "should deal correctly with filters before the association method" do
|
|
93
|
+
@Artist.filter(:id=>1).albums.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists WHERE (id = 1)))"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
it "should deal correctly with filters after the association method" do
|
|
97
|
+
@Artist.albums.filter(:id=>1).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id = 1))"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "should deal correctly with block on the association" do
|
|
101
|
+
@Artist.one_to_many :albums, :clone=>:albums do |ds| ds.filter(:id=>1..100) end
|
|
102
|
+
@Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id >= 1) AND (id <= 100))"
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
it "should deal correctly with :conditions option on the association" do
|
|
106
|
+
@Artist.one_to_many :albums, :clone=>:albums, :conditions=>{:id=>1..100}
|
|
107
|
+
@Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id >= 1) AND (id <= 100))"
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
it "should deal correctly with :distinct option on the association" do
|
|
111
|
+
@Artist.one_to_many :albums, :clone=>:albums, :distinct=>true
|
|
112
|
+
@Artist.albums.sql.should == "SELECT DISTINCT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
it "should deal correctly with :eager option on the association" do
|
|
116
|
+
@Artist.one_to_many :albums, :clone=>:albums, :eager=>:tags
|
|
117
|
+
@Artist.albums.opts[:eager].should == {:tags=>nil}
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
it "should deal correctly with :eager_block option on the association, ignoring the association block" do
|
|
121
|
+
@Artist.one_to_many :albums, :clone=>:albums, :eager_block=>proc{|ds| ds.filter(:id=>1..100)} do |ds| ds.filter(:id=>2..200) end
|
|
122
|
+
@Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id >= 1) AND (id <= 100))"
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should deal correctly with :extend option on the association" do
|
|
126
|
+
@Artist.one_to_many :albums, :clone=>:albums, :extend=>Module.new{def foo(x) filter(:id=>x) end}
|
|
127
|
+
@Artist.albums.foo(1).sql.should == "SELECT * FROM albums WHERE ((albums.artist_id IN (SELECT artists.id FROM artists)) AND (id = 1))"
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
it "should deal correctly with :order option on the association" do
|
|
131
|
+
@Artist.one_to_many :albums, :clone=>:albums, :order=>:name
|
|
132
|
+
@Artist.albums.sql.should == "SELECT * FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists)) ORDER BY name"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
it "should deal correctly with :select option on the association" do
|
|
136
|
+
@Artist.one_to_many :albums, :clone=>:albums, :select=>[:id, :name]
|
|
137
|
+
@Artist.albums.sql.should == "SELECT id, name FROM albums WHERE (albums.artist_id IN (SELECT artists.id FROM artists))"
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
describe "Sequel::Plugins::DatasetAssociations with composite keys" do
|
|
142
|
+
before do
|
|
143
|
+
@db = Sequel::Database.new
|
|
144
|
+
@Base = Class.new(Sequel::Model)
|
|
145
|
+
@Base.plugin :dataset_associations
|
|
146
|
+
|
|
147
|
+
@Artist = Class.new(@Base)
|
|
148
|
+
@Album = Class.new(@Base)
|
|
149
|
+
@Tag = Class.new(@Base)
|
|
150
|
+
|
|
151
|
+
@Artist.meta_def(:name){'Artist'}
|
|
152
|
+
@Album.meta_def(:name){'Album'}
|
|
153
|
+
@Tag.meta_def(:name){'Tag'}
|
|
154
|
+
|
|
155
|
+
@Artist.dataset = @db[:artists]
|
|
156
|
+
@Album.dataset = @db[:albums]
|
|
157
|
+
@Tag.dataset = @db[:tags]
|
|
158
|
+
|
|
159
|
+
@Artist.set_primary_key([:id1, :id2])
|
|
160
|
+
@Album.set_primary_key([:id1, :id2])
|
|
161
|
+
@Tag.set_primary_key([:id1, :id2])
|
|
162
|
+
|
|
163
|
+
@Artist.columns :id1, :id2, :name
|
|
164
|
+
@Album.columns :id1, :id2, :name, :artist_id1, :artist_id2
|
|
165
|
+
@Tag.columns :id1, :id2, :name
|
|
166
|
+
|
|
167
|
+
@Artist.plugin :many_through_many
|
|
168
|
+
@Artist.one_to_many :albums, :class=>@Album, :key=>[:artist_id1, :artist_id2]
|
|
169
|
+
@Artist.one_to_one :first_album, :class=>@Album, :key=>[:artist_id1, :artist_id2]
|
|
170
|
+
@Album.many_to_one :artist, :class=>@Artist, :key=>[:artist_id1, :artist_id2]
|
|
171
|
+
@Album.many_to_many :tags, :class=>@Tag, :left_key=>[:album_id1, :album_id2], :right_key=>[:tag_id1, :tag_id2]
|
|
172
|
+
@Tag.many_to_many :albums, :class=>@Album, :right_key=>[:album_id1, :album_id2], :left_key=>[:tag_id1, :tag_id2]
|
|
173
|
+
@Artist.many_through_many :tags, [[:albums, [:artist_id1, :artist_id2], [:id1, :id2]], [:albums_tags, [:album_id1, :album_id2], [:tag_id1, :tag_id2]]], :class=>@Tag
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
it "should work for many_to_one associations" do
|
|
177
|
+
@Album.artists.sql.should == "SELECT * FROM artists WHERE ((artists.id1, artists.id2) IN (SELECT albums.artist_id1, albums.artist_id2 FROM albums))"
|
|
178
|
+
end
|
|
179
|
+
|
|
180
|
+
it "should work for one_to_many associations" do
|
|
181
|
+
@Artist.albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists))"
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should work for one_to_one associations" do
|
|
185
|
+
@Artist.first_albums.sql.should == "SELECT * FROM albums WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists))"
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "should work for many_to_many associations" do
|
|
189
|
+
@Album.tags.sql.should == "SELECT tags.* FROM tags WHERE ((tags.id1, tags.id2) IN (SELECT albums_tags.tag_id1, albums_tags.tag_id2 FROM albums INNER JOIN albums_tags ON ((albums_tags.album_id1 = albums.id1) AND (albums_tags.album_id2 = albums.id2))))"
|
|
190
|
+
end
|
|
191
|
+
|
|
192
|
+
it "should work for many_through_many associations" do
|
|
193
|
+
@Artist.tags.sql.should == "SELECT tags.* FROM tags WHERE ((tags.id1, tags.id2) IN (SELECT albums_tags.tag_id1, albums_tags.tag_id2 FROM artists INNER JOIN albums ON ((albums.artist_id1 = artists.id1) AND (albums.artist_id2 = artists.id2)) INNER JOIN albums_tags ON ((albums_tags.album_id1 = albums.id1) AND (albums_tags.album_id2 = albums.id2))))"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
it "should work correctly when chaining" do
|
|
197
|
+
@Artist.albums.tags.sql.should == "SELECT tags.* FROM tags WHERE ((tags.id1, tags.id2) IN (SELECT albums_tags.tag_id1, albums_tags.tag_id2 FROM albums INNER JOIN albums_tags ON ((albums_tags.album_id1 = albums.id1) AND (albums_tags.album_id2 = albums.id2)) WHERE ((albums.artist_id1, albums.artist_id2) IN (SELECT artists.id1, artists.id2 FROM artists))))"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require File.join(File.dirname(File.expand_path(__FILE__)), "spec_helper")
|
|
2
|
+
|
|
3
|
+
describe "Sequel::Plugins::DefaultsSetter" do
|
|
4
|
+
before do
|
|
5
|
+
@db = db = Sequel::Database.new
|
|
6
|
+
@c = c = Class.new(Sequel::Model(db[:foo]))
|
|
7
|
+
@c.instance_variable_set(:@db_schema, {:a=>{}})
|
|
8
|
+
@c.plugin :defaults_setter
|
|
9
|
+
@c.columns :a
|
|
10
|
+
@pr = proc{|x| db.meta_def(:schema){|*| [[:a, {:ruby_default => x}]]}; c.dataset = c.dataset; c}
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should set default value upon initialization" do
|
|
14
|
+
@pr.call(2).new.values.should == {:a=>2}
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
it "should not mark the column as modified" do
|
|
18
|
+
@pr.call(2).new.changed_columns.should == []
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
it "should not set a default of nil" do
|
|
22
|
+
@pr.call(nil).new.values.should == {}
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
it "should not override a given value" do
|
|
26
|
+
@pr.call(2)
|
|
27
|
+
@c.new('a'=>3).values.should == {:a=>3}
|
|
28
|
+
@c.new('a'=>nil).values.should == {:a=>nil}
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
it "should work correctly when subclassing" do
|
|
32
|
+
Class.new(@pr.call(2)).new.values.should == {:a=>2}
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
it "should contain the default values in default_values" do
|
|
36
|
+
@pr.call(2).default_values.should == {:a=>2}
|
|
37
|
+
@pr.call(nil).default_values.should == {}
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
it "should allow modifications of default values" do
|
|
41
|
+
@pr.call(2)
|
|
42
|
+
@c.default_values[:a] = 3
|
|
43
|
+
@c.new.values.should == {:a => 3}
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should allow proc default values" do
|
|
47
|
+
@pr.call(2)
|
|
48
|
+
@c.default_values[:a] = proc{3}
|
|
49
|
+
@c.new.values.should == {:a => 3}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
it "should have procs that set default values set them to nil" do
|
|
53
|
+
@pr.call(2)
|
|
54
|
+
@c.default_values[:a] = proc{nil}
|
|
55
|
+
@c.new.values.should == {:a => nil}
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
it "should work correctly on a model without a dataset" do
|
|
59
|
+
@pr.call(2)
|
|
60
|
+
c = Class.new(Sequel::Model(@db[:bar]))
|
|
61
|
+
c.plugin :defaults_setter
|
|
62
|
+
c.default_values.should == {:a=>2}
|
|
63
|
+
end
|
|
64
|
+
end
|