sequel 1.5.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/CHANGELOG +30 -0
- data/README +12 -15
- data/Rakefile +9 -20
- data/lib/sequel_model.rb +47 -72
- data/lib/sequel_model/association_reflection.rb +59 -0
- data/lib/sequel_model/associations.rb +99 -94
- data/lib/sequel_model/base.rb +308 -102
- data/lib/sequel_model/caching.rb +72 -27
- data/lib/sequel_model/eager_loading.rb +308 -300
- data/lib/sequel_model/hooks.rb +51 -49
- data/lib/sequel_model/inflector.rb +186 -182
- data/lib/sequel_model/plugins.rb +54 -40
- data/lib/sequel_model/record.rb +185 -220
- data/lib/sequel_model/schema.rb +27 -34
- data/lib/sequel_model/validations.rb +54 -73
- data/spec/association_reflection_spec.rb +85 -0
- data/spec/associations_spec.rb +160 -73
- data/spec/base_spec.rb +3 -3
- data/spec/eager_loading_spec.rb +132 -35
- data/spec/hooks_spec.rb +120 -20
- data/spec/inflector_spec.rb +2 -2
- data/spec/model_spec.rb +110 -78
- data/spec/plugins_spec.rb +4 -0
- data/spec/rcov.opts +1 -1
- data/spec/record_spec.rb +160 -59
- data/spec/spec.opts +0 -5
- data/spec/spec_helper.rb +12 -0
- data/spec/validations_spec.rb +23 -0
- metadata +60 -50
- data/lib/sequel_model/deprecated.rb +0 -81
- data/lib/sequel_model/inflections.rb +0 -112
- data/spec/deprecated_relations_spec.rb +0 -113
data/lib/sequel_model/schema.rb
CHANGED
@@ -1,50 +1,43 @@
|
|
1
1
|
module Sequel
|
2
2
|
class Model
|
3
|
-
# Defines a table schema (see Schema::Generator for more information).
|
4
|
-
#
|
5
|
-
# This is only needed if you want to use the create_table or drop_table
|
6
|
-
# methods.
|
7
|
-
def self.set_schema(name = nil, &block)
|
8
|
-
if name
|
9
|
-
set_dataset(db[name])
|
10
|
-
end
|
11
|
-
@schema = Schema::Generator.new(db, &block)
|
12
|
-
if @schema.primary_key_name
|
13
|
-
set_primary_key @schema.primary_key_name
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
# Returns table schema for direct descendant of Model.
|
18
|
-
def self.schema
|
19
|
-
@schema || ((superclass != Model) && (superclass.schema))
|
20
|
-
end
|
21
|
-
|
22
|
-
# Returns name of table.
|
23
|
-
def self.table_name
|
24
|
-
dataset.opts[:from].first
|
25
|
-
end
|
26
|
-
|
27
|
-
# Returns true if table exists, false otherwise.
|
28
|
-
def self.table_exists?
|
29
|
-
db.table_exists?(table_name)
|
30
|
-
end
|
31
|
-
|
32
3
|
# Creates table.
|
33
4
|
def self.create_table
|
34
5
|
db.create_table_sql_list(table_name, *schema.create_info).each {|s| db << s}
|
35
|
-
@
|
6
|
+
@db_schema = get_db_schema unless @@lazy_load_schema
|
36
7
|
columns
|
37
8
|
end
|
38
9
|
|
10
|
+
# Drops the table if it exists and then runs create_table.
|
11
|
+
def self.create_table!
|
12
|
+
drop_table if table_exists?
|
13
|
+
create_table
|
14
|
+
end
|
15
|
+
|
39
16
|
# Drops table.
|
40
17
|
def self.drop_table
|
41
18
|
db.execute db.drop_table_sql(table_name)
|
42
19
|
end
|
20
|
+
|
21
|
+
# Returns table schema created with set_schema for direct descendant of Model.
|
22
|
+
# Does not retreive schema information from the database, see db_schema if you
|
23
|
+
# want that.
|
24
|
+
def self.schema
|
25
|
+
@schema || ((superclass != Model) && (superclass.schema))
|
26
|
+
end
|
27
|
+
|
28
|
+
# Defines a table schema (see Schema::Generator for more information).
|
29
|
+
#
|
30
|
+
# This is only needed if you want to use the create_table or drop_table
|
31
|
+
# methods.
|
32
|
+
def self.set_schema(name = nil, &block)
|
33
|
+
set_dataset(db[name]) if name
|
34
|
+
@schema = Schema::Generator.new(db, &block)
|
35
|
+
set_primary_key(@schema.primary_key_name) if @schema.primary_key_name
|
36
|
+
end
|
43
37
|
|
44
|
-
#
|
45
|
-
def self.
|
46
|
-
|
47
|
-
create_table
|
38
|
+
# Returns true if table exists, false otherwise.
|
39
|
+
def self.table_exists?
|
40
|
+
db.table_exists?(table_name)
|
48
41
|
end
|
49
42
|
end
|
50
43
|
end
|
@@ -1,17 +1,3 @@
|
|
1
|
-
class Array
|
2
|
-
# Removes and returns the last member of the array if it is a hash. Otherwise,
|
3
|
-
# an empty hash is returned This method is useful when writing methods that
|
4
|
-
# take an options hash as the last parameter. For example:
|
5
|
-
#
|
6
|
-
# def validate_each(*args, &block)
|
7
|
-
# opts = args.extract_options!
|
8
|
-
# ...
|
9
|
-
# end
|
10
|
-
def extract_options!
|
11
|
-
last.is_a?(Hash) ? pop : {}
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
1
|
# The Validations module provides validation capabilities as a mixin. When
|
16
2
|
# included into a class, it enhances the class with class and instance
|
17
3
|
# methods for defining validations and validating class instances.
|
@@ -41,12 +27,15 @@ module Validation
|
|
41
27
|
# Validates the object.
|
42
28
|
def validate
|
43
29
|
errors.clear
|
30
|
+
return false if before_validation == false
|
44
31
|
self.class.validate(self)
|
32
|
+
after_validation
|
33
|
+
nil
|
45
34
|
end
|
46
35
|
|
47
36
|
# Validates the object and returns true if no errors are reported.
|
48
37
|
def valid?
|
49
|
-
validate
|
38
|
+
return false if validate == false
|
50
39
|
errors.empty?
|
51
40
|
end
|
52
41
|
|
@@ -57,9 +46,9 @@ module Validation
|
|
57
46
|
@errors = Hash.new {|h, k| h[k] = []}
|
58
47
|
end
|
59
48
|
|
60
|
-
#
|
61
|
-
def
|
62
|
-
@errors
|
49
|
+
# Adds an error for the given attribute.
|
50
|
+
def add(att, msg)
|
51
|
+
@errors[att] << msg
|
63
52
|
end
|
64
53
|
|
65
54
|
# Clears all errors.
|
@@ -67,25 +56,14 @@ module Validation
|
|
67
56
|
@errors.clear
|
68
57
|
end
|
69
58
|
|
70
|
-
# Returns size of errors array
|
71
|
-
def size
|
72
|
-
@errors.size
|
73
|
-
end
|
74
|
-
|
75
59
|
# Iterates over errors
|
76
60
|
def each(&block)
|
77
61
|
@errors.each(&block)
|
78
62
|
end
|
79
63
|
|
80
|
-
# Returns
|
81
|
-
def
|
82
|
-
@errors
|
83
|
-
end
|
84
|
-
alias_method :[], :on
|
85
|
-
|
86
|
-
# Adds an error for the given attribute.
|
87
|
-
def add(att, msg)
|
88
|
-
@errors[att] << msg
|
64
|
+
# Returns true if no errors are stored.
|
65
|
+
def empty?
|
66
|
+
@errors.empty?
|
89
67
|
end
|
90
68
|
|
91
69
|
# Returns an array of fully-formatted error messages.
|
@@ -95,6 +73,17 @@ module Validation
|
|
95
73
|
m
|
96
74
|
end
|
97
75
|
end
|
76
|
+
|
77
|
+
# Returns the errors for the given attribute.
|
78
|
+
def on(att)
|
79
|
+
@errors[att]
|
80
|
+
end
|
81
|
+
alias_method :[], :on
|
82
|
+
|
83
|
+
# Returns size of errors array
|
84
|
+
def size
|
85
|
+
@errors.size
|
86
|
+
end
|
98
87
|
end
|
99
88
|
|
100
89
|
# The Generator class is used to generate validation definitions using
|
@@ -114,6 +103,16 @@ module Validation
|
|
114
103
|
|
115
104
|
# Validation class methods.
|
116
105
|
module ClassMethods
|
106
|
+
# Returns true if validations are defined.
|
107
|
+
def has_validations?
|
108
|
+
!validations.empty?
|
109
|
+
end
|
110
|
+
|
111
|
+
# Instructs the model to skip validations defined in superclasses
|
112
|
+
def skip_superclass_validations
|
113
|
+
@skip_superclass_validations = true
|
114
|
+
end
|
115
|
+
|
117
116
|
# Defines validations by converting a longhand block into a series of
|
118
117
|
# shorthand definitions. For example:
|
119
118
|
#
|
@@ -135,16 +134,6 @@ module Validation
|
|
135
134
|
Generator.new(self, &block)
|
136
135
|
end
|
137
136
|
|
138
|
-
# Returns the validations hash for the class.
|
139
|
-
def validations
|
140
|
-
@validations ||= Hash.new {|h, k| h[k] = []}
|
141
|
-
end
|
142
|
-
|
143
|
-
# Returns true if validations are defined.
|
144
|
-
def has_validations?
|
145
|
-
!validations.empty?
|
146
|
-
end
|
147
|
-
|
148
137
|
# Validates the given instance.
|
149
138
|
def validate(o)
|
150
139
|
if superclass.respond_to?(:validate) && !@skip_superclass_validations
|
@@ -156,21 +145,6 @@ module Validation
|
|
156
145
|
end
|
157
146
|
end
|
158
147
|
|
159
|
-
def skip_superclass_validations
|
160
|
-
@skip_superclass_validations = true
|
161
|
-
end
|
162
|
-
|
163
|
-
# Adds a validation for each of the given attributes using the supplied
|
164
|
-
# block. The block must accept three arguments: instance, attribute and
|
165
|
-
# value, e.g.:
|
166
|
-
#
|
167
|
-
# validates_each :name, :password do |object, attribute, value|
|
168
|
-
# object.errors[attribute] << 'is not nice' unless value.nice?
|
169
|
-
# end
|
170
|
-
def validates_each(*atts, &block)
|
171
|
-
atts.each {|a| validations[a] << block}
|
172
|
-
end
|
173
|
-
|
174
148
|
# Validates acceptance of an attribute.
|
175
149
|
def validates_acceptance_of(*atts)
|
176
150
|
opts = {
|
@@ -198,6 +172,17 @@ module Validation
|
|
198
172
|
end
|
199
173
|
end
|
200
174
|
|
175
|
+
# Adds a validation for each of the given attributes using the supplied
|
176
|
+
# block. The block must accept three arguments: instance, attribute and
|
177
|
+
# value, e.g.:
|
178
|
+
#
|
179
|
+
# validates_each :name, :password do |object, attribute, value|
|
180
|
+
# object.errors[attribute] << 'is not nice' unless value.nice?
|
181
|
+
# end
|
182
|
+
def validates_each(*atts, &block)
|
183
|
+
atts.each {|a| validations[a] << block}
|
184
|
+
end
|
185
|
+
|
201
186
|
# Validates the format of an attribute.
|
202
187
|
def validates_format_of(*atts)
|
203
188
|
opts = {
|
@@ -239,20 +224,23 @@ module Validation
|
|
239
224
|
end
|
240
225
|
end
|
241
226
|
|
242
|
-
NUMBER_RE = /^\d*\.{0,1}\d+$/
|
243
|
-
INTEGER_RE = /\A[+-]?\d+\Z/
|
244
|
-
|
245
227
|
# Validates whether an attribute is a number.
|
246
228
|
def validates_numericality_of(*atts)
|
247
229
|
opts = {
|
248
230
|
:message => 'is not a number',
|
249
231
|
}.merge!(atts.extract_options!)
|
250
232
|
|
251
|
-
re = opts[:only_integer] ? INTEGER_RE : NUMBER_RE
|
252
|
-
|
253
233
|
validates_each(*atts) do |o, a, v|
|
254
234
|
next if (v.nil? && opts[:allow_nil]) || (v.blank? && opts[:allow_blank])
|
255
|
-
|
235
|
+
begin
|
236
|
+
if opts[:only_integer]
|
237
|
+
Kernel.Integer(v.to_s)
|
238
|
+
else
|
239
|
+
Kernel.Float(v.to_s)
|
240
|
+
end
|
241
|
+
rescue
|
242
|
+
o.errors[a] << opts[:message]
|
243
|
+
end
|
256
244
|
end
|
257
245
|
end
|
258
246
|
|
@@ -297,17 +285,10 @@ module Validation
|
|
297
285
|
o.errors[a] << opts[:message] unless allow
|
298
286
|
end
|
299
287
|
end
|
300
|
-
end
|
301
|
-
end
|
302
288
|
|
303
|
-
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
alias_method :save!, :save
|
308
|
-
def save(*args)
|
309
|
-
return false unless valid?
|
310
|
-
save!(*args)
|
289
|
+
# Returns the validations hash for the class.
|
290
|
+
def validations
|
291
|
+
@validations ||= Hash.new {|h, k| h[k] = []}
|
311
292
|
end
|
312
293
|
end
|
313
294
|
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require File.join(File.dirname(__FILE__), "spec_helper")
|
2
|
+
|
3
|
+
describe Sequel::Model::Associations::AssociationReflection, "#associated_class" do
|
4
|
+
before do
|
5
|
+
@c = Class.new(Sequel::Model)
|
6
|
+
class ParParent < Sequel::Model; end
|
7
|
+
end
|
8
|
+
|
9
|
+
it "should use the :class value if present" do
|
10
|
+
@c.many_to_one :c, :class=>ParParent
|
11
|
+
@c.association_reflection(:c).should include(:class)
|
12
|
+
@c.association_reflection(:c).associated_class.should == ParParent
|
13
|
+
end
|
14
|
+
it "should figure out the class if the :class value is not present" do
|
15
|
+
@c.many_to_one :c, :class=>'ParParent'
|
16
|
+
@c.association_reflection(:c).should_not include(:class)
|
17
|
+
@c.association_reflection(:c).associated_class.should == ParParent
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe Sequel::Model::Associations::AssociationReflection, "#associated_primary_key" do
|
22
|
+
before do
|
23
|
+
@c = Class.new(Sequel::Model)
|
24
|
+
class ParParent < Sequel::Model; end
|
25
|
+
end
|
26
|
+
|
27
|
+
it "should use the :right_primary_key value if present" do
|
28
|
+
@c.many_to_one :c, :class=>ParParent, :associated_primary_key=>:blah__blah
|
29
|
+
@c.association_reflection(:c).should include(:associated_primary_key)
|
30
|
+
@c.association_reflection(:c).associated_primary_key.should == :blah__blah
|
31
|
+
end
|
32
|
+
it "should use the associated table's primary key if :associated_primary_key is not present" do
|
33
|
+
@c.many_to_one :c, :class=>'ParParent'
|
34
|
+
@c.association_reflection(:c).should_not include(:associated_primary_key)
|
35
|
+
@c.association_reflection(:c).associated_primary_key.should == :id
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe Sequel::Model::Associations::AssociationReflection, "#reciprocal" do
|
40
|
+
it "should use the :reciprocal value if present" do
|
41
|
+
@c = Class.new(Sequel::Model)
|
42
|
+
@d = Class.new(Sequel::Model)
|
43
|
+
@c.many_to_one :c, :class=>@d, :reciprocal=>:@xx
|
44
|
+
@c.association_reflection(:c).should include(:reciprocal)
|
45
|
+
@c.association_reflection(:c).reciprocal.should == :@xx
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should figure out the reciprocal if the :reciprocal value is not present" do
|
49
|
+
class ParParent < Sequel::Model; end
|
50
|
+
class ParParentTwo < Sequel::Model; end
|
51
|
+
class ParParentThree < Sequel::Model; end
|
52
|
+
ParParent.many_to_one :par_parent_two
|
53
|
+
ParParentTwo.one_to_many :par_parents
|
54
|
+
ParParent.many_to_many :par_parent_threes
|
55
|
+
ParParentThree.many_to_many :par_parents
|
56
|
+
|
57
|
+
ParParent.association_reflection(:par_parent_two).should_not include(:reciprocal)
|
58
|
+
ParParent.association_reflection(:par_parent_two).reciprocal.should == :@par_parents
|
59
|
+
ParParentTwo.association_reflection(:par_parents).should_not include(:reciprocal)
|
60
|
+
ParParentTwo.association_reflection(:par_parents).reciprocal.should == :@par_parent_two
|
61
|
+
ParParent.association_reflection(:par_parent_threes).should_not include(:reciprocal)
|
62
|
+
ParParent.association_reflection(:par_parent_threes).reciprocal.should == :@par_parents
|
63
|
+
ParParentThree.association_reflection(:par_parents).should_not include(:reciprocal)
|
64
|
+
ParParentThree.association_reflection(:par_parents).reciprocal.should == :@par_parent_threes
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe Sequel::Model::Associations::AssociationReflection, "#select" do
|
69
|
+
before do
|
70
|
+
@c = Class.new(Sequel::Model)
|
71
|
+
class ParParent < Sequel::Model; end
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should use the :select value if present" do
|
75
|
+
@c.many_to_one :c, :class=>ParParent, :select=>[:par_parents__id]
|
76
|
+
@c.association_reflection(:c).should include(:select)
|
77
|
+
@c.association_reflection(:c).select.should == [:par_parents__id]
|
78
|
+
end
|
79
|
+
it "should use the associated_table.* if :select is not present" do
|
80
|
+
@c.many_to_one :c, :class=>'ParParent'
|
81
|
+
@c.association_reflection(:c).should_not include(:select)
|
82
|
+
@c.association_reflection(:c).select.should == :par_parents.*
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
data/spec/associations_spec.rb
CHANGED
@@ -11,9 +11,9 @@ describe Sequel::Model, "associate" do
|
|
11
11
|
klass.associate :one_to_many, :par_parent1s, :class=>'ParParent'
|
12
12
|
klass.associate :many_to_many, :par_parent2s, :class=>:ParParent
|
13
13
|
|
14
|
-
klass.
|
15
|
-
klass.
|
16
|
-
klass.
|
14
|
+
klass.association_reflection(:"par_parent0").associated_class.should == ParParent
|
15
|
+
klass.association_reflection(:"par_parent1s").associated_class.should == ParParent
|
16
|
+
klass.association_reflection(:"par_parent2s").associated_class.should == ParParent
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
@@ -42,7 +42,7 @@ describe Sequel::Model, "many_to_one" do
|
|
42
42
|
p.class.should == @c2
|
43
43
|
p.values.should == {:x => 1, :id => 1}
|
44
44
|
|
45
|
-
MODEL_DB.sqls.should == ["SELECT
|
45
|
+
MODEL_DB.sqls.should == ["SELECT nodes.* FROM nodes WHERE (id = 234) LIMIT 1"]
|
46
46
|
end
|
47
47
|
|
48
48
|
it "should use implicit class if omitted" do
|
@@ -55,7 +55,7 @@ describe Sequel::Model, "many_to_one" do
|
|
55
55
|
p = d.par_parent
|
56
56
|
p.class.should == ParParent
|
57
57
|
|
58
|
-
MODEL_DB.sqls.should == ["SELECT
|
58
|
+
MODEL_DB.sqls.should == ["SELECT par_parents.* FROM par_parents WHERE (id = 234) LIMIT 1"]
|
59
59
|
end
|
60
60
|
|
61
61
|
it "should use class inside module if given as a string" do
|
@@ -70,7 +70,7 @@ describe Sequel::Model, "many_to_one" do
|
|
70
70
|
p = d.par_parent
|
71
71
|
p.class.should == Par::Parent
|
72
72
|
|
73
|
-
MODEL_DB.sqls.should == ["SELECT
|
73
|
+
MODEL_DB.sqls.should == ["SELECT parents.* FROM parents WHERE (id = 234) LIMIT 1"]
|
74
74
|
end
|
75
75
|
|
76
76
|
it "should use explicit key if given" do
|
@@ -81,7 +81,13 @@ describe Sequel::Model, "many_to_one" do
|
|
81
81
|
p.class.should == @c2
|
82
82
|
p.values.should == {:x => 1, :id => 1}
|
83
83
|
|
84
|
-
MODEL_DB.sqls.should == ["SELECT
|
84
|
+
MODEL_DB.sqls.should == ["SELECT nodes.* FROM nodes WHERE (id = 567) LIMIT 1"]
|
85
|
+
end
|
86
|
+
|
87
|
+
it "should use :select option if given" do
|
88
|
+
@c2.many_to_one :parent, :class => @c2, :key => :blah, :select=>[:id, :name]
|
89
|
+
@c2.new(:id => 1, :blah => 567).parent
|
90
|
+
MODEL_DB.sqls.should == ["SELECT id, name FROM nodes WHERE (id = 567) LIMIT 1"]
|
85
91
|
end
|
86
92
|
|
87
93
|
it "should return nil if key value is nil" do
|
@@ -101,9 +107,9 @@ describe Sequel::Model, "many_to_one" do
|
|
101
107
|
d = @c2.new(:id => 1, :parent_id=>555)
|
102
108
|
MODEL_DB.sqls.should == []
|
103
109
|
d.parent.should == nil
|
104
|
-
MODEL_DB.sqls.should == ['SELECT
|
110
|
+
MODEL_DB.sqls.should == ['SELECT nodes.* FROM nodes WHERE (id = 555) LIMIT 1']
|
105
111
|
d.parent.should == nil
|
106
|
-
MODEL_DB.sqls.should == ['SELECT
|
112
|
+
MODEL_DB.sqls.should == ['SELECT nodes.* FROM nodes WHERE (id = 555) LIMIT 1']
|
107
113
|
end
|
108
114
|
|
109
115
|
it "should define a setter method" do
|
@@ -142,7 +148,7 @@ describe Sequel::Model, "many_to_one" do
|
|
142
148
|
ds = @c2.dataset
|
143
149
|
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
144
150
|
e = d.parent
|
145
|
-
MODEL_DB.sqls.should == ["SELECT
|
151
|
+
MODEL_DB.sqls.should == ["SELECT nodes.* FROM nodes WHERE (id = 234) LIMIT 1"]
|
146
152
|
d.instance_variable_get("@parent").should == e
|
147
153
|
end
|
148
154
|
|
@@ -176,7 +182,7 @@ describe Sequel::Model, "many_to_one" do
|
|
176
182
|
d.parent_id = 234
|
177
183
|
d.instance_variable_set(:@parent, 42)
|
178
184
|
d.parent(true).should_not == 42
|
179
|
-
MODEL_DB.sqls.should == ["SELECT
|
185
|
+
MODEL_DB.sqls.should == ["SELECT nodes.* FROM nodes WHERE (id = 234) LIMIT 1"]
|
180
186
|
end
|
181
187
|
|
182
188
|
it "should have the setter add to the reciprocal one_to_many cached association list if it exists" do
|
@@ -192,16 +198,16 @@ describe Sequel::Model, "many_to_one" do
|
|
192
198
|
MODEL_DB.sqls.should == []
|
193
199
|
d.parent = e
|
194
200
|
e.children.should_not(include(d))
|
195
|
-
MODEL_DB.sqls.should == ['SELECT
|
201
|
+
MODEL_DB.sqls.should == ['SELECT nodes.* FROM nodes WHERE (parent_id = 2)']
|
196
202
|
|
197
203
|
MODEL_DB.reset
|
198
204
|
d = @c2.new(:id => 1)
|
199
205
|
e = @c2.new(:id => 2)
|
200
206
|
e.children.should_not(include(d))
|
201
|
-
MODEL_DB.sqls.should == ['SELECT
|
207
|
+
MODEL_DB.sqls.should == ['SELECT nodes.* FROM nodes WHERE (parent_id = 2)']
|
202
208
|
d.parent = e
|
203
209
|
e.children.should(include(d))
|
204
|
-
MODEL_DB.sqls.should == ['SELECT
|
210
|
+
MODEL_DB.sqls.should == ['SELECT nodes.* FROM nodes WHERE (parent_id = 2)']
|
205
211
|
end
|
206
212
|
|
207
213
|
it "should have the setter remove the object from the previous associated object's reciprocal one_to_many cached association list if it exists" do
|
@@ -238,7 +244,7 @@ describe Sequel::Model, "many_to_one" do
|
|
238
244
|
ds = @c2.dataset
|
239
245
|
def ds.fetch_rows(sql, &block); MODEL_DB.sqls << sql; yield({:id=>234}) end
|
240
246
|
e = d.parent
|
241
|
-
MODEL_DB.sqls.should == ["SELECT
|
247
|
+
MODEL_DB.sqls.should == ["SELECT nodes.* FROM nodes WHERE (id = 234) LIMIT 1"]
|
242
248
|
d.instance_variable_get("@parent").should == e
|
243
249
|
end
|
244
250
|
end
|
@@ -282,7 +288,7 @@ describe Sequel::Model, "one_to_many" do
|
|
282
288
|
n = @c2.new(:id => 1234)
|
283
289
|
a = n.attributes_dataset
|
284
290
|
a.should be_a_kind_of(Sequel::Dataset)
|
285
|
-
a.sql.should == 'SELECT
|
291
|
+
a.sql.should == 'SELECT attributes.* FROM attributes WHERE (node_id = 1234)'
|
286
292
|
end
|
287
293
|
|
288
294
|
it "should use implicit class if omitted" do
|
@@ -294,7 +300,7 @@ describe Sequel::Model, "one_to_many" do
|
|
294
300
|
n = @c2.new(:id => 1234)
|
295
301
|
v = n.historical_values_dataset
|
296
302
|
v.should be_a_kind_of(Sequel::Dataset)
|
297
|
-
v.sql.should == 'SELECT
|
303
|
+
v.sql.should == 'SELECT historical_values.* FROM historical_values WHERE (node_id = 1234)'
|
298
304
|
v.model_classes.should == {nil => HistoricalValue}
|
299
305
|
end
|
300
306
|
|
@@ -309,7 +315,7 @@ describe Sequel::Model, "one_to_many" do
|
|
309
315
|
n = @c2.new(:id => 1234)
|
310
316
|
v = n.historical_values_dataset
|
311
317
|
v.should be_a_kind_of(Sequel::Dataset)
|
312
|
-
v.sql.should == 'SELECT
|
318
|
+
v.sql.should == 'SELECT values.* FROM values WHERE (node_id = 1234)'
|
313
319
|
v.model_classes.should == {nil => Historical::Value}
|
314
320
|
end
|
315
321
|
|
@@ -319,7 +325,7 @@ describe Sequel::Model, "one_to_many" do
|
|
319
325
|
n = @c2.new(:id => 1234)
|
320
326
|
a = n.attributes_dataset
|
321
327
|
a.should be_a_kind_of(Sequel::Dataset)
|
322
|
-
a.sql.should == 'SELECT
|
328
|
+
a.sql.should == 'SELECT attributes.* FROM attributes WHERE (nodeid = 1234)'
|
323
329
|
end
|
324
330
|
|
325
331
|
it "should define an add_ method" do
|
@@ -344,18 +350,25 @@ describe Sequel::Model, "one_to_many" do
|
|
344
350
|
MODEL_DB.sqls.should == ['UPDATE attributes SET node_id = NULL WHERE (id = 2345)']
|
345
351
|
end
|
346
352
|
|
353
|
+
it "should support a select option" do
|
354
|
+
@c2.one_to_many :attributes, :class => @c1, :select => [:id, :name]
|
355
|
+
|
356
|
+
n = @c2.new(:id => 1234)
|
357
|
+
n.attributes_dataset.sql.should == "SELECT id, name FROM attributes WHERE (node_id = 1234)"
|
358
|
+
end
|
359
|
+
|
347
360
|
it "should support an order option" do
|
348
361
|
@c2.one_to_many :attributes, :class => @c1, :order => :kind
|
349
362
|
|
350
363
|
n = @c2.new(:id => 1234)
|
351
|
-
n.attributes_dataset.sql.should == "SELECT
|
364
|
+
n.attributes_dataset.sql.should == "SELECT attributes.* FROM attributes WHERE (node_id = 1234) ORDER BY kind"
|
352
365
|
end
|
353
366
|
|
354
367
|
it "should support an array for the order option" do
|
355
368
|
@c2.one_to_many :attributes, :class => @c1, :order => [:kind1, :kind2]
|
356
369
|
|
357
370
|
n = @c2.new(:id => 1234)
|
358
|
-
n.attributes_dataset.sql.should == "SELECT
|
371
|
+
n.attributes_dataset.sql.should == "SELECT attributes.* FROM attributes WHERE (node_id = 1234) ORDER BY kind1, kind2"
|
359
372
|
end
|
360
373
|
|
361
374
|
it "should return array with all members of the association" do
|
@@ -368,7 +381,7 @@ describe Sequel::Model, "one_to_many" do
|
|
368
381
|
atts.first.should be_a_kind_of(@c1)
|
369
382
|
atts.first.values.should == {}
|
370
383
|
|
371
|
-
MODEL_DB.sqls.should == ['SELECT
|
384
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE (node_id = 1234)']
|
372
385
|
end
|
373
386
|
|
374
387
|
it "should accept a block" do
|
@@ -383,7 +396,7 @@ describe Sequel::Model, "one_to_many" do
|
|
383
396
|
atts.first.should be_a_kind_of(@c1)
|
384
397
|
atts.first.values.should == {}
|
385
398
|
|
386
|
-
MODEL_DB.sqls.should == ['SELECT
|
399
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE ((node_id = 1234) AND (xxx IS NULL))']
|
387
400
|
end
|
388
401
|
|
389
402
|
it "should support order option with block" do
|
@@ -398,7 +411,7 @@ describe Sequel::Model, "one_to_many" do
|
|
398
411
|
atts.first.should be_a_kind_of(@c1)
|
399
412
|
atts.first.values.should == {}
|
400
413
|
|
401
|
-
MODEL_DB.sqls.should == ['SELECT
|
414
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE ((node_id = 1234) AND (xxx IS NULL)) ORDER BY kind']
|
402
415
|
end
|
403
416
|
|
404
417
|
it "should set cached instance variable when accessed" do
|
@@ -409,7 +422,7 @@ describe Sequel::Model, "one_to_many" do
|
|
409
422
|
n.instance_variables.include?("@attributes").should == false
|
410
423
|
atts = n.attributes
|
411
424
|
atts.should == n.instance_variable_get("@attributes")
|
412
|
-
MODEL_DB.sqls.should == ['SELECT
|
425
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE (node_id = 1234)']
|
413
426
|
end
|
414
427
|
|
415
428
|
it "should use cached instance variable if available" do
|
@@ -429,7 +442,7 @@ describe Sequel::Model, "one_to_many" do
|
|
429
442
|
MODEL_DB.reset
|
430
443
|
n.instance_variable_set(:@attributes, 42)
|
431
444
|
n.attributes(true).should_not == 42
|
432
|
-
MODEL_DB.sqls.should == ['SELECT
|
445
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE (node_id = 1234)']
|
433
446
|
end
|
434
447
|
|
435
448
|
it "should add item to cached instance variable if it exists when calling add_" do
|
@@ -488,7 +501,7 @@ describe Sequel::Model, "one_to_many" do
|
|
488
501
|
atts.first.should be_a_kind_of(@c1)
|
489
502
|
atts.first.values.should == {}
|
490
503
|
|
491
|
-
MODEL_DB.sqls.should == ['SELECT
|
504
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE (node_id = 1234)']
|
492
505
|
end
|
493
506
|
|
494
507
|
it "should populate the reciprocal many_to_one instance variable when loading the one_to_many association" do
|
@@ -497,7 +510,7 @@ describe Sequel::Model, "one_to_many" do
|
|
497
510
|
|
498
511
|
n = @c2.new(:id => 1234)
|
499
512
|
atts = n.attributes
|
500
|
-
MODEL_DB.sqls.should == ['SELECT
|
513
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE (node_id = 1234)']
|
501
514
|
atts.should be_a_kind_of(Array)
|
502
515
|
atts.size.should == 1
|
503
516
|
atts.first.should be_a_kind_of(@c1)
|
@@ -512,7 +525,7 @@ describe Sequel::Model, "one_to_many" do
|
|
512
525
|
|
513
526
|
n = @c2.new(:id => 1234)
|
514
527
|
atts = n.attributes
|
515
|
-
MODEL_DB.sqls.should == ['SELECT
|
528
|
+
MODEL_DB.sqls.should == ['SELECT attributes.* FROM attributes WHERE (node_id = 1234)']
|
516
529
|
atts.should be_a_kind_of(Array)
|
517
530
|
atts.size.should == 1
|
518
531
|
atts.first.should be_a_kind_of(@c1)
|
@@ -521,6 +534,55 @@ describe Sequel::Model, "one_to_many" do
|
|
521
534
|
|
522
535
|
MODEL_DB.sqls.length.should == 1
|
523
536
|
end
|
537
|
+
|
538
|
+
it "should have an remove_all_ method that removes all associations" do
|
539
|
+
@c2.one_to_many :attributes, :class => @c1
|
540
|
+
@c2.new(:id => 1234).remove_all_attributes
|
541
|
+
MODEL_DB.sqls.first.should == 'UPDATE attributes SET node_id = NULL WHERE (node_id = 1234)'
|
542
|
+
end
|
543
|
+
|
544
|
+
it "remove_all should set the cached instance variable to []" do
|
545
|
+
@c2.one_to_many :attributes, :class => @c1
|
546
|
+
node = @c2.new(:id => 1234)
|
547
|
+
node.remove_all_attributes
|
548
|
+
node.instance_variable_get(:@attributes).should == []
|
549
|
+
end
|
550
|
+
|
551
|
+
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
552
|
+
@c2.one_to_many :attributes, :class => @c1
|
553
|
+
attrib = @c1.new(:id=>3)
|
554
|
+
node = @c2.new(:id => 1234)
|
555
|
+
d = @c1.dataset
|
556
|
+
def d.fetch_rows(s); end
|
557
|
+
node.attributes.should == []
|
558
|
+
def attrib.save!; end
|
559
|
+
node.add_attribute(attrib)
|
560
|
+
node.instance_variable_get(:@attributes).should == [attrib]
|
561
|
+
node.remove_all_attributes.should == [attrib]
|
562
|
+
end
|
563
|
+
|
564
|
+
it "remove_all should return nil if the cached instance variable does not exist" do
|
565
|
+
@c2.one_to_many :attributes, :class => @c1
|
566
|
+
@c2.new(:id => 1234).remove_all_attributes.should == nil
|
567
|
+
end
|
568
|
+
|
569
|
+
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
570
|
+
@c2.one_to_many :attributes, :class => @c1
|
571
|
+
@c1.many_to_one :node, :class => @c2
|
572
|
+
d = @c1.dataset
|
573
|
+
def d.fetch_rows(s); end
|
574
|
+
d = @c2.dataset
|
575
|
+
def d.fetch_rows(s); end
|
576
|
+
attrib = @c1.new(:id=>3)
|
577
|
+
node = @c2.new(:id => 1234)
|
578
|
+
node.attributes.should == []
|
579
|
+
attrib.node.should == nil
|
580
|
+
def attrib.save!; end
|
581
|
+
node.add_attribute(attrib)
|
582
|
+
attrib.instance_variable_get(:@node).should == node
|
583
|
+
node.remove_all_attributes
|
584
|
+
attrib.instance_variable_get(:@node).should == :null
|
585
|
+
end
|
524
586
|
end
|
525
587
|
|
526
588
|
describe Sequel::Model, "many_to_many" do
|
@@ -559,9 +621,7 @@ describe Sequel::Model, "many_to_many" do
|
|
559
621
|
n = @c2.new(:id => 1234)
|
560
622
|
a = n.attributes_dataset
|
561
623
|
a.should be_a_kind_of(Sequel::Dataset)
|
562
|
-
|
563
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id)'
|
564
|
-
].should(include(a.sql))
|
624
|
+
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
565
625
|
end
|
566
626
|
|
567
627
|
it "should use implicit class if omitted" do
|
@@ -573,9 +633,7 @@ describe Sequel::Model, "many_to_many" do
|
|
573
633
|
n = @c2.new(:id => 1234)
|
574
634
|
a = n.tags_dataset
|
575
635
|
a.should be_a_kind_of(Sequel::Dataset)
|
576
|
-
|
577
|
-
'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.node_id = 1234) AND (nodes_tags.tag_id = tags.id)'
|
578
|
-
].should(include(a.sql))
|
636
|
+
a.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
579
637
|
end
|
580
638
|
|
581
639
|
it "should use class inside module if given as a string" do
|
@@ -589,9 +647,7 @@ describe Sequel::Model, "many_to_many" do
|
|
589
647
|
n = @c2.new(:id => 1234)
|
590
648
|
a = n.tags_dataset
|
591
649
|
a.should be_a_kind_of(Sequel::Dataset)
|
592
|
-
|
593
|
-
'SELECT tags.* FROM tags INNER JOIN nodes_tags ON (nodes_tags.node_id = 1234) AND (nodes_tags.tag_id = tags.id)'
|
594
|
-
].should(include(a.sql))
|
650
|
+
a.sql.should == 'SELECT tags.* FROM tags INNER JOIN nodes_tags ON ((nodes_tags.tag_id = tags.id) AND (nodes_tags.node_id = 1234))'
|
595
651
|
end
|
596
652
|
|
597
653
|
it "should use explicit key values and join table if given" do
|
@@ -600,9 +656,7 @@ describe Sequel::Model, "many_to_many" do
|
|
600
656
|
n = @c2.new(:id => 1234)
|
601
657
|
a = n.attributes_dataset
|
602
658
|
a.should be_a_kind_of(Sequel::Dataset)
|
603
|
-
|
604
|
-
'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON (attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234)'
|
605
|
-
].should(include(a.sql))
|
659
|
+
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attribute2node ON ((attribute2node.attributeid = attributes.id) AND (attribute2node.nodeid = 1234))'
|
606
660
|
end
|
607
661
|
|
608
662
|
it "should support an order option" do
|
@@ -611,9 +665,7 @@ describe Sequel::Model, "many_to_many" do
|
|
611
665
|
n = @c2.new(:id => 1234)
|
612
666
|
a = n.attributes_dataset
|
613
667
|
a.should be_a_kind_of(Sequel::Dataset)
|
614
|
-
|
615
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id) ORDER BY blah'
|
616
|
-
].should(include(a.sql))
|
668
|
+
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah'
|
617
669
|
end
|
618
670
|
|
619
671
|
it "should support an array for the order option" do
|
@@ -622,9 +674,7 @@ describe Sequel::Model, "many_to_many" do
|
|
622
674
|
n = @c2.new(:id => 1234)
|
623
675
|
a = n.attributes_dataset
|
624
676
|
a.should be_a_kind_of(Sequel::Dataset)
|
625
|
-
|
626
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id) ORDER BY blah1, blah2'
|
627
|
-
].should(include(a.sql))
|
677
|
+
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) ORDER BY blah1, blah2'
|
628
678
|
end
|
629
679
|
|
630
680
|
it "should support a select option" do
|
@@ -633,9 +683,7 @@ describe Sequel::Model, "many_to_many" do
|
|
633
683
|
n = @c2.new(:id => 1234)
|
634
684
|
a = n.attributes_dataset
|
635
685
|
a.should be_a_kind_of(Sequel::Dataset)
|
636
|
-
|
637
|
-
'SELECT blah FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id)'
|
638
|
-
].should(include(a.sql))
|
686
|
+
a.sql.should == 'SELECT blah FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
639
687
|
end
|
640
688
|
|
641
689
|
it "should support an array for the select option" do
|
@@ -644,9 +692,7 @@ describe Sequel::Model, "many_to_many" do
|
|
644
692
|
n = @c2.new(:id => 1234)
|
645
693
|
a = n.attributes_dataset
|
646
694
|
a.should be_a_kind_of(Sequel::Dataset)
|
647
|
-
|
648
|
-
'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id)'
|
649
|
-
].should(include(a.sql))
|
695
|
+
a.sql.should == 'SELECT attributes.*, attribute_nodes.blah2 FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
650
696
|
end
|
651
697
|
|
652
698
|
it "should accept a block" do
|
@@ -660,9 +706,7 @@ describe Sequel::Model, "many_to_many" do
|
|
660
706
|
a.should be_a_kind_of(Array)
|
661
707
|
a.size.should == 1
|
662
708
|
a.first.should be_a_kind_of(@c1)
|
663
|
-
|
664
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id) WHERE (xxx = 555)'
|
665
|
-
].should(include(MODEL_DB.sqls.first))
|
709
|
+
MODEL_DB.sqls.first.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555)'
|
666
710
|
end
|
667
711
|
|
668
712
|
it "should allow the order option while accepting a block" do
|
@@ -676,9 +720,7 @@ describe Sequel::Model, "many_to_many" do
|
|
676
720
|
a.should be_a_kind_of(Array)
|
677
721
|
a.size.should == 1
|
678
722
|
a.first.should be_a_kind_of(@c1)
|
679
|
-
|
680
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id) WHERE (xxx = 555) ORDER BY blah1, blah2'
|
681
|
-
].should(include(MODEL_DB.sqls.first))
|
723
|
+
MODEL_DB.sqls.first.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234)) WHERE (xxx = 555) ORDER BY blah1, blah2'
|
682
724
|
end
|
683
725
|
|
684
726
|
it "should define an add_ method" do
|
@@ -698,9 +740,7 @@ describe Sequel::Model, "many_to_many" do
|
|
698
740
|
n = @c2.new(:id => 1234)
|
699
741
|
a = @c1.new(:id => 2345)
|
700
742
|
a.should == n.remove_attribute(a)
|
701
|
-
|
702
|
-
'DELETE FROM attributes_nodes WHERE (attribute_id = 2345) AND (node_id = 1234)'
|
703
|
-
].should(include(MODEL_DB.sqls.first))
|
743
|
+
MODEL_DB.sqls.first.should == 'DELETE FROM attributes_nodes WHERE ((node_id = 1234) AND (attribute_id = 2345))'
|
704
744
|
end
|
705
745
|
|
706
746
|
it "should provide an array with all members of the association" do
|
@@ -712,9 +752,7 @@ describe Sequel::Model, "many_to_many" do
|
|
712
752
|
atts.size.should == 1
|
713
753
|
atts.first.should be_a_kind_of(@c1)
|
714
754
|
|
715
|
-
|
716
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id)'
|
717
|
-
].should(include(MODEL_DB.sqls.first))
|
755
|
+
MODEL_DB.sqls.first.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
718
756
|
end
|
719
757
|
|
720
758
|
it "should set cached instance variable when accessed" do
|
@@ -800,11 +838,55 @@ describe Sequel::Model, "many_to_many" do
|
|
800
838
|
n = @c2.new(:id => 1234)
|
801
839
|
a = n.attributes_dataset
|
802
840
|
a.should be_a_kind_of(Sequel::Dataset)
|
803
|
-
|
804
|
-
'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON (attributes_nodes.node_id = 1234) AND (attributes_nodes.attribute_id = attributes.id)'
|
805
|
-
].should(include(a.sql))
|
841
|
+
a.sql.should == 'SELECT attributes.* FROM attributes INNER JOIN attributes_nodes ON ((attributes_nodes.attribute_id = attributes.id) AND (attributes_nodes.node_id = 1234))'
|
806
842
|
end
|
807
843
|
|
844
|
+
it "should have an remove_all_ method that removes all associations" do
|
845
|
+
@c2.many_to_many :attributes, :class => @c1
|
846
|
+
@c2.new(:id => 1234).remove_all_attributes
|
847
|
+
MODEL_DB.sqls.first.should == 'DELETE FROM attributes_nodes WHERE (node_id = 1234)'
|
848
|
+
end
|
849
|
+
|
850
|
+
it "remove_all should set the cached instance variable to []" do
|
851
|
+
@c2.many_to_many :attributes, :class => @c1
|
852
|
+
node = @c2.new(:id => 1234)
|
853
|
+
node.remove_all_attributes
|
854
|
+
node.instance_variable_get(:@attributes).should == []
|
855
|
+
end
|
856
|
+
|
857
|
+
it "remove_all should return the array of previously associated items if the cached instance variable exists" do
|
858
|
+
@c2.many_to_many :attributes, :class => @c1
|
859
|
+
attrib = @c1.new(:id=>3)
|
860
|
+
node = @c2.new(:id => 1234)
|
861
|
+
d = @c1.dataset
|
862
|
+
def d.fetch_rows(s); end
|
863
|
+
node.attributes.should == []
|
864
|
+
node.add_attribute(attrib)
|
865
|
+
node.instance_variable_get(:@attributes).should == [attrib]
|
866
|
+
node.remove_all_attributes.should == [attrib]
|
867
|
+
end
|
868
|
+
|
869
|
+
it "remove_all should return nil if the cached instance variable does not exist" do
|
870
|
+
@c2.many_to_many :attributes, :class => @c1
|
871
|
+
@c2.new(:id => 1234).remove_all_attributes.should == nil
|
872
|
+
end
|
873
|
+
|
874
|
+
it "remove_all should remove the current item from all reciprocal instance varaibles if it cached instance variable exists" do
|
875
|
+
@c2.many_to_many :attributes, :class => @c1
|
876
|
+
@c1.many_to_many :nodes, :class => @c2
|
877
|
+
d = @c1.dataset
|
878
|
+
def d.fetch_rows(s); end
|
879
|
+
d = @c2.dataset
|
880
|
+
def d.fetch_rows(s); end
|
881
|
+
attrib = @c1.new(:id=>3)
|
882
|
+
node = @c2.new(:id => 1234)
|
883
|
+
node.attributes.should == []
|
884
|
+
attrib.nodes.should == []
|
885
|
+
node.add_attribute(attrib)
|
886
|
+
attrib.instance_variable_get(:@nodes).should == [node]
|
887
|
+
node.remove_all_attributes
|
888
|
+
attrib.instance_variable_get(:@nodes).should == []
|
889
|
+
end
|
808
890
|
end
|
809
891
|
|
810
892
|
describe Sequel::Model, "all_association_reflections" do
|
@@ -821,14 +903,17 @@ describe Sequel::Model, "all_association_reflections" do
|
|
821
903
|
@c1.associate :many_to_one, :parent, :class => @c1
|
822
904
|
@c1.all_association_reflections.should == [{
|
823
905
|
:type => :many_to_one, :name => :parent, :class_name => 'Node',
|
824
|
-
:class => @c1, :key => :parent_id, :block => nil, :cache => true
|
906
|
+
:class => @c1, :key => :parent_id, :block => nil, :cache => true,
|
907
|
+
:graph_join_type=>:left_outer, :graph_conditions=>[], :eager_block => nil, :model => @c1
|
825
908
|
}]
|
826
909
|
@c1.associate :one_to_many, :children, :class => @c1
|
827
910
|
@c1.all_association_reflections.sort_by{|x|x[:name].to_s}.should == [{
|
828
911
|
:type => :one_to_many, :name => :children, :class_name => 'Node',
|
829
|
-
:class => @c1, :key => :node_id, :block => nil, :cache => true
|
912
|
+
:class => @c1, :key => :node_id, :block => nil, :cache => true,
|
913
|
+
:graph_join_type=>:left_outer, :graph_conditions=>[], :eager_block => nil, :model => @c1}, {
|
830
914
|
:type => :many_to_one, :name => :parent, :class_name => 'Node',
|
831
|
-
:class => @c1, :key => :parent_id, :block => nil, :cache => true
|
915
|
+
:class => @c1, :key => :parent_id, :block => nil, :cache => true,
|
916
|
+
:graph_join_type=>:left_outer, :graph_conditions=>[], :eager_block => nil, :model => @c1}]
|
832
917
|
end
|
833
918
|
end
|
834
919
|
|
@@ -849,12 +934,14 @@ describe Sequel::Model, "association_reflection" do
|
|
849
934
|
@c1.associate :many_to_one, :parent, :class => @c1
|
850
935
|
@c1.association_reflection(:parent).should == {
|
851
936
|
:type => :many_to_one, :name => :parent, :class_name => 'Node',
|
852
|
-
:class => @c1, :key => :parent_id, :block => nil, :cache => true
|
937
|
+
:class => @c1, :key => :parent_id, :block => nil, :cache => true,
|
938
|
+
:graph_join_type=>:left_outer, :graph_conditions=>[], :eager_block => nil, :model => @c1
|
853
939
|
}
|
854
940
|
@c1.associate :one_to_many, :children, :class => @c1
|
855
941
|
@c1.association_reflection(:children).should == {
|
856
942
|
:type => :one_to_many, :name => :children, :class_name => 'Node',
|
857
|
-
:class => @c1, :key => :node_id, :block => nil, :cache => true
|
943
|
+
:class => @c1, :key => :node_id, :block => nil, :cache => true,
|
944
|
+
:graph_join_type=>:left_outer, :graph_conditions=>[], :eager_block => nil, :model => @c1
|
858
945
|
}
|
859
946
|
end
|
860
947
|
end
|