ANN: Sequel 1.5.0 Released

Sequel is a lightweight database access toolkit for Ruby.

  • Sequel provides thread safety, connection pooling and a concise DSL
    for constructing database queries and table schemas.
  • Sequel also includes a lightweight but comprehensive ORM layer for
    mapping records to Ruby objects and handling associated records.
  • Sequel makes it easy to deal with multiple records without having to
    break your teeth on SQL.
  • Sequel currently has adapters for ADO, DB2, DBI, Informix, JDBC,
    MySQL, ODBC, OpenBase, Oracle, PostgreSQL and SQLite3.

Sequel 1.5.0 has been released and should be available on the gem
mirrors. 1.5.0 has the following exciting new features:

You can now graph a dataset and have the result split into component
tables:

DB[:artists].graph(:albums, :artist_id=>:id).first

=> {:artists=>{:id=>artists.id, :name=>artists.name}, \

:albums=>{:id=>albums.id, :name=>albums.name,

:artist_id=>albums.artist_id}}

This aliases columns if necessary so they don’t stomp on each other,
which
is what usually happens if you just join the tables:

DB[:artists].left_outer_join(:albums, :artist_id=>:id).first

=> {:id=>(albums.id||artists.id),

:name=>(albums.name||artist.names),
:artist_id=>albums.artist_id}

Models can use graph as well, in which case the values will be model
objects:

Artist.graph(Album, :artist_id=>:id)

=> {:artists=>#<Artist…>, :albums=>#<Album…>}

Models can now eager load via .eager_graph, which will load all the
results
and all associations in a single query. This is necessary if you want
to
filter on columns in associated tables. It works exactly the same way
as
.eager, and supports cascading of associations as well:

Artist.one_to_many :albums

Album.one_to_many :tracks

Track.many_to_one :genre

Artist.eager_graph(:albums=>{:tracks=>:genre}).filter(
:tracks_name=>“Firewire”).all

This will give you all artists have have an album with a track named
“Firewire”, and calling .albums on one of those artists will only return
albums that have a track named “Firewire”, and calling .tracks on one of
those albums will return only the track(s) named “Firewire”.

You can use set_graph_aliases to select specific columns:

DB[:artists].graph(:albums, :artist_id=>:id).set_graph_aliases(
:artist_name=>[:artists, :name], :album_name=>[:albums,
:name]).first

=> {:artists=>{:name=>artists.name}, :albums=>{:name=>albums.name}}

You can use eager_graph with set_graph_aliases to have eager loading
with
control over the SELECT clause.

All associations now update their reciprocal associations whenever the
association methods are used, so you don’t need to refresh the
association or model to have the reciprocal association updated:

Album.many_to_one :band
Band.one_to_many :albums

Note that all of these associations are cached,

so after the first access there are no additional

database queries to fetch associated records.

many_to_one setter adds to reciprocal association

band1.albums # => []
album1.band = band1
band1.albums # => [album1]
band2.albums # => []
album1.band = band2
band1.albums # => []
band2.albums # => [album1]
album1.band = band2
band2.albums # => [album1]
album1.band = nil
band2.albums # => []

one_to_many add_* method sets reciprocal association

one_to_many remove_* method removes reciprocal association

album1.band # => nil
band1.add_album(album1)
album1.band # => band1
band2.add_album(album1)
album1.band # => band2
band2.remove_album(album1)
album1.band # => nil

Post.many_to_many :tags
Tag.many_to_many :posts

many_to_many add_* method adds to reciprocal association

many_to_many remove_* method removes from reciprocal association

post1.tags # => []
tag1.posts # => []
tag1.add_post(post1)
post1.tags # => [tag1]
tag1.posts # => [post1]
tag1.remove_post(post1)
post1.tags # => []
tag1.posts # => []
post1.add_tag(tag1)
post1.tags # => [tag1]
tag1.posts # => [post1]
post1.remove_tag(tag1)
post1.tags # => []
tag1.posts # => []

The MySQL and PostgreSQL adapters now support index types:

index :some_column, :type => :hash # or :spatial, :full_text, :rtree,
etc.

Starting in Sequel 1.5.0, some methods are deprecated. These methods
will be
removed in Sequel 2.0.0. The deprecation framework is fairly flexible.
You
can choose where the messages get sent:

Sequel::Deprecation.deprecation_message_stream = STDERR # the default
Sequel::Deprecation.deprecation_message_stream =
File.new(‘deprecation.txt’, ‘wb’) # A file
Sequel::Deprecation.deprecation_message_stream = nil # ignore the
messages

You can even have all deprecation messages accompanied by a traceback,
so you
can see exactly where in your code you are using a deprecated method:

Sequel::Deprecation.print_tracebacks = true

All deprecation methods come with an message telling you what
alternative code
will work.

In addition to deprecating some methods, we removed the ability to have
arrays returned instead of hashes. The array code still had debugging
messages
left it in, and we are not aware of anyone using it. Hashes have been
returned
by default since Sequel 0.3.

We have also removed the Numeric date/time extensions (e.g. 3.days.ago).
The
existing extensions were incomplete, better ones are provided elsewhere,
and the extensions were not really related to Sequel’s purpose.

Sequel no longer depends on ParseTree, RubyInline, or ruby2ruby. They
are
still required to use the block filters. Sequel’s only gem dependency
is on
the tiny metaid.

Sequel 1.5.0 has fixes for 12 tracker issues, including fixes to the
Informix,
MySQL, ODBC, ADO, JDBC, Postgres, and SQLite adapters.

If you have any questions, please post on the Google Group.

Thanks,
Jeremy