Pastie now auto-senses if line-wrap is a bad or good idea. Feedback?
## mark a section (Learn more)
From 0ebe58ed686bd44273409b6c429c2d8c56f0f352 Mon Sep 17 00:00:00 2001 From: Jeremy Evans <code@jeremyevans.net> Date: Sat, 11 Jul 2009 11:09:06 -0700 Subject: [PATCH] Model associations now default to associating to classes in the same scope (Fixes #274) This changes the default for the :class_name option to use a model in the same scope as the current model. This is a slight breakage of backwards compatibility, but should only affect users who are associating a model inside a module to a model outside the module. Defaulting to an object in the same scope leads to less surprising behavior. This patch also is a cleaner implementation, since the code no longer varies per association type. --- CHANGELOG | 2 ++ lib/sequel/model/associations.rb | 4 +--- lib/sequel/plugins/many_through_many.rb | 1 - spec/extensions/many_through_many_spec.rb | 13 +++++++++++++ spec/model/associations_spec.rb | 20 ++++++++++++++++++++ 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 07e2def..7b7750a 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,5 +1,7 @@ === HEAD +* Model associations now default to associating to classes in the same scope (jeremyevans, nougad) (#274) + * Add Dataset#unlimited, similar to unfiltered and unordered (jeremyevans) * Make Dataset#from_self take an options hash and respect an :alias option, giving the alias to use (Phrogz) diff --git a/lib/sequel/model/associations.rb b/lib/sequel/model/associations.rb index 24176af..275edbf 100644 --- a/lib/sequel/model/associations.rb +++ b/lib/sequel/model/associations.rb @@ -548,6 +548,7 @@ module Sequel when Class opts[:class_name] ||= opts[:class].name end + opts[:class_name] ||= (opts[:model].name.split("::")[0..-2] + [camelize(opts.returns_array? ? singularize(name) : name)]).join('::') send(:"def_#{type}", opts) @@ -646,7 +647,6 @@ module Sequel left = (opts[:left_key] ||= opts.default_left_key) right = (opts[:right_key] ||= opts.default_right_key) left_pk = (opts[:left_primary_key] ||= self.primary_key) - opts[:class_name] ||= camelize(singularize(name)) opts[:cartesian_product_number] ||= 1 join_table = (opts[:join_table] ||= opts.default_join_table) left_key_alias = opts[:left_key_alias] ||= opts.default_associated_key_alias @@ -705,7 +705,6 @@ module Sequel opts[:key] = opts.default_key unless opts.include?(:key) key = opts[:key] opts[:cartesian_product_number] ||= 0 - opts[:class_name] ||= camelize(name) opts[:dataset] ||= proc do klass = opts.associated_class klass.filter(SQL::QualifiedIdentifier.new(klass.table_name, opts.primary_key)=>send(key)) @@ -750,7 +749,6 @@ module Sequel model = self key = (opts[:key] ||= opts.default_key) primary_key = (opts[:primary_key] ||= self.primary_key) - opts[:class_name] ||= camelize(singularize(name)) opts[:dataset] ||= proc do klass = opts.associated_class klass.filter(SQL::QualifiedIdentifier.new(klass.table_name, key) => send(primary_key)) diff --git a/lib/sequel/plugins/many_through_many.rb b/lib/sequel/plugins/many_through_many.rb index bdb18fa..490c85d 100644 --- a/lib/sequel/plugins/many_through_many.rb +++ b/lib/sequel/plugins/many_through_many.rb @@ -125,7 +125,6 @@ module Sequel name = opts[:name] model = self opts[:read_only] = true - opts[:class_name] ||= camelize(singularize(name)) opts[:after_load].unshift(:array_uniq!) if opts[:uniq] opts[:cartesian_product_number] ||= 2 opts[:through] = opts[:through].map do |e| diff --git a/spec/extensions/many_through_many_spec.rb b/spec/extensions/many_through_many_spec.rb index 694430d..e547829 100644 --- a/spec/extensions/many_through_many_spec.rb +++ b/spec/extensions/many_through_many_spec.rb @@ -23,6 +23,19 @@ describe Sequel::Model, "many_through_many" do Object.send(:remove_const, :Tag) end + it "should default to associating to other models in the same scope" do + class ::AssociationModuleTest + class Artist < Sequel::Model + plugin :many_through_many + many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id, :tag_id]] + end + class Tag < Sequel::Model + end + end + + ::AssociationModuleTest::Artist.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag + end + it "should raise an error if in invalid form of through is used" do proc{@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], [:albums_tags, :album_id]]}.should raise_error(Sequel::Error) proc{@c1.many_through_many :tags, [[:albums_artists, :artist_id, :album_id], [:albums, :id, :id], {:table=>:album_tags, :left=>:album_id}]}.should raise_error(Sequel::Error) diff --git a/spec/model/associations_spec.rb b/spec/model/associations_spec.rb index d02725a..6a9885a 100644 --- a/spec/model/associations_spec.rb +++ b/spec/model/associations_spec.rb @@ -16,6 +16,26 @@ describe Sequel::Model, "associate" do klass.association_reflection(:"par_parent2s").associated_class.should == ParParent end + it "should default to associating to other models in the same scope" do + class ::AssociationModuleTest + class Album < Sequel::Model + many_to_one :artist + many_to_many :tags + end + class Artist< Sequel::Model + one_to_many :albums + end + class Tag < Sequel::Model + many_to_many :albums + end + end + + ::AssociationModuleTest::Album.association_reflection(:artist).associated_class.should == ::AssociationModuleTest::Artist + ::AssociationModuleTest::Album.association_reflection(:tags).associated_class.should == ::AssociationModuleTest::Tag + ::AssociationModuleTest::Artist.association_reflection(:albums).associated_class.should == ::AssociationModuleTest::Album + ::AssociationModuleTest::Tag.association_reflection(:albums).associated_class.should == ::AssociationModuleTest::Album + end + it "should add a model_object and association_reflection accessors to the dataset, and return it with the current model object" do MODEL_DB.reset klass = Class.new(Sequel::Model(:nodes)) do -- 1.6.1.3
This paste will be private.
From the Design Piracy series on my blog: