Skip to content
Commits on Jul 5, 2008
  1. Bump version to 2.2.0

  2. Major refactoring of association internals

    Implement the association methods with standard instance methods that
    accept the AssociationReflection in addition to any arguments.
    Move many methods from the Associations module (where they ended up
    being Model private class methods) to the AssociationReflection class.
    Add more methods governing behavior to AssociationReflection, which
    should make it much easier to add new association types to Sequel.
    Add AssociationReflection::ASSOCIATION_TYPES containing the allowed
    association types, people wishing to implement new association
    types should add to this array.
    Add a single Model class method for eager loading, instead of creating
    one method per association.
  3. Add :extend association option, for extending a dataset with module(s)

    Update the advanced_associations.rdoc file to show a cool usage of
  4. Expand the advanced_associations.rdoc file

    All examples have now been tested, and an integration test suite will
    be committed soon starting with some of these examples.
Commits on Jul 4, 2008
  1. Add :after_load association callback

    This lets you run code after the associated items have been loaded
    from the database.
    Also, this lets you specify a nil :key option for a many_to_one
    association.  If specified the query will load all records for
    the association, and just give you the first one.  This allows
    many_to_one to work correctly with datasets that use eager_graph,
    as well as with associations where there is no foreign key in the
    current table, or when both are true (which is possible for a
    has_one :through style association).
  2. Only select table.* by default for many_to_many associations

    For other association types, it is not needed, and using it caused
    problems if you wanted to use a :dataset option that included
    an eager_graph call.  Now select is only called on the dataset
    if it is specifically set or many_to_many is used.  If you want
    many_to_many to select all columns, you can use :select=>nil.
    While here, add documentation for the callback options.
Commits on Jul 3, 2008
  1. Remove ParseTree support, the expression syntax is now the only avail…

    …able syntax inside blocks
    Sequel.use_parse_tree always returns false, and
    Sequel.use_parse_tree= raises an Error if the argument given is true.
    Other than the the obvious change to the syntax inside blocks, the
    only significant change is that update no longer takes a block. As
    update only makes sense for equality, a block would not add any value
    over using a hash argument.  Before, it was necessary to take a block
    to do things like x = x + 1, but that has been easily done with
    {:x=>:x + 1} since Sequel 2.0.0.
    No longer include the deprecation feature, but still leave it in the
    repository for future use.
  2. Fix spelling and cover corner case in :descendants eager loading exam…

    …ple in advanced_associations.rdoc
  3. Make validation methods support a :tag option, to work correctly with…

    … source reloading
    If a validation has a :tag option, it overwrites a previous
    validation block with the same tag and attribute (if any), similar to
    how tags work with hooks.
    All validates_*_of methods set the tag to * by default (e.g.
    validates_uniqueness_of uses a :tag of :uniqueness by default). This
    breaks backwards compatibility slightly, if you have two of the same
    type of validations on the same attribute.  If that is the case, add
    a different tag to one or both.
    While here, refactor the :if option handling to be less verbose.
    Also, document all of the supported options to the validates_*_of
    methods, as well as some other documentation improvements.
Commits on Jul 2, 2008
  1. Add doc/advanced_associations.rdoc file, showing off how powerful and…

    … flexible Sequel::Model associations are
  2. Add :before_add, :after_add, :before_remove, :after_remove associatio…

    …n callback options
    These mirror the association callback capabilities of ActiveRecord.
    Each of these options can be a Symbol specifying an instance method
    that takes one argument (the associated object), or a Proc that takes
    two arguments (the current object and the associated object).
    If any of the before callbacks return false, the adding/removing
    does not happen and it either raises an error (the default), or
    returns nil (if raise_on_save_failure is false).
    All callbacks are also run on many_to_one associations.  If there
    was already an existing object for the association, it calls the
    remove callbacks on the existing object and the add callbacks on the
    new object.  The remove callback calls are placed around the add
    callback calls.
    This also separates the many_to_one setter (association=) method into
    two parts, the public association= method, and the private
    _association= method that actually sets the foreign key.  This is
    necessary to support polymorphic associations, where another column
    would also need to be changed, and probably in other cases as well.
    This also changes the many_to_one setter logic somewhat, as it
    doesn't just look in the associations cache for an existing object,
    it just calls the association method, which means using the setter
    can cause database access.  This was necessary to make sure the
    remove callback methods worked correctly for many_to_one
    The many_to_one setter now exits early if the object passed to it
    is the same as the existing object.
Commits on Jul 1, 2008
  1. Model.validates_presence_of now considers false as present instead of…

    … absent
    This makes it usable for NOT NULL boolean fields.
  2. Add Model.raise_on_save_failure, raising errors on save failure inste…

    …ad of return false (now nil), default to true
    This breaks backwards compatibility, but I believe it is the correct
    default for most non-web-apps.  The problem with just returning a
    value is that the return value is often not checked, and I think that
    invalid data should be treated as an exceptional condition by
    Like the strict_param_setting and typecast_on_assignment setting,
    you can turn this off/on at the global, class, and instance level:
      Sequel::Model.raise_on_save_failure = false # Global
      Artist.raise_on_save_failure = true # Class
      artist =
      artist.raise_on_save_failure = false # Instance
    Backwards compatibility is even slightly broken if you turn it off,
    as save and it's variants will now return nil instead of false. The
    exception is save_changes, which will now have the same behavior as
    before, returning nil if no columns changed, and false if the save
  3. Do not apply the :limit association option when eager loading

    Using :limit when eager loading will lead to wrong results in most
    cases, so ignore that option when eager loading.  Note that eager
    loading on a limited dataset still works correctly, it is just the
    :limit association option that is ignored.
    Applying the :limit association option was recently added, but it
    is obviously wrong. Not sure what I was thinking when I added it.
