sequel 3.21.0 → 3.41.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 +1131 -3
- data/MIT-LICENSE +1 -1
- data/README.rdoc +106 -65
- data/Rakefile +59 -27
- data/bin/sequel +50 -26
- data/doc/active_record.rdoc +68 -52
- data/doc/advanced_associations.rdoc +201 -75
- data/doc/association_basics.rdoc +327 -79
- data/doc/bin_sequel.rdoc +144 -0
- data/doc/cheat_sheet.rdoc +21 -21
- data/doc/core_extensions.rdoc +374 -0
- data/doc/dataset_basics.rdoc +10 -10
- data/doc/dataset_filtering.rdoc +54 -42
- data/doc/mass_assignment.rdoc +56 -0
- data/doc/migration.rdoc +89 -557
- data/doc/model_hooks.rdoc +80 -29
- data/doc/object_model.rdoc +576 -0
- data/doc/opening_databases.rdoc +121 -53
- data/doc/prepared_statements.rdoc +41 -15
- data/doc/querying.rdoc +137 -56
- data/doc/reflection.rdoc +36 -10
- 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/release_notes/3.33.0.txt +157 -0
- data/doc/release_notes/3.34.0.txt +671 -0
- data/doc/release_notes/3.35.0.txt +144 -0
- data/doc/release_notes/3.36.0.txt +245 -0
- data/doc/release_notes/3.37.0.txt +338 -0
- data/doc/release_notes/3.38.0.txt +234 -0
- data/doc/release_notes/3.39.0.txt +237 -0
- data/doc/release_notes/3.40.0.txt +73 -0
- data/doc/release_notes/3.41.0.txt +155 -0
- data/doc/schema_modification.rdoc +585 -0
- data/doc/sharding.rdoc +99 -8
- data/doc/sql.rdoc +154 -112
- data/doc/testing.rdoc +169 -0
- data/doc/thread_safety.rdoc +17 -0
- data/doc/transactions.rdoc +137 -0
- data/doc/validations.rdoc +1 -1
- data/doc/virtual_rows.rdoc +78 -43
- data/lib/sequel/adapters/ado/access.rb +334 -0
- data/lib/sequel/adapters/ado/mssql.rb +18 -12
- data/lib/sequel/adapters/ado.rb +69 -21
- data/lib/sequel/adapters/amalgalite.rb +17 -14
- data/lib/sequel/adapters/cubrid.rb +143 -0
- data/lib/sequel/adapters/db2.rb +178 -85
- data/lib/sequel/adapters/dbi.rb +19 -21
- data/lib/sequel/adapters/do/mysql.rb +17 -11
- data/lib/sequel/adapters/do/postgres.rb +2 -61
- data/lib/sequel/adapters/do/sqlite.rb +0 -10
- data/lib/sequel/adapters/do.rb +20 -39
- data/lib/sequel/adapters/firebird.rb +33 -210
- data/lib/sequel/adapters/ibmdb.rb +452 -0
- data/lib/sequel/adapters/informix.rb +6 -29
- data/lib/sequel/adapters/jdbc/as400.rb +16 -34
- data/lib/sequel/adapters/jdbc/cubrid.rb +52 -0
- data/lib/sequel/adapters/jdbc/db2.rb +78 -0
- data/lib/sequel/adapters/jdbc/derby.rb +325 -0
- data/lib/sequel/adapters/jdbc/firebird.rb +24 -0
- data/lib/sequel/adapters/jdbc/h2.rb +68 -31
- data/lib/sequel/adapters/jdbc/hsqldb.rb +189 -0
- data/lib/sequel/adapters/jdbc/informix.rb +21 -0
- data/lib/sequel/adapters/jdbc/jtds.rb +40 -0
- data/lib/sequel/adapters/jdbc/mssql.rb +3 -33
- data/lib/sequel/adapters/jdbc/mysql.rb +16 -28
- data/lib/sequel/adapters/jdbc/oracle.rb +88 -25
- data/lib/sequel/adapters/jdbc/postgresql.rb +77 -52
- data/lib/sequel/adapters/jdbc/progress.rb +21 -0
- data/lib/sequel/adapters/jdbc/sqlite.rb +20 -10
- data/lib/sequel/adapters/jdbc/sqlserver.rb +72 -0
- data/lib/sequel/adapters/jdbc/transactions.rb +83 -0
- data/lib/sequel/adapters/jdbc.rb +308 -114
- data/lib/sequel/adapters/mock.rb +372 -0
- data/lib/sequel/adapters/mysql.rb +130 -230
- data/lib/sequel/adapters/mysql2.rb +64 -63
- data/lib/sequel/adapters/odbc/mssql.rb +17 -9
- data/lib/sequel/adapters/odbc.rb +29 -10
- data/lib/sequel/adapters/openbase.rb +7 -11
- data/lib/sequel/adapters/oracle.rb +364 -57
- data/lib/sequel/adapters/postgres.rb +379 -145
- data/lib/sequel/adapters/shared/access.rb +236 -11
- data/lib/sequel/adapters/shared/cubrid.rb +216 -0
- data/lib/sequel/adapters/shared/db2.rb +353 -0
- data/lib/sequel/adapters/shared/firebird.rb +231 -0
- data/lib/sequel/adapters/shared/informix.rb +53 -0
- data/lib/sequel/adapters/shared/mssql.rb +412 -116
- data/lib/sequel/adapters/shared/mysql.rb +396 -89
- data/lib/sequel/adapters/shared/mysql_prepared_statements.rb +166 -0
- data/lib/sequel/adapters/shared/oracle.rb +262 -45
- data/lib/sequel/adapters/shared/postgres.rb +688 -279
- data/lib/sequel/adapters/shared/progress.rb +5 -8
- data/lib/sequel/adapters/shared/sqlite.rb +317 -96
- data/lib/sequel/adapters/sqlite.rb +109 -46
- data/lib/sequel/adapters/swift/mysql.rb +10 -12
- data/lib/sequel/adapters/swift/postgres.rb +13 -79
- data/lib/sequel/adapters/swift/sqlite.rb +9 -6
- data/lib/sequel/adapters/swift.rb +31 -27
- data/lib/sequel/adapters/tinytds.rb +177 -25
- data/lib/sequel/adapters/utils/emulate_offset_with_row_number.rb +77 -0
- data/lib/sequel/adapters/utils/pg_types.rb +81 -0
- data/lib/sequel/adapters/utils/split_alter_table.rb +36 -0
- data/lib/sequel/adapters/utils/stored_procedures.rb +1 -11
- data/lib/sequel/ast_transformer.rb +194 -0
- data/lib/sequel/connection_pool/sharded_single.rb +23 -13
- data/lib/sequel/connection_pool/sharded_threaded.rb +64 -13
- data/lib/sequel/connection_pool/single.rb +11 -3
- data/lib/sequel/connection_pool/threaded.rb +69 -20
- data/lib/sequel/connection_pool.rb +20 -18
- data/lib/sequel/core.rb +143 -11
- data/lib/sequel/database/connecting.rb +66 -29
- data/lib/sequel/database/dataset.rb +4 -4
- data/lib/sequel/database/dataset_defaults.rb +63 -2
- data/lib/sequel/database/logging.rb +7 -2
- data/lib/sequel/database/misc.rb +192 -51
- data/lib/sequel/database/query.rb +299 -114
- data/lib/sequel/database/schema_generator.rb +103 -36
- data/lib/sequel/database/schema_methods.rb +310 -69
- data/lib/sequel/dataset/actions.rb +344 -90
- data/lib/sequel/dataset/features.rb +101 -8
- data/lib/sequel/dataset/graph.rb +42 -15
- data/lib/sequel/dataset/misc.rb +52 -25
- data/lib/sequel/dataset/mutation.rb +12 -7
- data/lib/sequel/dataset/prepared_statements.rb +68 -30
- data/lib/sequel/dataset/query.rb +322 -68
- data/lib/sequel/dataset/sql.rb +716 -293
- data/lib/sequel/dataset.rb +8 -0
- data/lib/sequel/exceptions.rb +4 -0
- data/lib/sequel/extensions/_pretty_table.rb +83 -0
- data/lib/sequel/extensions/arbitrary_servers.rb +109 -0
- data/lib/sequel/extensions/blank.rb +4 -0
- data/lib/sequel/extensions/columns_introspection.rb +72 -0
- data/lib/sequel/extensions/connection_validator.rb +109 -0
- data/lib/sequel/extensions/constraint_validations.rb +451 -0
- data/lib/sequel/{core_sql.rb → extensions/core_extensions.rb} +30 -46
- data/lib/sequel/extensions/eval_inspect.rb +173 -0
- data/lib/sequel/extensions/inflector.rb +4 -0
- data/lib/sequel/extensions/looser_typecasting.rb +5 -4
- data/lib/sequel/extensions/migration.rb +100 -11
- data/lib/sequel/extensions/named_timezones.rb +9 -0
- data/lib/sequel/extensions/null_dataset.rb +94 -0
- data/lib/sequel/extensions/pagination.rb +4 -0
- data/lib/sequel/extensions/pg_array.rb +539 -0
- data/lib/sequel/extensions/pg_array_ops.rb +263 -0
- data/lib/sequel/extensions/pg_auto_parameterize.rb +175 -0
- data/lib/sequel/extensions/pg_hstore.rb +334 -0
- data/lib/sequel/extensions/pg_hstore_ops.rb +293 -0
- data/lib/sequel/extensions/pg_inet.rb +113 -0
- data/lib/sequel/extensions/pg_interval.rb +191 -0
- data/lib/sequel/extensions/pg_json.rb +212 -0
- data/lib/sequel/extensions/pg_range.rb +513 -0
- data/lib/sequel/extensions/pg_range_ops.rb +150 -0
- data/lib/sequel/extensions/pg_row.rb +576 -0
- data/lib/sequel/extensions/pg_row_ops.rb +182 -0
- data/lib/sequel/extensions/pg_statement_cache.rb +317 -0
- data/lib/sequel/extensions/pretty_table.rb +17 -72
- data/lib/sequel/extensions/query.rb +8 -4
- data/lib/sequel/extensions/query_literals.rb +79 -0
- data/lib/sequel/extensions/schema_caching.rb +76 -0
- data/lib/sequel/extensions/schema_dumper.rb +282 -76
- data/lib/sequel/extensions/select_remove.rb +39 -0
- data/lib/sequel/extensions/server_block.rb +140 -0
- data/lib/sequel/extensions/split_array_nil.rb +65 -0
- data/lib/sequel/extensions/sql_expr.rb +8 -110
- data/lib/sequel/extensions/string_date_time.rb +4 -0
- data/lib/sequel/extensions/thread_local_timezones.rb +10 -4
- data/lib/sequel/extensions/to_dot.rb +99 -83
- data/lib/sequel/model/associations.rb +1263 -409
- data/lib/sequel/model/base.rb +624 -171
- data/lib/sequel/model/errors.rb +1 -1
- data/lib/sequel/model/exceptions.rb +24 -2
- data/lib/sequel/model/inflections.rb +1 -1
- data/lib/sequel/model.rb +30 -11
- data/lib/sequel/no_core_ext.rb +2 -0
- data/lib/sequel/plugins/active_model.rb +13 -1
- data/lib/sequel/plugins/association_pks.rb +137 -16
- data/lib/sequel/plugins/caching.rb +25 -18
- data/lib/sequel/plugins/class_table_inheritance.rb +4 -4
- data/lib/sequel/plugins/composition.rb +44 -12
- data/lib/sequel/plugins/constraint_validations.rb +198 -0
- data/lib/sequel/plugins/dataset_associations.rb +100 -0
- data/lib/sequel/plugins/defaults_setter.rb +72 -0
- data/lib/sequel/plugins/dirty.rb +214 -0
- data/lib/sequel/plugins/eager_each.rb +59 -0
- data/lib/sequel/plugins/force_encoding.rb +6 -6
- data/lib/sequel/plugins/hook_class_methods.rb +1 -1
- data/lib/sequel/plugins/identity_map.rb +134 -15
- data/lib/sequel/plugins/instance_filters.rb +10 -0
- data/lib/sequel/plugins/instance_hooks.rb +1 -1
- data/lib/sequel/plugins/json_serializer.rb +77 -6
- data/lib/sequel/plugins/list.rb +13 -2
- data/lib/sequel/plugins/many_through_many.rb +103 -51
- data/lib/sequel/plugins/many_to_one_pk_lookup.rb +71 -0
- data/lib/sequel/plugins/nested_attributes.rb +150 -66
- data/lib/sequel/plugins/optimistic_locking.rb +8 -0
- data/lib/sequel/plugins/pg_row.rb +121 -0
- data/lib/sequel/plugins/pg_typecast_on_load.rb +65 -0
- data/lib/sequel/plugins/prepared_statements.rb +168 -0
- data/lib/sequel/plugins/prepared_statements_associations.rb +87 -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 +31 -17
- data/lib/sequel/plugins/schema.rb +8 -3
- 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 +57 -12
- data/lib/sequel/plugins/static_cache.rb +99 -0
- data/lib/sequel/plugins/subclasses.rb +29 -3
- data/lib/sequel/plugins/tactical_eager_loading.rb +7 -7
- data/lib/sequel/plugins/timestamps.rb +1 -1
- data/lib/sequel/plugins/touch.rb +18 -6
- data/lib/sequel/plugins/tree.rb +3 -3
- data/lib/sequel/plugins/typecast_on_load.rb +9 -12
- data/lib/sequel/plugins/update_primary_key.rb +2 -2
- data/lib/sequel/plugins/validation_class_methods.rb +2 -1
- data/lib/sequel/plugins/validation_helpers.rb +57 -4
- data/lib/sequel/plugins/xml_serializer.rb +15 -4
- data/lib/sequel/sql.rb +721 -141
- data/lib/sequel/timezones.rb +67 -40
- data/lib/sequel/version.rb +1 -1
- data/spec/adapters/db2_spec.rb +146 -0
- data/spec/adapters/firebird_spec.rb +53 -39
- data/spec/adapters/mssql_spec.rb +261 -66
- data/spec/adapters/mysql_spec.rb +597 -352
- data/spec/adapters/oracle_spec.rb +92 -117
- data/spec/adapters/postgres_spec.rb +2103 -341
- data/spec/adapters/spec_helper.rb +16 -6
- data/spec/adapters/sqlite_spec.rb +237 -76
- data/spec/core/connection_pool_spec.rb +270 -141
- data/spec/core/database_spec.rb +980 -524
- data/spec/core/dataset_spec.rb +1658 -1243
- data/spec/core/expression_filters_spec.rb +741 -334
- data/spec/core/mock_adapter_spec.rb +453 -0
- data/spec/core/object_graph_spec.rb +88 -129
- data/spec/core/schema_generator_spec.rb +4 -4
- data/spec/core/schema_spec.rb +556 -53
- data/spec/core/spec_helper.rb +7 -48
- data/spec/core_extensions_spec.rb +626 -0
- data/spec/extensions/active_model_spec.rb +13 -0
- data/spec/extensions/arbitrary_servers_spec.rb +110 -0
- data/spec/extensions/association_autoreloading_spec.rb +18 -10
- data/spec/extensions/association_dependencies_spec.rb +15 -25
- data/spec/extensions/association_pks_spec.rb +227 -33
- data/spec/extensions/association_proxies_spec.rb +4 -4
- data/spec/extensions/boolean_readers_spec.rb +25 -25
- data/spec/extensions/caching_spec.rb +47 -51
- 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/connection_validator_spec.rb +118 -0
- data/spec/extensions/constraint_validations_plugin_spec.rb +196 -0
- data/spec/extensions/constraint_validations_spec.rb +316 -0
- data/spec/extensions/dataset_associations_spec.rb +199 -0
- data/spec/extensions/defaults_setter_spec.rb +88 -0
- data/spec/extensions/dirty_spec.rb +155 -0
- data/spec/extensions/eager_each_spec.rb +34 -0
- data/spec/extensions/eval_inspect_spec.rb +67 -0
- data/spec/extensions/force_encoding_spec.rb +4 -2
- data/spec/extensions/hook_class_methods_spec.rb +97 -128
- data/spec/extensions/identity_map_spec.rb +142 -24
- data/spec/extensions/inflector_spec.rb +0 -4
- data/spec/extensions/instance_filters_spec.rb +11 -21
- data/spec/extensions/instance_hooks_spec.rb +72 -0
- data/spec/extensions/json_serializer_spec.rb +49 -12
- data/spec/extensions/lazy_attributes_spec.rb +16 -20
- data/spec/extensions/list_spec.rb +49 -40
- data/spec/extensions/looser_typecasting_spec.rb +7 -7
- data/spec/extensions/many_through_many_spec.rb +368 -254
- data/spec/extensions/many_to_one_pk_lookup_spec.rb +140 -0
- data/spec/extensions/migration_spec.rb +140 -35
- data/spec/extensions/named_timezones_spec.rb +29 -11
- data/spec/extensions/nested_attributes_spec.rb +268 -89
- data/spec/extensions/null_dataset_spec.rb +85 -0
- data/spec/extensions/optimistic_locking_spec.rb +24 -21
- data/spec/extensions/pg_array_ops_spec.rb +112 -0
- data/spec/extensions/pg_array_spec.rb +324 -0
- data/spec/extensions/pg_auto_parameterize_spec.rb +65 -0
- data/spec/extensions/pg_hstore_ops_spec.rb +140 -0
- data/spec/extensions/pg_hstore_spec.rb +200 -0
- data/spec/extensions/pg_inet_spec.rb +47 -0
- data/spec/extensions/pg_interval_spec.rb +72 -0
- data/spec/extensions/pg_json_spec.rb +99 -0
- data/spec/extensions/pg_range_ops_spec.rb +56 -0
- data/spec/extensions/pg_range_spec.rb +395 -0
- data/spec/extensions/pg_row_ops_spec.rb +58 -0
- data/spec/extensions/pg_row_plugin_spec.rb +49 -0
- data/spec/extensions/pg_row_spec.rb +340 -0
- data/spec/extensions/pg_statement_cache_spec.rb +208 -0
- data/spec/extensions/pg_typecast_on_load_spec.rb +58 -0
- 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 +87 -0
- data/spec/extensions/prepared_statements_with_pk_spec.rb +31 -0
- data/spec/extensions/pretty_table_spec.rb +7 -6
- data/spec/extensions/query_literals_spec.rb +167 -0
- data/spec/extensions/query_spec.rb +9 -3
- data/spec/extensions/rcte_tree_spec.rb +50 -43
- data/spec/extensions/schema_caching_spec.rb +41 -0
- data/spec/extensions/schema_dumper_spec.rb +434 -49
- data/spec/extensions/schema_spec.rb +30 -49
- data/spec/extensions/select_remove_spec.rb +38 -0
- data/spec/extensions/serialization_modification_detection_spec.rb +72 -0
- data/spec/extensions/serialization_spec.rb +86 -48
- data/spec/extensions/server_block_spec.rb +90 -0
- data/spec/extensions/sharding_spec.rb +69 -143
- data/spec/extensions/single_table_inheritance_spec.rb +65 -29
- data/spec/extensions/skip_create_refresh_spec.rb +1 -1
- data/spec/extensions/spec_helper.rb +34 -67
- data/spec/extensions/split_array_nil_spec.rb +24 -0
- data/spec/extensions/sql_expr_spec.rb +29 -60
- data/spec/extensions/static_cache_spec.rb +145 -0
- data/spec/extensions/subclasses_spec.rb +14 -0
- data/spec/extensions/tactical_eager_loading_spec.rb +17 -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 +8 -11
- data/spec/extensions/touch_spec.rb +53 -14
- data/spec/extensions/tree_spec.rb +11 -26
- data/spec/extensions/typecast_on_load_spec.rb +9 -6
- data/spec/extensions/update_primary_key_spec.rb +30 -24
- data/spec/extensions/validation_class_methods_spec.rb +77 -68
- data/spec/extensions/validation_helpers_spec.rb +48 -37
- data/spec/extensions/xml_serializer_spec.rb +29 -4
- data/spec/files/transaction_specified_migrations/001_create_alt_basic.rb +4 -0
- data/spec/files/transaction_specified_migrations/002_create_basic.rb +4 -0
- data/spec/files/transaction_unspecified_migrations/001_create_alt_basic.rb +3 -0
- data/spec/files/transaction_unspecified_migrations/002_create_basic.rb +3 -0
- data/spec/integration/associations_test.rb +659 -21
- data/spec/integration/database_test.rb +25 -5
- data/spec/integration/dataset_test.rb +729 -141
- data/spec/integration/eager_loader_test.rb +38 -54
- data/spec/integration/migrator_test.rb +2 -3
- data/spec/integration/model_test.rb +81 -2
- data/spec/integration/plugin_test.rb +871 -160
- data/spec/integration/prepared_statement_test.rb +272 -128
- data/spec/integration/schema_test.rb +377 -57
- data/spec/integration/spec_helper.rb +49 -32
- data/spec/integration/timezone_test.rb +38 -12
- data/spec/integration/transaction_test.rb +183 -8
- data/spec/integration/type_test.rb +40 -8
- data/spec/model/association_reflection_spec.rb +207 -8
- data/spec/model/associations_spec.rb +1206 -693
- data/spec/model/base_spec.rb +334 -100
- data/spec/model/dataset_methods_spec.rb +45 -27
- data/spec/model/eager_loading_spec.rb +828 -692
- data/spec/model/hooks_spec.rb +355 -67
- data/spec/model/model_spec.rb +251 -179
- data/spec/model/plugins_spec.rb +24 -13
- data/spec/model/record_spec.rb +506 -232
- data/spec/model/spec_helper.rb +16 -77
- data/spec/model/validations_spec.rb +38 -2
- data/spec/rcov.opts +2 -0
- metadata +223 -81
- data/spec/core/core_sql_spec.rb +0 -451
data/MIT-LICENSE
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
Copyright (c) 2007-2008 Sharon Rosner
|
|
2
|
-
Copyright (c) 2008-
|
|
2
|
+
Copyright (c) 2008-2012 Jeremy Evans
|
|
3
3
|
|
|
4
4
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
5
5
|
of this software and associated documentation files (the "Software"), to
|
data/README.rdoc
CHANGED
|
@@ -11,16 +11,17 @@ toolkit for Ruby.
|
|
|
11
11
|
statements, bound variables, stored procedures, savepoints,
|
|
12
12
|
two-phase commit, transaction isolation, master/slave
|
|
13
13
|
configurations, and database sharding.
|
|
14
|
-
* Sequel currently has adapters for ADO, Amalgalite,
|
|
15
|
-
DB2, DBI, Firebird, Informix, JDBC, MySQL,
|
|
16
|
-
Oracle, PostgreSQL, SQLite3, Swift, and
|
|
14
|
+
* Sequel currently has adapters for ADO, Amalgalite, CUBRID,
|
|
15
|
+
DataObjects, DB2, DBI, Firebird, IBM_DB, Informix, JDBC, MySQL,
|
|
16
|
+
Mysql2, ODBC, OpenBase, Oracle, PostgreSQL, SQLite3, Swift, and
|
|
17
|
+
TinyTDS.
|
|
17
18
|
|
|
18
19
|
== Resources
|
|
19
20
|
|
|
20
21
|
* {Website}[http://sequel.rubyforge.org]
|
|
21
22
|
* {Blog}[http://sequel.heroku.com]
|
|
22
23
|
* {Source code}[http://github.com/jeremyevans/sequel]
|
|
23
|
-
* {Bug tracking}[http://
|
|
24
|
+
* {Bug tracking}[http://github.com/jeremyevans/sequel/issues]
|
|
24
25
|
* {Google group}[http://groups.google.com/group/sequel-talk]
|
|
25
26
|
* {RDoc}[http://sequel.rubyforge.org/rdoc]
|
|
26
27
|
|
|
@@ -64,12 +65,14 @@ If you have any comments or suggestions please post to the Google group.
|
|
|
64
65
|
|
|
65
66
|
== The Sequel Console
|
|
66
67
|
|
|
67
|
-
Sequel includes an IRB console for quick access to databases. You can use it like this:
|
|
68
|
+
Sequel includes an IRB console for quick access to databases (usually referred to as <tt>bin/sequel</tt>). You can use it like this:
|
|
68
69
|
|
|
69
70
|
sequel sqlite://test.db # test.db in current directory
|
|
70
71
|
|
|
71
72
|
You get an IRB session with the database object stored in DB.
|
|
72
73
|
|
|
74
|
+
In addition to providing an IRB shell (the default behavior), bin/sequel also has support for migrating databases, dumping schema migrations, and copying databases. See the {bin/sequel guide}[link:files/doc/bin_sequel_rdoc.html] for more details.
|
|
75
|
+
|
|
73
76
|
== An Introduction
|
|
74
77
|
|
|
75
78
|
Sequel is designed to take the hassle away from connecting to databases and manipulating them. Sequel deals with all the boring stuff like maintaining connections, formatting SQL correctly and fetching records so you can concentrate on your application.
|
|
@@ -91,11 +94,11 @@ Since datasets retrieve records only when needed, they can be stored and later r
|
|
|
91
94
|
|
|
92
95
|
Sequel also offers convenience methods for extracting data from Datasets, such as an extended +map+ method:
|
|
93
96
|
|
|
94
|
-
middle_east.map(:name) #=> ['Egypt', '
|
|
97
|
+
middle_east.map(:name) #=> ['Egypt', 'Turkey', 'Israel', ...]
|
|
95
98
|
|
|
96
99
|
Or getting results as a hash via +to_hash+, with one column as key and another as value:
|
|
97
100
|
|
|
98
|
-
middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, '
|
|
101
|
+
middle_east.to_hash(:name, :area) #=> {'Israel' => 20000, 'Turkey' => 120000, ...}
|
|
99
102
|
|
|
100
103
|
== Getting Started
|
|
101
104
|
|
|
@@ -169,7 +172,7 @@ You can also iterate through records one at a time using +each+:
|
|
|
169
172
|
|
|
170
173
|
Or perform more advanced stuff:
|
|
171
174
|
|
|
172
|
-
names_and_dates = posts.map
|
|
175
|
+
names_and_dates = posts.map([:name, :date])
|
|
173
176
|
old_posts, recent_posts = posts.partition{|r| r[:date] < Date.today - 7}
|
|
174
177
|
|
|
175
178
|
You can also retrieve the first record in a dataset:
|
|
@@ -189,29 +192,29 @@ If the dataset is ordered, you can also ask for the last record:
|
|
|
189
192
|
|
|
190
193
|
=== Filtering Records
|
|
191
194
|
|
|
192
|
-
An easy way to filter records is to provide a hash of values to match to +
|
|
195
|
+
An easy way to filter records is to provide a hash of values to match to +where+:
|
|
193
196
|
|
|
194
|
-
my_posts = posts.
|
|
197
|
+
my_posts = posts.where(:category => 'ruby', :author => 'david')
|
|
195
198
|
# WHERE category = 'ruby' AND author = 'david'
|
|
196
199
|
|
|
197
200
|
You can also specify ranges:
|
|
198
201
|
|
|
199
|
-
my_posts = posts.
|
|
202
|
+
my_posts = posts.where(:stamp => (Date.today - 14)..(Date.today - 7))
|
|
200
203
|
# WHERE stamp >= '2010-06-30' AND stamp <= '2010-07-07'
|
|
201
204
|
|
|
202
205
|
Or arrays of values:
|
|
203
206
|
|
|
204
|
-
my_posts = posts.
|
|
207
|
+
my_posts = posts.where(:category => ['ruby', 'postgres', 'linux'])
|
|
205
208
|
# WHERE category IN ('ruby', 'postgres', 'linux')
|
|
206
209
|
|
|
207
210
|
Sequel also accepts expressions:
|
|
208
211
|
|
|
209
|
-
my_posts = posts.
|
|
212
|
+
my_posts = posts.where{stamp > Date.today << 1}
|
|
210
213
|
# WHERE stamp > '2010-06-14'
|
|
211
214
|
|
|
212
215
|
Some adapters will also let you specify Regexps:
|
|
213
216
|
|
|
214
|
-
my_posts = posts.
|
|
217
|
+
my_posts = posts.where(:category => /ruby/i)
|
|
215
218
|
# WHERE category ~* 'ruby'
|
|
216
219
|
|
|
217
220
|
You can also use an inverse filter via +exclude+:
|
|
@@ -221,32 +224,31 @@ You can also use an inverse filter via +exclude+:
|
|
|
221
224
|
|
|
222
225
|
You can also specify a custom WHERE clause using a string:
|
|
223
226
|
|
|
224
|
-
posts.
|
|
227
|
+
posts.where('stamp IS NOT NULL')
|
|
225
228
|
# WHERE stamp IS NOT NULL
|
|
226
229
|
|
|
227
230
|
You can use parameters in your string, as well:
|
|
228
231
|
|
|
229
232
|
author_name = 'JKR'
|
|
230
|
-
posts.
|
|
233
|
+
posts.where('(stamp < ?) AND (author != ?)', Date.today - 3, author_name)
|
|
231
234
|
# WHERE (stamp < '2010-07-11') AND (author != 'JKR')
|
|
232
|
-
posts.filter{(stamp < Date.today - 3) & ~{:author => author_name}} # same as above
|
|
233
235
|
|
|
234
236
|
Datasets can also be used as subqueries:
|
|
235
237
|
|
|
236
|
-
DB[:items].
|
|
238
|
+
DB[:items].where('price > ?', DB[:items].select{avg(price) + 100})
|
|
237
239
|
# WHERE price > (SELECT avg(price) + 100 FROM items)
|
|
238
240
|
|
|
239
|
-
After filtering you can retrieve the matching records by using any of the retrieval methods:
|
|
241
|
+
After filtering, you can retrieve the matching records by using any of the retrieval methods:
|
|
240
242
|
|
|
241
243
|
my_posts.each{|row| p row}
|
|
242
244
|
|
|
243
|
-
See the doc/
|
|
245
|
+
See the {Dataset Filtering}[link:files/doc/dataset_filtering_rdoc.html] file for more details.
|
|
244
246
|
|
|
245
247
|
=== Summarizing Records
|
|
246
248
|
|
|
247
249
|
Counting records is easy using +count+:
|
|
248
250
|
|
|
249
|
-
posts.
|
|
251
|
+
posts.where(:category.like('%ruby%')).count
|
|
250
252
|
# SELECT COUNT(*) FROM posts WHERE category LIKE '%ruby%'
|
|
251
253
|
|
|
252
254
|
And you can also query maximum/minimum values via +max+ and +min+:
|
|
@@ -273,7 +275,7 @@ Ordering datasets is simple using +order+:
|
|
|
273
275
|
posts.order(:stamp, :name)
|
|
274
276
|
# ORDER BY stamp, name
|
|
275
277
|
|
|
276
|
-
Chaining +order+ doesn't work the same as +
|
|
278
|
+
Chaining +order+ doesn't work the same as +where+:
|
|
277
279
|
|
|
278
280
|
posts.order(:stamp).order(:name)
|
|
279
281
|
# ORDER BY name
|
|
@@ -283,10 +285,27 @@ The +order_append+ method chains this way, though:
|
|
|
283
285
|
posts.order(:stamp).order_append(:name)
|
|
284
286
|
# ORDER BY stamp, name
|
|
285
287
|
|
|
288
|
+
The +order_prepend+ method can be used as well:
|
|
289
|
+
|
|
290
|
+
posts.order(:stamp).order_prepend(:name)
|
|
291
|
+
# ORDER BY name, stamp
|
|
292
|
+
|
|
286
293
|
You can also specify descending order:
|
|
287
294
|
|
|
288
|
-
posts.
|
|
295
|
+
posts.reverse_order(:stamp)
|
|
289
296
|
# ORDER BY stamp DESC
|
|
297
|
+
posts.order(Sequel.desc(:stamp))
|
|
298
|
+
# ORDER BY stamp DESC
|
|
299
|
+
|
|
300
|
+
=== Core Extensions
|
|
301
|
+
|
|
302
|
+
Note the use of <tt>Sequel.desc(:stamp)</tt> in the above example. Much of Sequel's DSL uses this style, calling methods on the Sequel module that return SQL expression objects. Sequel also ships with a {core_extensions extension}[link:files/doc/core_extensions_rdoc.html]) that integrates Sequel's DSL better into the ruby language, allowing you to write:
|
|
303
|
+
|
|
304
|
+
:stamp.desc
|
|
305
|
+
|
|
306
|
+
instead of:
|
|
307
|
+
|
|
308
|
+
Sequel.desc(:stamp)
|
|
290
309
|
|
|
291
310
|
=== Selecting Columns
|
|
292
311
|
|
|
@@ -297,7 +316,7 @@ Selecting specific columns to be returned is also simple using +select+:
|
|
|
297
316
|
posts.select(:stamp, :name)
|
|
298
317
|
# SELECT stamp, name FROM posts
|
|
299
318
|
|
|
300
|
-
Chaining +select+ works like +order+, not +
|
|
319
|
+
Chaining +select+ works like +order+, not +where+:
|
|
301
320
|
|
|
302
321
|
posts.select(:stamp).select(:name)
|
|
303
322
|
# SELECT name FROM posts
|
|
@@ -311,16 +330,16 @@ As you might expect, there is an +order_append+ equivalent for +select+ called +
|
|
|
311
330
|
|
|
312
331
|
Deleting records from the table is done with +delete+:
|
|
313
332
|
|
|
314
|
-
posts.
|
|
333
|
+
posts.where('stamp < ?', Date.today - 3).delete
|
|
315
334
|
# DELETE FROM posts WHERE stamp < '2010-07-11'
|
|
316
335
|
|
|
317
336
|
Be very careful when deleting, as +delete+ affects all rows in the dataset.
|
|
318
|
-
+
|
|
337
|
+
Call +where+ first and +delete+ second:
|
|
319
338
|
|
|
320
339
|
# DO THIS:
|
|
321
|
-
posts.
|
|
340
|
+
posts.where('stamp < ?', Date.today - 7).delete
|
|
322
341
|
# NOT THIS:
|
|
323
|
-
posts.delete.
|
|
342
|
+
posts.delete.where('stamp < ?', Date.today - 7)
|
|
324
343
|
|
|
325
344
|
=== Inserting Records
|
|
326
345
|
|
|
@@ -333,21 +352,21 @@ Inserting records into the table is done with +insert+:
|
|
|
333
352
|
|
|
334
353
|
Updating records in the table is done with +update+:
|
|
335
354
|
|
|
336
|
-
posts.
|
|
355
|
+
posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
|
|
337
356
|
# UPDATE posts SET state = 'archived' WHERE stamp < '2010-07-07'
|
|
338
357
|
|
|
339
358
|
You can reference table columns when choosing what values to set:
|
|
340
359
|
|
|
341
|
-
posts.
|
|
360
|
+
posts.where{|o| o.stamp < Date.today - 7}.update(:backup_number => :backup_number + 1)
|
|
342
361
|
# UPDATE posts SET backup_number = backup_number + 1 WHERE stamp < '2010-07-07'
|
|
343
362
|
|
|
344
|
-
As with +delete+, +update+ affects all rows in the dataset, so +
|
|
345
|
-
+update+ second
|
|
363
|
+
As with +delete+, +update+ affects all rows in the dataset, so +where+ first,
|
|
364
|
+
+update+ second:
|
|
346
365
|
|
|
347
366
|
# DO THIS:
|
|
348
|
-
posts.
|
|
367
|
+
posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
|
|
349
368
|
# NOT THIS:
|
|
350
|
-
posts.update(:state => 'archived').
|
|
369
|
+
posts.update(:state => 'archived').where('stamp < ?', Date.today - 7)
|
|
351
370
|
|
|
352
371
|
=== Transactions
|
|
353
372
|
|
|
@@ -355,7 +374,7 @@ You can wrap some code in a database transaction using the <tt>Database#transact
|
|
|
355
374
|
|
|
356
375
|
DB.transaction do
|
|
357
376
|
posts.insert(:category => 'ruby', :author => 'david')
|
|
358
|
-
posts.
|
|
377
|
+
posts.where('stamp < ?', Date.today - 7).update(:state => 'archived')
|
|
359
378
|
end
|
|
360
379
|
|
|
361
380
|
If the block does not raise an exception, the transaction will be committed.
|
|
@@ -376,11 +395,15 @@ and not raise an exception outside the block, you can raise the
|
|
|
376
395
|
Sequel makes it easy to join tables:
|
|
377
396
|
|
|
378
397
|
order_items = DB[:items].join(:order_items, :item_id => :id).
|
|
379
|
-
|
|
398
|
+
where(:order_items__order_id => 1234)
|
|
380
399
|
# SELECT * FROM items INNER JOIN order_items
|
|
381
400
|
# ON order_items.item_id = items.id
|
|
382
401
|
# WHERE order_items.order_id = 1234
|
|
383
402
|
|
|
403
|
+
The important thing to note here is that item_id is automatically qualified with
|
|
404
|
+
the table being joined, and id is automatically qualified with the last table
|
|
405
|
+
joined.
|
|
406
|
+
|
|
384
407
|
You can then do anything you like with the dataset:
|
|
385
408
|
|
|
386
409
|
order_total = order_items.sum(:price)
|
|
@@ -404,14 +427,14 @@ Using +graph+, you can split the result hashes into subhashes, one per join:
|
|
|
404
427
|
|
|
405
428
|
Sequel expects column names to be specified using symbols. In addition, returned hashes always use symbols as their keys. This allows you to freely mix literal values and column references in many cases. For example, the two following lines produce equivalent SQL:
|
|
406
429
|
|
|
407
|
-
items.
|
|
430
|
+
items.where(:x => 1)
|
|
408
431
|
# SELECT * FROM items WHERE (x = 1)
|
|
409
|
-
items.
|
|
432
|
+
items.where(1 => :x)
|
|
410
433
|
# SELECT * FROM items WHERE (1 = x)"
|
|
411
434
|
|
|
412
435
|
Ruby strings are generally treated as SQL strings:
|
|
413
436
|
|
|
414
|
-
items.
|
|
437
|
+
items.where(:x => 'x')
|
|
415
438
|
# SELECT * FROM items WHERE (x = 'x')
|
|
416
439
|
|
|
417
440
|
=== Qualifying column names
|
|
@@ -421,9 +444,9 @@ Column references can be qualified by using the double underscore special notati
|
|
|
421
444
|
items.literal(:items__price)
|
|
422
445
|
# items.price
|
|
423
446
|
|
|
424
|
-
Another way to qualify columns is to use the
|
|
447
|
+
Another way to qualify columns is to use the <tt>Sequel.qualify</tt> method:
|
|
425
448
|
|
|
426
|
-
items.literal(
|
|
449
|
+
items.literal(Sequel.qualify(:items, :price))
|
|
427
450
|
# items.price
|
|
428
451
|
|
|
429
452
|
=== Column aliases
|
|
@@ -435,9 +458,9 @@ You can also alias columns by using the triple undersecore special notation <tt>
|
|
|
435
458
|
items.literal(:items__price___p)
|
|
436
459
|
# items.price AS p
|
|
437
460
|
|
|
438
|
-
Another way to alias columns is to use the
|
|
461
|
+
Another way to alias columns is to use the <tt>Sequel.as</tt> method:
|
|
439
462
|
|
|
440
|
-
items.literal(
|
|
463
|
+
items.literal(Sequel.as(:price, :p))
|
|
441
464
|
# price AS p
|
|
442
465
|
|
|
443
466
|
== Sequel Models
|
|
@@ -463,7 +486,7 @@ You can explicitly set the table name or even the dataset used:
|
|
|
463
486
|
|
|
464
487
|
If you call +set_dataset+ with a symbol, it assumes you are referring to the table with the same name. You can also call it with a dataset, which will set the defaults for all retrievals for that model:
|
|
465
488
|
|
|
466
|
-
Post.set_dataset DB[:my_posts].
|
|
489
|
+
Post.set_dataset DB[:my_posts].where(:category => 'ruby')
|
|
467
490
|
Post.set_dataset DB[:my_posts].select(:id, :name).order(:date)
|
|
468
491
|
|
|
469
492
|
=== Model instances
|
|
@@ -498,12 +521,12 @@ A single model instance can also be fetched by specifying a condition:
|
|
|
498
521
|
|
|
499
522
|
A model class lets you iterate over subsets of records by proxying many methods to the underlying dataset. This means that you can use most of the +Dataset+ API to create customized queries that return model instances, e.g.:
|
|
500
523
|
|
|
501
|
-
Post.
|
|
524
|
+
Post.where(:category => 'ruby').each{|post| p post}
|
|
502
525
|
|
|
503
526
|
You can also manipulate the records in the dataset:
|
|
504
527
|
|
|
505
|
-
Post.
|
|
506
|
-
Post.
|
|
528
|
+
Post.where{num_comments < 7}.delete
|
|
529
|
+
Post.where(Sequel.like(:title, /ruby/)).update(:category => 'ruby')
|
|
507
530
|
|
|
508
531
|
=== Accessing record values
|
|
509
532
|
|
|
@@ -521,10 +544,12 @@ If the record's attributes names are not valid columns in the model's dataset (m
|
|
|
521
544
|
post[:id] #=> 123
|
|
522
545
|
post[:title] #=> 'hello world'
|
|
523
546
|
|
|
524
|
-
You can also modify record values using attribute setters or the +set+ method:
|
|
547
|
+
You can also modify record values using attribute setters, the <tt>[]=</tt> method, or the +set+ method:
|
|
525
548
|
|
|
526
549
|
post.title = 'hey there'
|
|
527
550
|
# or
|
|
551
|
+
post[:title] = 'hey there'
|
|
552
|
+
# or
|
|
528
553
|
post.set(:title=>'hey there')
|
|
529
554
|
|
|
530
555
|
That will just change the value for the object, it will not update the row in the database. To update the database row, call the +save+ method:
|
|
@@ -573,7 +598,7 @@ You can execute custom code when creating, updating, or deleting records by defi
|
|
|
573
598
|
|
|
574
599
|
Note the use of +super+ if you define your own hook methods. Almost all <tt>Sequel::Model</tt> class and instance methods (not just hook methods) can be overridden safely, but you have to make sure to call +super+ when doing so, otherwise you risk breaking things.
|
|
575
600
|
|
|
576
|
-
For the example above, you should probably use a database trigger if you can. Hooks can be used for data integrity, but they will only enforce that integrity when you are modifying the database through model instances
|
|
601
|
+
For the example above, you should probably use a database trigger if you can. Hooks can be used for data integrity, but they will only enforce that integrity when you are modifying the database through model instances, and even then they are often subject to race conditions. It's best to use database triggers and constraints to enforce data integrity.
|
|
577
602
|
|
|
578
603
|
=== Deleting records
|
|
579
604
|
|
|
@@ -584,8 +609,8 @@ You can delete individual records by calling +delete+ or +destroy+. The only dif
|
|
|
584
609
|
|
|
585
610
|
Records can also be deleted en-masse by calling <tt>Model.delete</tt> and <tt>Model.destroy</tt>. As stated above, you can specify filters for the deleted records:
|
|
586
611
|
|
|
587
|
-
Post.
|
|
588
|
-
Post.
|
|
612
|
+
Post.where(:category => 32).delete # => bypasses hooks
|
|
613
|
+
Post.where(:category => 32).destroy # => runs hooks
|
|
589
614
|
|
|
590
615
|
Please note that if <tt>Model.destroy</tt> is called, each record is deleted
|
|
591
616
|
separately, but <tt>Model.delete</tt> deletes all matching records with a single
|
|
@@ -630,7 +655,7 @@ All associations add a dataset method that can be used to further filter or reor
|
|
|
630
655
|
post.comments_dataset.destroy
|
|
631
656
|
|
|
632
657
|
# Return all tags related to this post with no subscribers, ordered by the tag's name
|
|
633
|
-
post.tags_dataset.
|
|
658
|
+
post.tags_dataset.where(:subscribers=>0).order(:name).all
|
|
634
659
|
|
|
635
660
|
=== Eager Loading
|
|
636
661
|
|
|
@@ -661,7 +686,7 @@ Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> associati
|
|
|
661
686
|
Post.eager(:person).all
|
|
662
687
|
|
|
663
688
|
# eager is a dataset method, so it works with filters/orders/limits/etc.
|
|
664
|
-
Post.
|
|
689
|
+
Post.where{topic > 'M'}.order(:date).limit(5).eager(:person).all
|
|
665
690
|
|
|
666
691
|
person = Person.first
|
|
667
692
|
# Eager loading via :eager (will eagerly load the tags for this person's posts)
|
|
@@ -681,9 +706,23 @@ Associations can be eagerly loaded via +eager+ and the <tt>:eager</tt> associati
|
|
|
681
706
|
# Loads all people, their posts, their posts' tags, replies to those posts,
|
|
682
707
|
# the person for each reply, the tag for each reply, and all posts and
|
|
683
708
|
# replies that have that tag. Uses a total of 8 queries.
|
|
684
|
-
Person.eager(:posts=>{:replies=>[:person, {:tags=>
|
|
709
|
+
Person.eager(:posts=>{:replies=>[:person, {:tags=>[:posts, :replies]}]}).all
|
|
710
|
+
|
|
711
|
+
In addition to using +eager+, you can also use +eager_graph+, which will use a single query to get the object and all associated objects. This may be necessary if you want to filter or order the result set based on columns in associated tables. It works with cascading as well, the API is very similar. Note that using +eager_graph+ to eagerly load multiple <tt>*_to_many</tt> associations will cause the result set to be a cartesian product, so you should be very careful with your filters when using it in that case.
|
|
712
|
+
|
|
713
|
+
You can dynamically customize the eagerly loaded dataset by using using a proc. This proc is passed the dataset used for eager loading, and should return a modified copy of that dataset:
|
|
714
|
+
|
|
715
|
+
# Eagerly load only replies containing 'foo'
|
|
716
|
+
Post.eager(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
|
|
717
|
+
|
|
718
|
+
This also works when using +eager_graph+, in which case the proc is called with dataset to graph into the current dataset:
|
|
685
719
|
|
|
686
|
-
|
|
720
|
+
Post.eager_graph(:replies=>proc{|ds| ds.where(Sequel.like(text, '%foo%'))}).all
|
|
721
|
+
|
|
722
|
+
You can dynamically customize eager loads for both +eager+ and +eager_graph+ while also cascading, by making the value a single entry hash with the proc as a key, and the cascaded associations as the value:
|
|
723
|
+
|
|
724
|
+
# Eagerly load only replies containing 'foo', and the person and tags for those replies
|
|
725
|
+
Post.eager(:replies=>{proc{|ds| ds.where(Sequel.like(text, '%foo%'))}=>[:person, :tags]}).all
|
|
687
726
|
|
|
688
727
|
=== Extending the underlying dataset
|
|
689
728
|
|
|
@@ -691,7 +730,7 @@ The obvious way to add table-wide logic is to define class methods to the model
|
|
|
691
730
|
|
|
692
731
|
class Post < Sequel::Model
|
|
693
732
|
def self.posts_with_few_comments
|
|
694
|
-
|
|
733
|
+
where{num_comments < 30}
|
|
695
734
|
end
|
|
696
735
|
|
|
697
736
|
def self.clean_posts_with_few_comments
|
|
@@ -699,27 +738,29 @@ The obvious way to add table-wide logic is to define class methods to the model
|
|
|
699
738
|
end
|
|
700
739
|
end
|
|
701
740
|
|
|
702
|
-
You can also implement table-wide logic by defining methods on the dataset using +
|
|
741
|
+
You can also implement table-wide logic by defining methods on the dataset using +dataset_module+:
|
|
703
742
|
|
|
704
743
|
class Post < Sequel::Model
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
744
|
+
dataset_module do
|
|
745
|
+
def posts_with_few_comments
|
|
746
|
+
where{num_comments < 30}
|
|
747
|
+
end
|
|
748
|
+
|
|
749
|
+
def clean_posts_with_few_comments
|
|
750
|
+
posts_with_few_comments.delete
|
|
751
|
+
end
|
|
711
752
|
end
|
|
712
753
|
end
|
|
713
754
|
|
|
714
755
|
This is the recommended way of implementing table-wide operations, and allows you to have access to your model API from filtered datasets as well:
|
|
715
756
|
|
|
716
|
-
Post.
|
|
757
|
+
Post.where(:category => 'ruby').clean_posts_with_few_comments
|
|
717
758
|
|
|
718
759
|
Sequel models also provide a +subset+ class method that creates a dataset method with a simple filter:
|
|
719
760
|
|
|
720
761
|
class Post < Sequel::Model
|
|
721
762
|
subset(:posts_with_few_comments){num_comments < 30}
|
|
722
|
-
subset :invisible,
|
|
763
|
+
subset :invisible, Sequel.~(:visible)
|
|
723
764
|
end
|
|
724
765
|
|
|
725
766
|
=== Model Validations
|
data/Rakefile
CHANGED
|
@@ -1,11 +1,5 @@
|
|
|
1
1
|
require "rake"
|
|
2
2
|
require "rake/clean"
|
|
3
|
-
require "rake/gempackagetask"
|
|
4
|
-
begin
|
|
5
|
-
require "hanna/rdoctask"
|
|
6
|
-
rescue LoadError
|
|
7
|
-
require "rake/rdoctask"
|
|
8
|
-
end
|
|
9
3
|
|
|
10
4
|
NAME = 'sequel'
|
|
11
5
|
VERS = lambda do
|
|
@@ -13,34 +7,47 @@ VERS = lambda do
|
|
|
13
7
|
Sequel.version
|
|
14
8
|
end
|
|
15
9
|
CLEAN.include ["**/.*.sw?", "sequel-*.gem", ".config", "rdoc", "coverage", "www/public/*.html", "www/public/rdoc*", '**/*.rbc']
|
|
16
|
-
|
|
17
|
-
RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
|
|
10
|
+
SUDO = ENV['SUDO'] || 'sudo'
|
|
18
11
|
|
|
19
12
|
# Gem Packaging and Release
|
|
20
13
|
|
|
21
14
|
desc "Packages sequel"
|
|
22
15
|
task :package=>[:clean] do |p|
|
|
23
|
-
|
|
16
|
+
load './sequel.gemspec'
|
|
17
|
+
Gem::Builder.new(SEQUEL_GEMSPEC).build
|
|
24
18
|
end
|
|
25
19
|
|
|
26
20
|
desc "Install sequel gem"
|
|
27
21
|
task :install=>[:package] do
|
|
28
|
-
sh %{
|
|
22
|
+
sh %{#{SUDO} gem install ./#{NAME}-#{VERS.call} --local}
|
|
29
23
|
end
|
|
30
24
|
|
|
31
25
|
desc "Uninstall sequel gem"
|
|
32
26
|
task :uninstall=>[:clean] do
|
|
33
|
-
sh %{
|
|
27
|
+
sh %{#{SUDO} gem uninstall #{NAME}}
|
|
34
28
|
end
|
|
35
29
|
|
|
36
30
|
desc "Upload sequel gem to gemcutter"
|
|
37
31
|
task :release=>[:package] do
|
|
38
|
-
sh %{gem push ./#{NAME}-#{VERS.call}.gem}
|
|
32
|
+
sh %{gem push ./#{NAME}-#{VERS.call}.gem}
|
|
39
33
|
end
|
|
40
34
|
|
|
41
35
|
### RDoc
|
|
42
36
|
|
|
43
|
-
|
|
37
|
+
RDOC_DEFAULT_OPTS = ["--quiet", "--line-numbers", "--inline-source", '--title', 'Sequel: The Database Toolkit for Ruby']
|
|
38
|
+
|
|
39
|
+
rdoc_task_class = begin
|
|
40
|
+
require "rdoc/task"
|
|
41
|
+
RDOC_DEFAULT_OPTS.concat(['-f', 'hanna'])
|
|
42
|
+
RDoc::Task
|
|
43
|
+
rescue LoadError
|
|
44
|
+
require "rake/rdoctask"
|
|
45
|
+
Rake::RDocTask
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
RDOC_OPTS = RDOC_DEFAULT_OPTS + ['--main', 'README.rdoc']
|
|
49
|
+
|
|
50
|
+
rdoc_task_class.new do |rdoc|
|
|
44
51
|
rdoc.rdoc_dir = "rdoc"
|
|
45
52
|
rdoc.options += RDOC_OPTS
|
|
46
53
|
rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/**/*.rb doc/*.rdoc doc/release_notes/*.txt"
|
|
@@ -50,25 +57,25 @@ end
|
|
|
50
57
|
|
|
51
58
|
desc "Make local version of website"
|
|
52
59
|
task :website do
|
|
53
|
-
sh %{www/make_www.rb}
|
|
60
|
+
sh %{#{FileUtils::RUBY} www/make_www.rb}
|
|
54
61
|
end
|
|
55
62
|
|
|
56
63
|
desc "Make rdoc for website"
|
|
57
64
|
task :website_rdoc=>[:website_rdoc_main, :website_rdoc_adapters, :website_rdoc_plugins]
|
|
58
65
|
|
|
59
|
-
|
|
66
|
+
rdoc_task_class.new(:website_rdoc_main) do |rdoc|
|
|
60
67
|
rdoc.rdoc_dir = "www/public/rdoc"
|
|
61
68
|
rdoc.options += RDOC_OPTS
|
|
62
69
|
rdoc.rdoc_files.add %w"README.rdoc CHANGELOG MIT-LICENSE lib/*.rb lib/sequel/*.rb lib/sequel/{connection_pool,dataset,database,model}/*.rb doc/*.rdoc doc/release_notes/*.txt lib/sequel/extensions/migration.rb"
|
|
63
70
|
end
|
|
64
71
|
|
|
65
|
-
|
|
72
|
+
rdoc_task_class.new(:website_rdoc_adapters) do |rdoc|
|
|
66
73
|
rdoc.rdoc_dir = "www/public/rdoc-adapters"
|
|
67
74
|
rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel'
|
|
68
75
|
rdoc.rdoc_files.add %w"lib/sequel/adapters/**/*.rb"
|
|
69
76
|
end
|
|
70
77
|
|
|
71
|
-
|
|
78
|
+
rdoc_task_class.new(:website_rdoc_plugins) do |rdoc|
|
|
72
79
|
rdoc.rdoc_dir = "www/public/rdoc-plugins"
|
|
73
80
|
rdoc.options += RDOC_DEFAULT_OPTS + %w'--main Sequel'
|
|
74
81
|
rdoc.rdoc_files.add %w"lib/sequel/{extensions,plugins}/**/*.rb"
|
|
@@ -92,11 +99,13 @@ begin
|
|
|
92
99
|
require "spec/rake/spectask"
|
|
93
100
|
spec_class = Spec::Rake::SpecTask
|
|
94
101
|
spec_files_meth = :spec_files=
|
|
102
|
+
spec_opts_meth = :spec_opts=
|
|
95
103
|
rescue LoadError
|
|
96
104
|
# RSpec 2
|
|
97
105
|
require "rspec/core/rake_task"
|
|
98
106
|
spec_class = RSpec::Core::RakeTask
|
|
99
107
|
spec_files_meth = :pattern=
|
|
108
|
+
spec_opts_meth = :rspec_opts=
|
|
100
109
|
end
|
|
101
110
|
|
|
102
111
|
spec = lambda do |name, files, d|
|
|
@@ -105,26 +114,49 @@ begin
|
|
|
105
114
|
desc d
|
|
106
115
|
spec_class.new(name) do |t|
|
|
107
116
|
t.send spec_files_meth, files
|
|
108
|
-
t.
|
|
117
|
+
t.send spec_opts_meth, ENV['SEQUEL_SPEC_OPTS'].split if ENV['SEQUEL_SPEC_OPTS']
|
|
109
118
|
end
|
|
110
119
|
end
|
|
111
120
|
|
|
112
|
-
spec_with_cov = lambda do |name, files, d|
|
|
121
|
+
spec_with_cov = lambda do |name, files, d, &b|
|
|
113
122
|
spec.call(name, files, d)
|
|
114
123
|
t = spec.call("#{name}_cov", files, "#{d} with coverage")
|
|
115
124
|
t.rcov = true
|
|
116
125
|
t.rcov_opts = File.read("spec/rcov.opts").split("\n")
|
|
126
|
+
b.call(t) if b
|
|
127
|
+
t
|
|
117
128
|
end
|
|
118
|
-
|
|
129
|
+
|
|
119
130
|
task :default => [:spec]
|
|
120
|
-
spec_with_cov.call("spec", Dir["spec/{core,model}/*_spec.rb"], "Run core and model specs")
|
|
131
|
+
spec_with_cov.call("spec", Dir["spec/{core,model}/*_spec.rb"], "Run core and model specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/(adapters/([a-ln-z]|m[a-np-z])|extensions/core_extensions)"')}
|
|
121
132
|
spec.call("spec_core", Dir["spec/core/*_spec.rb"], "Run core specs")
|
|
122
133
|
spec.call("spec_model", Dir["spec/model/*_spec.rb"], "Run model specs")
|
|
123
|
-
|
|
134
|
+
spec.call("_spec_model_no_assoc", Dir["spec/model/*_spec.rb"].delete_if{|f| f =~ /association|eager_loading/}, '')
|
|
135
|
+
spec_with_cov.call("spec_core_ext", ["spec/core_extensions_spec.rb"], "Run core extensions specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|adapters|connection_pool|database|dataset|model)"')}
|
|
136
|
+
spec_with_cov.call("spec_plugin", Dir["spec/extensions/*_spec.rb"], "Run extension/plugin specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|adapters|connection_pool|database|dataset|model)"')}
|
|
124
137
|
spec_with_cov.call("spec_integration", Dir["spec/integration/*_test.rb"], "Run integration tests")
|
|
125
|
-
|
|
126
|
-
%w'postgres sqlite mysql informix oracle firebird mssql'.each do |adapter|
|
|
127
|
-
spec_with_cov.call("spec_#{adapter}", ["spec/adapters/#{adapter}_spec.rb"] + Dir["spec/integration/*_test.rb"], "Run #{adapter} specs")
|
|
138
|
+
|
|
139
|
+
%w'postgres sqlite mysql informix oracle firebird mssql db2'.each do |adapter|
|
|
140
|
+
spec_with_cov.call("spec_#{adapter}", ["spec/adapters/#{adapter}_spec.rb"] + Dir["spec/integration/*_test.rb"], "Run #{adapter} specs"){|t| t.rcov_opts.concat(%w'--exclude "lib/sequel/([a-z_]+\.rb|connection_pool|database|dataset|model|extensions|plugins)"')}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
task :spec_travis=>[:spec, :spec_plugin, :spec_core_ext, :spec_sqlite] do
|
|
144
|
+
if defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby'
|
|
145
|
+
ENV['SEQUEL_PG_SPEC_DB'] = "jdbc:postgresql://localhost/sequel_test?user=postgres"
|
|
146
|
+
ENV['SEQUEL_MY_SPEC_DB'] = "jdbc:mysql://localhost/sequel_test?user=root"
|
|
147
|
+
else
|
|
148
|
+
ENV['SEQUEL_PG_SPEC_DB'] = "postgres://localhost/sequel_test?user=postgres"
|
|
149
|
+
ENV['SEQUEL_MY_SPEC_DB'] = "mysql2://localhost/sequel_test?user=root"
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
Rake::Task['spec_postgres'].invoke
|
|
153
|
+
Rake::Task['spec_mysql'].invoke
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
desc "Run model specs without the associations code"
|
|
157
|
+
task :spec_model_no_assoc do
|
|
158
|
+
ENV['SEQUEL_NO_ASSOCIATIONS'] = '1'
|
|
159
|
+
Rake::Task['_spec_model_no_assoc'].invoke
|
|
128
160
|
end
|
|
129
161
|
rescue LoadError
|
|
130
162
|
task :default do
|
|
@@ -142,7 +174,7 @@ end
|
|
|
142
174
|
desc "Report code statistics (KLOCs, etc) from the application"
|
|
143
175
|
task :stats do
|
|
144
176
|
STATS_DIRECTORIES = [%w(Code lib/), %w(Spec spec)].map{|name, dir| [ name, "./#{dir}" ] }.select { |name, dir| File.directory?(dir)}
|
|
145
|
-
require "extra/stats"
|
|
177
|
+
require "./extra/stats"
|
|
146
178
|
verbose = true
|
|
147
179
|
CodeStatistics.new(*STATS_DIRECTORIES).to_s
|
|
148
180
|
end
|
|
@@ -154,5 +186,5 @@ end
|
|
|
154
186
|
|
|
155
187
|
desc "Check syntax of all .rb files"
|
|
156
188
|
task :check_syntax do
|
|
157
|
-
Dir['**/*.rb'].each{|file| print `#{
|
|
189
|
+
Dir['**/*.rb'].each{|file| print `#{FileUtils::RUBY} -c #{file} | fgrep -v "Syntax OK"`}
|
|
158
190
|
end
|