- A TimestampMigrator has been added to Sequel, and is automatically used
if any migration has a version greater than
- This migrator operates similarly to the default
ActiveRecord migrator, in that it allows missing migrations. It differs
from the ActiveRecord migrator in that it supports migrations with the same
timestamp/version as well as a wide variety of timestamp formats (though
the ActiveRecord default of YYYYMMDDHHMMSS is recommended and should be
used in portable code).
Sequel still defaults to the old
migrator, but you can use the new one without making changes to your old
migrations. Just make sure your new migration starts with a version greater
than 20000100, and Sequel will
automatically convert the previous schema table to the new format.
- A new migration DSL was added:
Sequel.migration do
up do
end
down do
end
end
The old style of using a Sequel::Migration
subclass is still supported, but it is recommended that new code use the
new DSL.
- The default migrator also had significant issues fixed. First, it now saves
the migration version after each migration, instead of after all
migrations, which means Sequel
won‘t attempt to apply already applied migrations if there was
previously an error when applying multiple migrations at once on a database
that didn‘t support transactional schema modification.
Second, duplicate migration versions in the default migrator now raise an
exception, as do missing migration versions. Neither should happen when
using the default migrator, which requires consecutive integer versions,
similar to the old ActiveRecord migrator.
- Execution times for migrations are now logged to the database‘s
loggers.
- Sequel::Model#set_fields and update_fields were added. These methods have a
similar API to set_only and update_only, but they operate differently.
While set_only and update_only operate over the hash, these methods operate
over the array of fields, so they don‘t raise errors if the hash
contains fields not in the array:
params = {:a=>1, :b=>2, :c=>3}
album = Album[1]
# raises Error because :a is not in the fields
album.set_only(params, [:b, :c])
# Just sets the value of album.b and album.c
album.set_fields(params, [:b, :c])
Other than handling entries in the hash that aren‘t in the array,
set_fields and update_fields also handle entries not in the hash
differently:
# Doesn't modify the object, since the hash is empty
album.set_only({}, [:b, :c])
# Sets album.b and album.c to nil, since they aren't in the hash
album.set_fields({}, [:b, :c])
- The :eager_loader association option has a new API, though the previous API
still works. Instead of accepting three arguments, it can now accept a
single hash argument, which will use the :key_hash, :rows, and :association
keys for the previous three arguments. The hash will also contain a :self
key whose value is the dataset doing the eager load, which was not possible
to determine using the old API.
- Sequel::SQL::Expression#hash has been added so that the objects are now
safe to use as hash keys.
- A Dataset#order_prepend method has been added allowing you to prepend to an
existing order. This is useful if want to modify a dataset‘s order
such that it first orders by the columns you provide, but for any rows
where the columns you provide are equal, uses the existing order to further
order the dataset:
ds.order(:albums__name).order_prepend(:artists__name)
# ORDER BY artists.name, albums.name
- When creating foreign key columns, you can now use a :deferrable option to
set up a foreign key constraint that is not checked until the end of the
transaction:
DB.create_table(:albums) do
primary_key :id
String :name
foreign_key :artist_id, :artists, :deferrable=>true
end
- many_to_many associations now support a :join_table_block option that is
used by the add/remove/remove_all methods. It can modify the dataset to
ensure that certain columns are included when inserting or to add a filter
so that only certain records are deleted. It‘s useful if you have a
many_to_many association that is filtered to only a subset of the matching
rows in the join table.
- The single_table_inheritance plugin now supports :model_map and :key_map
options to set up a custom mapping of column values to model classes. For
simple situations such as when you are mapping integer values to certain
classes, a :model_map hash is sufficient:
Employee.plugin :single_table_inheritance, :type_id,
:model_map=>{1=>:Staff, 2=>:Manager}
Here the :model_map keys are type_id column values, and the :model_map
values are symbols or strings specifying class names.
For more complex conditions, you can use a pair of procs:
Employee.plugin :single_table_inheritance, :type_name,
:model_map=>proc{|v| v.reverse},
:key_map=>proc{|klass| klass.name.reverse}
Here the type_name column is a string column holding the reverse of the
class‘s name.
- The single_table_inheritance plugin now correctly sets up subclass filters
for middle tables in a class hierarchy with more than 2 levels. For
example, with this code:
class Employee < Sequel::Model; end
Employee.plugin :single_table_inheritance, :kind
class Manager < Employee; end
class Executive < Manager; end
Sequel previously would not
return Executives if you used Manager.all. It now correctly recognizes
subclasses so that it will return both Managers and Executives.
- Sequel::Model.qualified_primary_key_hash has been added, giving you a hash
that can be used for filtering. It is similar to primary_key_hash, but it
qualifies the keys with the model‘s table. It‘s useful if you
have joined the table to another table that has columns with the same name,
but you want to only look for a single model object in that dataset.
- For consistency, you can now use Dataset#order_append as an alias for
order_more.