Commits on Jun 30, 2008
  1. Add :eager_loader association option, to specify code to be run when …

    …eager loading
    :eager_loader is powerful option that allows you to completely
    specify how associations are to be eagerly loaded.  It is flexible
    enough that it can be used to eagerly load association types that
    Sequel doesn't even natively support, such as polymorphic
    associations.  The eager loading code has been greatly simplified as
    it now just uses the :eager_loader option, which has defaults that
    are the same as the previous eager loading behavior.
    :eager_loader should be a proc that takes 3 arguments, a key_hash,
    an array of records, and a hash of dependent associations.  Since you
    are given all of the records, you can do things like filter on
    associations that are specified by multiple keys, or do multiple
    queries depending on the content of the records (which would be
    necessary for polymorphic associations).  Inside the :eager_loader
    proc, you should get the related objects and populate the
    associations for all objects in the array of records.  The hash
    of dependent associations is available for you to cascade the eager
    loading down multiple levels, but it is up to you to use it.  The
    key_hash is a performance enhancement that is used by the default
    code and is also available to you.  It is a hash with keys being
    foreign/primary key symbols in the current table, and the values
    being hashes where the key is foreign/primary key values and values
    being arrays of current model objects having the foreign/primary key
    value associated with the key.  This is hard to visualize, so I'll
    give an example:
      album1 = Album.load(:id=>1, :artist_id=>2)
      album2 = Album.load(:id=>3, :artist_id=>2)
      Album.many_to_one :artist
      Album.one_to_many :tracks
      Album.eager(:band, :tracks).all
      # The key_hash provided to the :eager_loader proc would be:
      {:id=>{1=>[album1], 3=>[album2]}, :artist_id=>{2=>[album1, album2]}}
  2. Make :many_to_one associations support :dataset, :order, :limit assoc…

    …iation options, as well as block arguments
    This makes the many_to_one association code use the same
    infrastructure as the other association code for getting records.
    This also makes it create a _dataset method for many_to_one
    associations, just as it does for other associations.  Because the
    same infrastructure is used, it automatically supports the :order,
    :limit (to specify offset), and :dataset options, as well as a block
    This can be used to set up ActiveRecord has_one-style associations,
    by using a :dataset option, instead of using a one_to_many
    association with the :one_to_one option:
      Band.many_to_one :band_info, :key=>:id, \
        :dataset=>proc{BandInfo.filter(:band_id => id)}
    This commit also refactors some private association methods to remove
    the redundant name argument, since it is included in the
  3. Refactor add_/remove_/remove_all_ association method creation

    This adds the add_reciprocal_object and remove_reciprocal_object
    instance methods to Sequel::Model, which makes it possible to merge
    the add_/remove_/remove_all_ methods created by many_to_many and
    one_to_many associations.  This simplifies the code and should be
    more readable.
    Also, remove some symbol proliferation in the many_to_many case.
  4. Add :dataset association option, which overrides the default base dat…

    …aset to use
    The :dataset option should be a proc, which is instance_evaled to get
    the base dataset to use.  It is currently only used for :one_to_many
    and :many_to_many associations, but will be extended to :many_to_one
    associations soon.
    Some examples of use:
      Artist.one_to_many :albums_not_by, :class=>:Album, \
      Album.many_to_many :genres, \
        :dataset=>proc{Genre.join_table(:natural, :albums_genres) \
Commits on Jun 27, 2008
  1. Add the :eager_graph association option, works just like :eager excep…

    …t it uses #eager_graph
    This doesn't work perfectly yet, as the association filters don't use
    qualified columns.  That will be fixed in a later commit.
  2. Add :graph_join_table_join_type association option

    This can be used to specify the type of SQL join to use for the join
    table when eagerly loading the association via #eager_graph.  It
    defaults to the :graph_join_type option, or :left_outer if that
    is not used.
  3. Add :graph_only_conditions and :graph_join_table_only_conditions asso…

    …ciation options
    These allow you to override the default conditions specified via the
    foreign/primary keys.  They can be used to specify NATURAL joins or
    USING joins.  When using these options, you can specify any condition
    that Dataset#join_table will accept.  If you use a hash or an array
    of all two pairs, it will qualify unqualified columns the same way
    it usual does in Dataset#join_table.  Examples:
      # Artist primary key is artist_id, same as foreign key in albums
      # table.  This will do a JOIN USING.
      Artist.one_to_many :albums, :graph_only_conditions=>[:artist_id]
      # Same, but assumes that all columns in both tables are unique,
      # except for the key columns.  This will do a NATURAL JOIN.
      Artist.one_to_many :albums, :graph_only_conditions=>nil, \
  4. Add support for :graph_block and :graph_join_table_block association …

    These allow you to specify arbitrary conditions on joins when eager loading
    via eager_graph.  For example:
      Artist.one_to_many(:gold_albums, :class=>Album, \
        :graph_block=>proc{|ja,lja,js| :copies_sold.qualify(ja) > 500000}) \
        do |ds|
        ds.filter(:copies_sold > 500000)
Commits on Jun 26, 2008
  1. Set the model's dataset's columns in addition to the model columns wh…

    …en loading the schema
    This should save a query (potentially many queries) to get the
    columns for model datasets.
Commits on Jun 18, 2008
Commits on Jun 17, 2008
  1. For PostgreSQL, don't raise an error when assigning a value to a SERI…

    …AL PRIMARY KEY field when inserting records
  2. Bump version to 2.1.0

Commits on Jun 16, 2008
Something went wrong with that request. Please try again.