dm-mongo-adapter 0.2.0.pre3 → 0.6.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/Gemfile +27 -0
- data/README.rdoc +16 -35
- data/Rakefile +6 -16
- data/VERSION.yml +2 -2
- data/dm-mongo-adapter.gemspec +100 -121
- data/lib/mongo_adapter.rb +19 -62
- data/lib/mongo_adapter/adapter.rb +49 -36
- data/lib/mongo_adapter/conditions.rb +0 -5
- data/lib/mongo_adapter/migrations.rb +17 -23
- data/lib/mongo_adapter/model.rb +3 -74
- data/lib/mongo_adapter/modifier.rb +1 -1
- data/lib/mongo_adapter/property/array.rb +10 -0
- data/lib/mongo_adapter/property/db_ref.rb +17 -0
- data/lib/mongo_adapter/property/hash.rb +27 -0
- data/lib/mongo_adapter/property/object_id.rb +47 -0
- data/lib/mongo_adapter/query.rb +42 -45
- data/lib/mongo_adapter/rails/storage.rb +15 -0
- data/lib/mongo_adapter/resource.rb +0 -130
- data/lib/mongo_adapter/support/class.rb +11 -0
- data/lib/mongo_adapter/support/date.rb +11 -0
- data/lib/mongo_adapter/support/date_time.rb +12 -0
- data/lib/mongo_adapter/support/object.rb +9 -0
- data/spec/legacy/adapter_spec.rb +9 -6
- data/spec/legacy/associations_spec.rb +37 -29
- data/spec/legacy/property_spec.rb +4 -3
- data/spec/legacy/sti_spec.rb +1 -2
- data/spec/lib/cleanup_models.rb +0 -1
- data/spec/public/aggregates_spec.rb +171 -0
- data/spec/public/model_spec.rb +8 -22
- data/spec/public/modifier_spec.rb +109 -0
- data/spec/public/properties/db_ref_spec.rb +17 -0
- data/spec/public/properties/object_id_spec.rb +15 -0
- data/spec/public/resource_spec.rb +2 -383
- data/spec/public/shared/object_id_shared_spec.rb +16 -39
- data/spec/spec_helper.rb +0 -4
- metadata +87 -117
- data/.gitignore +0 -9
- data/lib/mongo_adapter/embedded_model.rb +0 -187
- data/lib/mongo_adapter/embedded_resource.rb +0 -134
- data/lib/mongo_adapter/embedments/one_to_many.rb +0 -144
- data/lib/mongo_adapter/embedments/one_to_one.rb +0 -57
- data/lib/mongo_adapter/embedments/relationship.rb +0 -258
- data/lib/mongo_adapter/model/embedment.rb +0 -215
- data/lib/mongo_adapter/types/date.rb +0 -24
- data/lib/mongo_adapter/types/date_time.rb +0 -28
- data/lib/mongo_adapter/types/db_ref.rb +0 -65
- data/lib/mongo_adapter/types/discriminator.rb +0 -32
- data/lib/mongo_adapter/types/object_id.rb +0 -72
- data/lib/mongo_adapter/types/objects.rb +0 -31
- data/spec/legacy/embedded_resource_spec.rb +0 -157
- data/spec/legacy/embedments_spec.rb +0 -177
- data/spec/legacy/modifier_spec.rb +0 -81
- data/spec/public/embedded_collection_spec.rb +0 -61
- data/spec/public/embedded_resource_spec.rb +0 -220
- data/spec/public/model/embedment_spec.rb +0 -186
- data/spec/public/shared/model_embedments_spec.rb +0 -338
- data/spec/public/types/df_ref_spec.rb +0 -6
- data/spec/public/types/discriminator_spec.rb +0 -118
- data/spec/public/types/embedded_array_spec.rb +0 -55
- data/spec/public/types/embedded_hash_spec.rb +0 -83
- data/spec/public/types/object_id_spec.rb +0 -6
- data/spec/semipublic/embedded_model_spec.rb +0 -43
- data/spec/semipublic/model/embedment_spec.rb +0 -42
- data/spec/semipublic/resource_spec.rb +0 -70
@@ -5,141 +5,11 @@ module DataMapper
|
|
5
5
|
module Resource
|
6
6
|
def self.included(model)
|
7
7
|
model.send(:include, DataMapper::Resource)
|
8
|
-
model.send(:include, ResourceMethods)
|
9
8
|
model.send(:include, Modifier)
|
10
9
|
|
11
10
|
# Needs to be after the inclusion of DM::Resource so as to overwrite
|
12
11
|
# methods added by DM::Model.
|
13
12
|
model.extend(Model)
|
14
|
-
end
|
15
|
-
|
16
|
-
module ResourceMethods
|
17
|
-
# monkey patching based on this: http://github.com/datamapper/dm-core/commit/3332db6c25ab9cea9ba58ce62a9ad3038303baa1
|
18
|
-
# TODO: remove once dm-core 0.10.3 is released
|
19
|
-
def eager_load(properties)
|
20
|
-
unless properties.empty? || key.nil? || collection.nil?
|
21
|
-
collection.reload(:fields => properties)
|
22
|
-
end
|
23
|
-
|
24
|
-
self
|
25
|
-
end
|
26
|
-
|
27
|
-
# Assign values to multiple attributes in one call (mass assignment)
|
28
|
-
#
|
29
|
-
# Overrides attributes= in dm-core so as to permit assignments to
|
30
|
-
# embedments.
|
31
|
-
#
|
32
|
-
# @param [Hash] attributes
|
33
|
-
# names and values of attributes to assign
|
34
|
-
#
|
35
|
-
# @return [Hash]
|
36
|
-
# names and values of attributes assigned
|
37
|
-
#
|
38
|
-
# @api public
|
39
|
-
def attributes=(attributes)
|
40
|
-
attributes.each do |name, value|
|
41
|
-
name.set(self, value) if name.kind_of?(Embedments::Relationship)
|
42
|
-
end
|
43
|
-
|
44
|
-
super(attributes)
|
45
|
-
end
|
46
|
-
|
47
|
-
# Checks if the resource, or embedded documents, have unsaved changes
|
48
|
-
#
|
49
|
-
# @return [Boolean]
|
50
|
-
# True if resource may be persisted
|
51
|
-
#
|
52
|
-
# @overrides DataMapper::Resource#dirty?
|
53
|
-
#
|
54
|
-
# @api public
|
55
|
-
def dirty?
|
56
|
-
super || run_once(true) { dirty_embedments? }
|
57
|
-
end
|
58
|
-
|
59
|
-
# Checks if any embedded documents have unsaved changes
|
60
|
-
#
|
61
|
-
# @return [Boolean]
|
62
|
-
# True if any embedded documents can be persisted
|
63
|
-
#
|
64
|
-
# @api private
|
65
|
-
def dirty_embedments?
|
66
|
-
embedments.values.any? do |embedment|
|
67
|
-
embedment.loaded?(self) && case embedment
|
68
|
-
when Embedments::OneToOne::Relationship then embedment.get!(self).dirty?
|
69
|
-
when Embedments::OneToMany::Relationship then embedment.get!(self).any? { |r| r.dirty? }
|
70
|
-
else false
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end
|
74
|
-
|
75
|
-
# Hash of attributes that have unsaved changes
|
76
|
-
#
|
77
|
-
# @return [Hash]
|
78
|
-
# attributes that have unsaved changes
|
79
|
-
#
|
80
|
-
# @overrides DataMapper::Resource#dirty_attributes
|
81
|
-
#
|
82
|
-
# @api semipublic
|
83
|
-
def dirty_attributes
|
84
|
-
embedded_attributes = {}
|
85
|
-
|
86
|
-
each_embedment do |name, target|
|
87
|
-
case (embedment = embedments[name])
|
88
|
-
when Embedments::OneToMany::Relationship
|
89
|
-
target.each do |resource|
|
90
|
-
if resource.dirty?
|
91
|
-
embedded_attributes[embedment] ||= []
|
92
|
-
embedded_attributes[embedment] << resource.dirty_attributes
|
93
|
-
end
|
94
|
-
end
|
95
|
-
when Embedments::OneToOne::Relationship
|
96
|
-
# Relationship target is a single resource.
|
97
|
-
if target.dirty?
|
98
|
-
embedded_attributes[embedment] = target.dirty_attributes
|
99
|
-
end
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
|
-
super.merge(embedded_attributes)
|
104
|
-
end
|
105
|
-
|
106
|
-
# Saves the resource and it's embedments
|
107
|
-
#
|
108
|
-
# @return [Boolean]
|
109
|
-
# True if the resource was successfully saved
|
110
|
-
#
|
111
|
-
# @overrides DataMapper::Resource#save_self
|
112
|
-
#
|
113
|
-
# @api semipublic
|
114
|
-
def save_self(safe = true)
|
115
|
-
super && embedments.values.each do |e|
|
116
|
-
e.loaded?(self) && Array(e.get!(self)).each { |r| r.original_attributes.clear }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
private
|
121
|
-
|
122
|
-
# The embedments (relationships to embedded objects) on this model
|
123
|
-
#
|
124
|
-
# @return [Hash<Symbol,Embedments::Relationship>]
|
125
|
-
#
|
126
|
-
# @api private
|
127
|
-
def embedments
|
128
|
-
model.embedments
|
129
|
-
end
|
130
|
-
|
131
|
-
# Iterates through each loaded embedment, yielding the name and value
|
132
|
-
#
|
133
|
-
# @yieldparam [Symbol]
|
134
|
-
# The name of the embedment
|
135
|
-
# @yieldparam [Mongo::Collection]
|
136
|
-
# The embedded resource, or collection of embedded resources
|
137
|
-
#
|
138
|
-
# @api private
|
139
|
-
def each_embedment
|
140
|
-
embedments.each { |name, embedment|
|
141
|
-
embedment.loaded?(self) && yield(name, embedment.get!(self)) }
|
142
|
-
end
|
143
13
|
end # ResourceMethods
|
144
14
|
|
145
15
|
end # Resource
|
data/spec/legacy/adapter_spec.rb
CHANGED
@@ -9,7 +9,7 @@ describe DataMapper::Adapters::MongoAdapter do
|
|
9
9
|
class ::Heffalump
|
10
10
|
include DataMapper::Mongo::Resource
|
11
11
|
|
12
|
-
property :id,
|
12
|
+
property :id, ObjectId
|
13
13
|
property :color, String
|
14
14
|
property :num_spots, Integer
|
15
15
|
property :striped, Boolean
|
@@ -113,9 +113,9 @@ describe DataMapper::Adapters::MongoAdapter do
|
|
113
113
|
class ::Zoo
|
114
114
|
include DataMapper::Mongo::Resource
|
115
115
|
|
116
|
-
property :id,
|
117
|
-
property :animals,
|
118
|
-
property :address,
|
116
|
+
property :id, ObjectId
|
117
|
+
property :animals, Array
|
118
|
+
property :address, Hash
|
119
119
|
end
|
120
120
|
end
|
121
121
|
|
@@ -134,8 +134,11 @@ describe DataMapper::Adapters::MongoAdapter do
|
|
134
134
|
Zoo.create(:animals => penguins)
|
135
135
|
|
136
136
|
zoo = Zoo.first(:animals => penguins)
|
137
|
-
|
138
|
-
|
137
|
+
|
138
|
+
pending "this is currently not supported by dm-core" do
|
139
|
+
zoo.should_not be_nil
|
140
|
+
zoo.animals.should eql(penguins)
|
141
|
+
end
|
139
142
|
end
|
140
143
|
end
|
141
144
|
|
@@ -7,7 +7,7 @@ describe "associations" do
|
|
7
7
|
class ::User
|
8
8
|
include DataMapper::Mongo::Resource
|
9
9
|
|
10
|
-
property :id,
|
10
|
+
property :id, ObjectId
|
11
11
|
property :group_id, DBRef
|
12
12
|
property :name, String
|
13
13
|
property :age, Integer
|
@@ -16,14 +16,14 @@ describe "associations" do
|
|
16
16
|
class ::Group
|
17
17
|
include DataMapper::Mongo::Resource
|
18
18
|
|
19
|
-
property :id,
|
19
|
+
property :id, ObjectId
|
20
20
|
property :name, String
|
21
21
|
end
|
22
22
|
|
23
23
|
class ::Friend
|
24
24
|
include DataMapper::Mongo::Resource
|
25
25
|
|
26
|
-
property :id,
|
26
|
+
property :id, ObjectId
|
27
27
|
property :name, String
|
28
28
|
end
|
29
29
|
|
@@ -72,38 +72,46 @@ describe "associations" do
|
|
72
72
|
end
|
73
73
|
|
74
74
|
describe "has many" do
|
75
|
-
before :each do
|
76
|
-
@john = User.create(:name => 'john', :age => 101)
|
77
|
-
@jane = User.create(:name => 'jane', :age => 102)
|
78
|
-
|
79
|
-
@group = Group.create(:name => 'dm hackers')
|
80
|
-
|
81
|
-
[@john, @jane].each { |user| user.update(:group_id => @group.id) }
|
82
|
-
end
|
75
|
+
# before :each do
|
76
|
+
# @john = User.create(:name => 'john', :age => 101)
|
77
|
+
# @jane = User.create(:name => 'jane', :age => 102)
|
78
|
+
#
|
79
|
+
# @group = Group.create(:name => 'dm hackers')
|
80
|
+
#
|
81
|
+
# [@john, @jane].each { |user| user.update(:group_id => @group.id) }
|
82
|
+
# end
|
83
83
|
|
84
84
|
# @done
|
85
85
|
it "should get children" do
|
86
|
-
|
86
|
+
pending "bug in edge dm-core causes an infinite loop here" do
|
87
|
+
@group.users.size.should eql(2)
|
88
|
+
end
|
87
89
|
end
|
88
90
|
|
89
91
|
it "should add new children with <<" do
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
92
|
+
pending "bug in edge dm-core causes an infinite loop here" do
|
93
|
+
user = User.new(:name => 'kyle')
|
94
|
+
@group.users << user
|
95
|
+
user.group_id.should eql(@group.id)
|
96
|
+
@group.users.size.should eql(3)
|
97
|
+
end
|
94
98
|
end
|
95
99
|
|
96
100
|
# @done
|
97
101
|
it "should replace children" do
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
+
pending "bug in edge dm-core causes an infinite loop here" do
|
103
|
+
user = User.create(:name => 'stan')
|
104
|
+
@group.users = [user]
|
105
|
+
@group.users.size.should eql(1)
|
106
|
+
@group.users.first.should eql(user)
|
107
|
+
end
|
102
108
|
end
|
103
109
|
|
104
110
|
it "should fetch children matching conditions" do
|
105
|
-
|
106
|
-
|
111
|
+
pending "bug in edge dm-core causes an infinite loop here" do
|
112
|
+
users = @group.users.all(:name => 'john')
|
113
|
+
users.size.should eql(1)
|
114
|
+
end
|
107
115
|
end
|
108
116
|
end
|
109
117
|
|
@@ -114,13 +122,13 @@ describe "associations" do
|
|
114
122
|
@user1 = User.new
|
115
123
|
@user2 = User.new
|
116
124
|
@group = Group.new(:users =>
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
125
|
+
[
|
126
|
+
{:friends =>
|
127
|
+
[{:name => "blah"}, {:name => "blah2"}]
|
128
|
+
},
|
129
|
+
{:friends =>
|
130
|
+
[{:name => "blah3"},{:name => "blah4"}]
|
131
|
+
}])
|
124
132
|
end
|
125
133
|
|
126
134
|
# @done
|
@@ -7,7 +7,7 @@ describe "Property" do
|
|
7
7
|
class ::User
|
8
8
|
include DataMapper::Mongo::Resource
|
9
9
|
|
10
|
-
property :id,
|
10
|
+
property :id, ObjectId
|
11
11
|
property :date_time_field, DateTime
|
12
12
|
property :date_field, Date
|
13
13
|
property :type, Discriminator
|
@@ -32,7 +32,8 @@ describe "Property" do
|
|
32
32
|
user = User.get(_id)
|
33
33
|
|
34
34
|
user.date_time_field.class.should be(DateTime)
|
35
|
-
|
35
|
+
|
36
|
+
Time.parse(user.date_time_field.to_s).to_i.should == Time.parse(dt_now.to_s).to_i
|
36
37
|
end
|
37
38
|
end
|
38
39
|
|
@@ -43,7 +44,7 @@ describe "Property" do
|
|
43
44
|
_id = $db.collection('users').insert(:type => 'User', :date_field => Time.parse(today.to_s))
|
44
45
|
|
45
46
|
user = User.get(_id)
|
46
|
-
|
47
|
+
|
47
48
|
user.date_field.class.should be(Date)
|
48
49
|
Time.parse(user.date_field.to_s).should == Time.parse(today.to_s)
|
49
50
|
end
|
data/spec/legacy/sti_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe "Single Table Inheritance" do
|
|
6
6
|
class ::Person
|
7
7
|
include DataMapper::Mongo::Resource
|
8
8
|
|
9
|
-
property :id,
|
9
|
+
property :id, ObjectId
|
10
10
|
property :name, String
|
11
11
|
property :job, String
|
12
12
|
property :type, Discriminator
|
@@ -24,7 +24,6 @@ describe "Single Table Inheritance" do
|
|
24
24
|
it "should have a type property that reflects the class" do
|
25
25
|
[Person, Male, Father, Son].each_with_index do |model, i|
|
26
26
|
object = model.create!(:name => "#{model} #{i}")
|
27
|
-
object.reload
|
28
27
|
object.type.should == model
|
29
28
|
end
|
30
29
|
end
|
data/spec/lib/cleanup_models.rb
CHANGED
@@ -0,0 +1,171 @@
|
|
1
|
+
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'spec_helper'))
|
2
|
+
|
3
|
+
describe DataMapper::Mongo::Model do
|
4
|
+
before(:all) do
|
5
|
+
class ::Student
|
6
|
+
include DataMapper::Mongo::Resource
|
7
|
+
|
8
|
+
property :id, ObjectId
|
9
|
+
property :name, String
|
10
|
+
property :school, String
|
11
|
+
property :score, Float
|
12
|
+
end
|
13
|
+
|
14
|
+
Student.all.destroy!
|
15
|
+
|
16
|
+
@student_one = Student.create(:school => 'School 1', :name => 'One', :score => 3.0)
|
17
|
+
@student_two = Student.create(:school => 'School 2', :name => 'Two', :score => 3.5)
|
18
|
+
@student_three = Student.create(:school => 'School 2', :name => 'Three', :score => 4.5)
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#count" do
|
22
|
+
describe 'with no query' do
|
23
|
+
it 'should return number of all resources' do
|
24
|
+
Student.count.should == 3
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'with a query' do
|
29
|
+
it 'should return number of resources matching conditions' do
|
30
|
+
Student.count(:name => /one|two/i).should == 2
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "#aggregate" do
|
36
|
+
describe "without operators" do
|
37
|
+
describe "without conditions" do
|
38
|
+
it "should return array of hashes based on all records" do
|
39
|
+
result = Student.aggregate(:school, :score).to_a
|
40
|
+
|
41
|
+
result.should == [
|
42
|
+
{ :school => "School 1", :score => 3.0 },
|
43
|
+
{ :school => "School 2", :score => 3.5 },
|
44
|
+
{ :school => "School 2", :score => 4.5 }]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "with conditions" do
|
49
|
+
it "should return array of hashes based on records that match conditions" do
|
50
|
+
result = Student.aggregate(:school, :score, :score.gt => 3.0)
|
51
|
+
|
52
|
+
result.should == [
|
53
|
+
{ :school => "School 2", :score => 3.5 },
|
54
|
+
{ :school => "School 2", :score => 4.5 }]
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
describe "count operator" do
|
60
|
+
describe "without conditions" do
|
61
|
+
it "should get correct results based on all records" do
|
62
|
+
result = Student.aggregate(:school, :score.count)
|
63
|
+
|
64
|
+
result.size.should == 2
|
65
|
+
|
66
|
+
school_1, school_2 = result
|
67
|
+
|
68
|
+
school_1[:school].should == 'School 1'
|
69
|
+
school_2[:school].should == 'School 2'
|
70
|
+
|
71
|
+
school_1[:score].should == 1
|
72
|
+
school_2[:score].should == 2
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "with conditions" do
|
77
|
+
it "should get correct results based on records that match conditions" do
|
78
|
+
result = Student.aggregate(:school, :score.count, :name => /two|three/i)
|
79
|
+
|
80
|
+
result.size.should == 1
|
81
|
+
result.first[:score].should == 2
|
82
|
+
result.first[:school].should == 'School 2'
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# avg
|
89
|
+
#
|
90
|
+
# TODO: add spec for #avg with conditions
|
91
|
+
|
92
|
+
describe "avg operator" do
|
93
|
+
describe 'without conditions' do
|
94
|
+
it 'should return an avarage value of the given field' do
|
95
|
+
result = Student.aggregate(:school, :score.avg)
|
96
|
+
|
97
|
+
school_1, school_2 = result
|
98
|
+
|
99
|
+
school_1[:school].should == 'School 1'
|
100
|
+
school_2[:school].should == 'School 2'
|
101
|
+
|
102
|
+
school_1[:score].should == 3.0
|
103
|
+
school_2[:score].should == 4.0
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# min
|
110
|
+
#
|
111
|
+
# TODO: add spec for #min with conditions
|
112
|
+
|
113
|
+
describe "min operator" do
|
114
|
+
describe 'without conditions' do
|
115
|
+
it 'should return the minimum value of the given field' do
|
116
|
+
result = Student.aggregate(:school, :score.min)
|
117
|
+
|
118
|
+
school_1, school_2 = result
|
119
|
+
|
120
|
+
school_1[:school].should == 'School 1'
|
121
|
+
school_2[:school].should == 'School 2'
|
122
|
+
|
123
|
+
school_1[:score].should == 3.0
|
124
|
+
school_2[:score].should == 3.5
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# max
|
131
|
+
#
|
132
|
+
# TODO: add spec for #max with conditions
|
133
|
+
|
134
|
+
describe "max operator" do
|
135
|
+
describe 'without conditions' do
|
136
|
+
it 'should return the maximum value of the given field' do
|
137
|
+
result = Student.aggregate(:school, :score.max)
|
138
|
+
|
139
|
+
school_1, school_2 = result
|
140
|
+
|
141
|
+
school_1[:school].should == 'School 1'
|
142
|
+
school_2[:school].should == 'School 2'
|
143
|
+
|
144
|
+
school_1[:score].should == 3.0
|
145
|
+
school_2[:score].should == 4.5
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
#
|
151
|
+
# max
|
152
|
+
#
|
153
|
+
# TODO: add spec for #sum with conditions
|
154
|
+
|
155
|
+
describe "sum operator" do
|
156
|
+
describe 'without conditions' do
|
157
|
+
it 'should return the maximum value of the given field' do
|
158
|
+
result = Student.aggregate(:school, :score.sum)
|
159
|
+
|
160
|
+
school_1, school_2 = result
|
161
|
+
|
162
|
+
school_1[:school].should == 'School 1'
|
163
|
+
school_2[:school].should == 'School 2'
|
164
|
+
|
165
|
+
school_1[:score].should == 3.0
|
166
|
+
school_2[:score].should == 8.0
|
167
|
+
end
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|