1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
|
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
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) (
+
* Add Dataset
* Make Dataset
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
|