mongodb_model 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,80 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Model callbacks' do
4
+ with_mongo
5
+
6
+ after{remove_constants :User, :Writer}
7
+
8
+ it "should update attributes" do
9
+ class User
10
+ inherit Mongo::Model
11
+
12
+ attr_accessor :name, :has_mail, :age, :banned
13
+ end
14
+
15
+ u = User.new
16
+ u.set name: 'Alex', has_mail: '1', age: '31', banned: '0'
17
+ [u.name, u.has_mail, u.age, u.banned].should == ['Alex', '1', '31', '0']
18
+ end
19
+
20
+ it "should update only specified attributes" do
21
+ class User
22
+ inherit Mongo::Model
23
+
24
+ attr_accessor :name, :has_mail, :age, :position, :banned
25
+
26
+ assign do
27
+ name String, true
28
+ has_mail Boolean, true
29
+ age Integer, true
30
+ position true
31
+ banned Boolean
32
+ end
33
+ end
34
+
35
+ u = User.new
36
+ u.set name: 'Alex', has_mail: '1', age: '31', position: [11, 34] ,banned: '0'
37
+ [u.name, u.has_mail, u.age, u.position, u.banned].should == ['Alex', true, 31, [11, 34], nil]
38
+
39
+ # should allow to forcefully cast and update any attribute
40
+ u.set! banned: '0'
41
+ u.banned.should == false
42
+ end
43
+
44
+ it "should inherit assignment rules" do
45
+ class User
46
+ inherit Mongo::Model
47
+
48
+ attr_accessor :age
49
+
50
+ assign do
51
+ age Integer, true
52
+ end
53
+ end
54
+
55
+ class Writer < User
56
+ attr_accessor :posts
57
+
58
+ assign do
59
+ posts Integer, true
60
+ end
61
+ end
62
+
63
+ u = Writer.new
64
+ u.set age: '20', posts: '12'
65
+ [u.age, u.posts].should == [20, 12]
66
+ end
67
+
68
+ it 'casting smoke test' do
69
+ [
70
+ Boolean, '1', true,
71
+ Date, '2011-08-23', Date.parse('2011-08-23'),
72
+ Float, '1.2', 1.2,
73
+ Integer, '10', 10,
74
+ String, 'Hi', 'Hi',
75
+ Time, '2011-08-23', Date.parse('2011-08-23').to_time
76
+ ].each_slice 3 do |type, raw, expected|
77
+ type.cast(raw).should == expected
78
+ end
79
+ end
80
+ end
@@ -0,0 +1,73 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Attribute Convertors" do
4
+ with_mongo_model
5
+
6
+ after(:all){remove_constants :TheSample}
7
+
8
+ convertors = Mongo::Model::AttributeConvertors::CONVERTORS
9
+
10
+ it ":line convertor" do
11
+ v = ['a', 'b']
12
+ str_v = 'a, b'
13
+ convertors[:line][:from_string].call(str_v).should == v
14
+ convertors[:line][:to_string].call(v).should == str_v
15
+ end
16
+
17
+ it ":yaml convertor" do
18
+ v = {'a' => 'b'}
19
+ str_v = v.to_yaml.strip
20
+
21
+ convertors[:yaml][:from_string].call(str_v).should == v
22
+ convertors[:yaml][:to_string].call(v).should == str_v
23
+ end
24
+
25
+ it ":json convertor" do
26
+ v = {'a' => 'b'}
27
+ str_v = v.to_json.strip
28
+ convertors[:json][:from_string].call(str_v).should == v
29
+ convertors[:json][:to_string].call(v).should == str_v
30
+ end
31
+
32
+ it ":field should generate helper methods if :as_string option provided" do
33
+ class ::TheSample
34
+ inherit Mongo::Model
35
+
36
+ attr_accessor :tags, :protected_tags
37
+ available_as_string :tags, :line
38
+ available_as_string :protected_tags, :line
39
+
40
+ def initialize
41
+ @tags, @protected_tags = [], []
42
+ end
43
+
44
+ assign do
45
+ tags_as_string true
46
+ end
47
+ end
48
+
49
+ o = TheSample.new
50
+
51
+ # get
52
+ o.tags_as_string.should == ''
53
+ o.tags = %w(Java Ruby)
54
+ o._clear_cache
55
+ o.tags_as_string.should == 'Java, Ruby'
56
+
57
+ # set
58
+ o.tags_as_string = ''
59
+ o.tags.should == []
60
+ o.tags_as_string = 'Java, Ruby'
61
+ o.tags.should == %w(Java Ruby)
62
+
63
+ # mass assignment
64
+ o.tags = []
65
+ o.set tags_as_string: 'Java, Ruby'
66
+ o.tags.should == %w(Java Ruby)
67
+
68
+ # # protection
69
+ o.protected_tags = []
70
+ o.set protected_tags_as_string: 'Java, Ruby'
71
+ o.protected_tags.should == []
72
+ end
73
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Model callbacks' do
4
+ with_mongo
5
+
6
+ after(:all){remove_constants :TheModel, :Player}
7
+
8
+ it "callback integration" do
9
+ class TheModel
10
+ inherit Mongo::Model
11
+ end
12
+
13
+ model = TheModel.new
14
+
15
+ model.should_receive(:run_before_callbacks).with(:save, {method: :save})
16
+ model._run_callbacks :before, :save
17
+ end
18
+
19
+ it "integration smoke test" do
20
+ class Player
21
+ inherit Mongo::Model
22
+
23
+ before_validate :before_validate_check
24
+ after_save :after_save_check
25
+
26
+ attr_accessor :missions
27
+
28
+ class Mission
29
+ inherit Mongo::Model
30
+
31
+ before_validate :before_validate_check
32
+ after_save :after_save_check
33
+ end
34
+ end
35
+
36
+ mission = Player::Mission.new
37
+ player = Player.new
38
+ player.missions = [mission]
39
+
40
+ player.should_receive(:before_validate_check).once.ordered.and_return(nil)
41
+ mission.should_receive(:before_validate_check).once.ordered.and_return(nil)
42
+ player.should_receive(:after_save_check).once.ordered.and_return(nil)
43
+ mission.should_receive(:after_save_check).once.ordered.and_return(nil)
44
+
45
+ db.units.save(player).should be_true
46
+ end
47
+ end
data/spec/crud_spec.rb ADDED
@@ -0,0 +1,151 @@
1
+ require 'spec_helper'
2
+ require 'mongodb/object/spec/crud_shared'
3
+
4
+ describe "Model CRUD" do
5
+ with_mongo_model
6
+
7
+ describe 'simple' do
8
+ before :all do
9
+ class Unit
10
+ inherit Mongo::Model
11
+ collection :units
12
+
13
+ attr_accessor :name, :info
14
+ def == o; [self.class, name, info] == [o.class, o.respond_to(:name), o.respond_to(:info)] end
15
+ end
16
+ end
17
+ after(:all){remove_constants :Unit}
18
+
19
+ before do
20
+ @zeratul = Unit.build name: 'Zeratul', info: 'Dark Templar'
21
+ end
22
+
23
+ it_should_behave_like "object CRUD"
24
+
25
+ it 'model crud' do
26
+ # read
27
+ Unit.count.should == 0
28
+ Unit.all.should == []
29
+ Unit.first.should == nil
30
+
31
+ # create
32
+ @zeratul.save.should be_true
33
+ @zeratul._id.should_not be_nil
34
+
35
+ # read
36
+ Unit.count.should == 1
37
+ Unit.all.should == [@zeratul]
38
+ Unit.first.should == @zeratul
39
+ Unit.first.object_id.should_not == @zeratul.object_id
40
+
41
+ # update
42
+ @zeratul.info = 'Killer of Cerebrates'
43
+ @zeratul.save.should be_true
44
+ Unit.count.should == 1
45
+ Unit.first(name: 'Zeratul').info.should == 'Killer of Cerebrates'
46
+
47
+ # destroy
48
+ @zeratul.destroy.should be_true
49
+ Unit.count.should == 0
50
+ end
51
+
52
+ it 'should be able to save to another collection' do
53
+ # create
54
+ @zeratul.save(collection: db.heroes).should be_true
55
+ @zeratul._id.should_not be_nil
56
+
57
+ # read
58
+ Unit.count.should == 0
59
+ db.heroes.count.should == 1
60
+ db.heroes.first.should == @zeratul
61
+ db.heroes.first.object_id.should_not == @zeratul.object_id
62
+
63
+ # update
64
+ @zeratul.info = 'Killer of Cerebrates'
65
+ @zeratul.save(collection: db.heroes).should be_true
66
+ Unit.count.should == 0
67
+ db.heroes.count.should == 1
68
+ db.heroes.first(name: 'Zeratul').info.should == 'Killer of Cerebrates'
69
+
70
+ # destroy
71
+ @zeratul.destroy(collection: db.heroes).should be_true
72
+ db.heroes.count.should == 0
73
+ end
74
+
75
+ it 'build' do
76
+ u = Unit.build name: 'Zeratul'
77
+ u.name.should == 'Zeratul'
78
+ end
79
+
80
+ it 'create' do
81
+ u = Unit.create(name: 'Zeratul')
82
+ u.new_record?.should be_false
83
+
84
+ u = Unit.create!(name: 'Zeratul')
85
+ u.new_record?.should be_false
86
+ end
87
+
88
+ it 'destroy_all' do
89
+ Unit.create(name: 'Zeratul')
90
+ Unit.count.should == 1
91
+ Unit.destroy_all
92
+ Unit.count.should == 0
93
+
94
+ Unit.destroy_all!
95
+ end
96
+ end
97
+
98
+ describe 'embedded' do
99
+ before :all do
100
+ class Player
101
+ inherit Mongo::Model
102
+ collection :players
103
+
104
+ attr_accessor :missions
105
+ def == o; [self.class, self.missions] == [o.class, o.respond_to(:missions)] end
106
+
107
+ class Mission
108
+ inherit Mongo::Model
109
+
110
+ attr_accessor :name, :stats
111
+ def == o; [self.class, self.name, self.stats] == [o.class, o.respond_to(:name), o.respond_to(:stats)] end
112
+ end
113
+ end
114
+ end
115
+ after(:all){remove_constants :Player}
116
+
117
+ before do
118
+ @mission_class = Player::Mission
119
+ @player = Player.new
120
+ @player.missions = [
121
+ Player::Mission.build(name: 'Wasteland', stats: {buildings: 5, units: 10}),
122
+ Player::Mission.build(name: 'Backwater Station', stats: {buildings: 8, units: 25}),
123
+ ]
124
+ end
125
+
126
+ it_should_behave_like 'embedded object CRUD'
127
+
128
+ it 'crud' do
129
+ # create
130
+ @player.save.should be_true
131
+ @player._id.should_not be_nil
132
+
133
+ # read
134
+ Player.count.should == 1
135
+ Player.first.should == @player
136
+ Player.first.object_id.should_not == @players.object_id
137
+
138
+ # update
139
+ @player.missions.first.stats[:units] = 9
140
+ @player.missions << Player::Mission.build(name: 'Desperate Alliance', stats: {buildings: 11, units: 40})
141
+ @player.save.should be_true
142
+ Player.count.should == 1
143
+ Player.first.should == @player
144
+ Player.first.object_id.should_not == @player.object_id
145
+
146
+ # destroy
147
+ @player.destroy.should be_true
148
+ Player.count.should == 0
149
+ end
150
+ end
151
+ end
data/spec/db_spec.rb ADDED
@@ -0,0 +1,63 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Collection & Database' do
4
+ with_mongo
5
+
6
+ before :all do
7
+ class TheModel
8
+ inherit Mongo::Model
9
+ end
10
+ end
11
+ after(:all){remove_constants :TheModel}
12
+
13
+ after do
14
+ TheModel.db = nil
15
+ TheModel.collection = nil
16
+ Mongo::Model.connection, Mongo::Model.db = nil, nil
17
+ end
18
+
19
+ it "global setting" do
20
+ Mongo::Model.connection = db.connection
21
+ Mongo::Model.db = db
22
+
23
+ Mongo::Model.connection.should == db.connection
24
+ Mongo::Model.db.should == db
25
+ end
26
+
27
+ it "should allow set database per model" do
28
+ Mongo::Model.connection = db.connection
29
+ Mongo::Model.db = db
30
+
31
+ TheModel.db.should == db
32
+
33
+ TheModel.db :test
34
+ TheModel.db.name.should == 'test'
35
+
36
+ TheModel.db = nil
37
+ TheModel.db db
38
+ TheModel.db.should == db
39
+
40
+ TheModel.db = nil
41
+ TheModel.db{db}
42
+ TheModel.db.should == db
43
+ end
44
+
45
+ it "should allow set collection per model" do
46
+ Mongo::Model.db = db
47
+
48
+ # TheModel.default_collection_name.should == :the_model
49
+ # TheModel.collection.name.should == 'the_model'
50
+
51
+ TheModel.collection :units
52
+ TheModel.collection.name.should == 'units'
53
+
54
+ TheModel.collection = nil
55
+ units = db.units
56
+ TheModel.collection units
57
+ TheModel.collection.should == units
58
+
59
+ TheModel.collection = nil
60
+ TheModel.collection{units}
61
+ TheModel.collection.should == units
62
+ end
63
+ end
data/spec/misc_spec.rb ADDED
@@ -0,0 +1,58 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'Model Miscellaneous' do
4
+ with_mongo_model
5
+
6
+ before do
7
+ class User
8
+ inherit Mongo::Model
9
+ collection :users
10
+ end
11
+ end
12
+ after{remove_constants :Unit3, :User}
13
+
14
+ it "timestamps" do
15
+ class Unit3
16
+ inherit Mongo::Model
17
+ collection :units
18
+
19
+ attr_accessor :name
20
+
21
+ timestamps!
22
+ end
23
+
24
+ unit = Unit3.build name: 'Zeratul'
25
+ unit.save!
26
+
27
+ unit = Unit3.first
28
+ unit.created_at.should_not be_nil
29
+ unit.updated_at.should_not be_nil
30
+ created_at,updated_at = unit.created_at, unit.updated_at
31
+
32
+ unit.save!
33
+ unit.created_at.should == created_at
34
+ unit.updated_at.should > updated_at
35
+ end
36
+
37
+ it 'cache' do
38
+ class Unit3
39
+ inherit Mongo::Model
40
+ end
41
+ u = Unit3.new
42
+ u._cache.should == {}
43
+ end
44
+
45
+ it "to_param" do
46
+ u = User.new
47
+ u.to_param.should == ''
48
+ u.save!
49
+ u.to_param.should_not be_empty
50
+ end
51
+
52
+ it "dom_id" do
53
+ u = User.new
54
+ u.dom_id.should == ''
55
+ u.save!
56
+ u.dom_id.should_not be_empty
57
+ end
58
+ end
@@ -0,0 +1,46 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Model Query" do
4
+ with_mongo_model
5
+
6
+ before :all do
7
+ class Unit
8
+ inherit Mongo::Model
9
+ collection :units
10
+
11
+ attr_accessor :name
12
+ end
13
+ end
14
+ after(:all){remove_constants :Unit}
15
+
16
+ before{@zeratul = Unit.build name: 'Zeratul'}
17
+
18
+ it 'exist?' do
19
+ Unit.should_not exist(name: 'Zeratul')
20
+ @zeratul.save!
21
+ Unit.should exist(name: 'Zeratul')
22
+ end
23
+
24
+ it 'first, first!' do
25
+ Unit.first.should be_nil
26
+ -> {Unit.first!}.should raise_error(Mongo::NotFound)
27
+ @zeratul.save
28
+ Unit.first.should_not be_nil
29
+ Unit.first!.should_not be_nil
30
+ end
31
+
32
+ it 'all, each' do
33
+ list = []; Unit.each{|o| list << o}
34
+ list.size.should == 0
35
+
36
+ @zeratul.save
37
+ list = []; Unit.each{|o| list << o}
38
+ list.size.should == 1
39
+ end
40
+
41
+ it 'dynamic finders integration' do
42
+ Unit.first_by_name('Zeratul').should be_nil
43
+ Unit.build(name: 'Zeratul').save!
44
+ Unit.first_by_name('Zeratul').name.should == 'Zeratul'
45
+ end
46
+ end
@@ -0,0 +1,149 @@
1
+ require 'spec_helper'
2
+
3
+ describe "Scope" do
4
+ with_mongo_model
5
+
6
+ before do
7
+ class Unit
8
+ inherit Mongo::Model
9
+ collection :units
10
+
11
+ attr_accessor :name, :status, :race
12
+ end
13
+ end
14
+
15
+ after{remove_constants :Unit, :Protoss}
16
+
17
+ describe 'current scope' do
18
+ it "should affect finders" do
19
+ Unit.build(name: 'Zeratul', status: 'alive').save!
20
+ Unit.build(name: 'Jim', status: 'alive').save!
21
+ Unit.build(name: 'Tassadar', status: 'dead').save!
22
+
23
+ Unit.count.should == 3
24
+ Unit.all.size.should == 3
25
+ Unit.first(name: 'Tassadar').should_not be_nil
26
+ Unit.first!(name: 'Tassadar').should_not be_nil
27
+
28
+ Unit.stub!(:current_scope).and_return(status: 'alive')
29
+
30
+ Unit.count.should == 2
31
+ Unit.all.size.should == 2
32
+ Unit.first(name: 'Tassadar').should be_nil
33
+ -> {Unit.first!(name: 'Tassadar')}.should raise_error(Mongo::NotFound)
34
+
35
+ # should be merged with finders
36
+ Unit.count(status: 'dead').should == 1
37
+ Unit.all(status: 'dead').size.should == 1
38
+ Unit.first(name: 'Tassadar', status: 'dead').should_not be_nil
39
+ Unit.first!(name: 'Tassadar', status: 'dead').should_not be_nil
40
+ end
41
+ end
42
+
43
+ describe 'default scope' do
44
+ it "should not affect objects without default_scope" do
45
+ Unit.current_scope.should == {}
46
+ end
47
+
48
+ it "definition" do
49
+ Unit.default_scope status: 'alive'
50
+ Unit.current_scope.should == {status: 'alive'}
51
+
52
+ Unit.default_scope do
53
+ {status: 'alive'}
54
+ end
55
+ Unit.current_scope.should == {status: 'alive'}
56
+ end
57
+
58
+ it "should be inherited" do
59
+ Unit.default_scope status: 'alive'
60
+
61
+ class Protoss < Unit; end
62
+ Protoss.current_scope.should == {status: 'alive'}
63
+
64
+ Protoss.default_scope status: 'dead'
65
+ Unit.current_scope.should == {status: 'alive'}
66
+ Protoss.current_scope.should == {status: 'dead'}
67
+ end
68
+ end
69
+
70
+ describe 'scope' do
71
+ it "definition" do
72
+ Unit.scope :alive, status: 'alive'
73
+ Unit.alive.current_scope.should == {status: 'alive'}
74
+
75
+ Unit.scope :alive do
76
+ {status: 'alive'}
77
+ end
78
+ Unit.alive.current_scope.should == {status: 'alive'}
79
+ end
80
+
81
+ it 'scope should affect current scope' do
82
+ Unit.scope :alive, status: 'alive'
83
+
84
+ Unit.current_scope.should == {}
85
+
86
+ Unit.alive.current_scope.should == {status: 'alive'}
87
+ Unit.alive.should == Unit
88
+ end
89
+
90
+ it 'should be merged with default scope' do
91
+ Unit.default_scope race: 'Protoss'
92
+ Unit.scope :alive, status: 'alive'
93
+ Unit.alive.current_scope.should == {race: 'Protoss', status: 'alive'}
94
+ end
95
+
96
+ it 'should allow to chain scopes' do
97
+ Unit.scope :alive, status: 'alive'
98
+ Unit.scope :protosses, race: 'Protoss'
99
+ Unit.alive.protosses.current_scope.should == {race: 'Protoss', status: 'alive'}
100
+ end
101
+ end
102
+
103
+ describe 'with_scope' do
104
+ it "shouldn't allow to nest exclusive scope" do
105
+ -> {
106
+ Unit.with_exclusive_scope do
107
+ Unit.with_exclusive_scope{}
108
+ end
109
+ }.should raise_error(/exclusive scope already applied/)
110
+
111
+ -> {
112
+ Unit.with_exclusive_scope do
113
+ Unit.with_scope{}
114
+ end
115
+ }.should raise_error(/exclusive scope already applied/)
116
+ end
117
+
118
+ it "with_exclusive_scope should clear other scopes" do
119
+ Unit.default_scope status: 'alive'
120
+
121
+ Unit.with_scope race: 'Protoss' do
122
+ Unit.current_scope.should == {status: 'alive', race: 'Protoss'}
123
+
124
+ Unit.with_exclusive_scope do
125
+ Unit.current_scope.should == {}
126
+ end
127
+
128
+ Unit.with_exclusive_scope race: 'Terran' do
129
+ Unit.current_scope.should == {race: 'Terran'}
130
+ end
131
+ end
132
+ end
133
+
134
+ it "usage" do
135
+ Unit.with_scope status: 'alive' do
136
+ Unit.current_scope.should == {status: 'alive'}
137
+ end
138
+ end
139
+
140
+ it "should merge scope" do
141
+ Unit.default_scope status: 'alive'
142
+ Unit.with_scope race: 'Protoss' do
143
+ Unit.with_scope name: 'Zeratul' do
144
+ Unit.current_scope.should == {name: 'Zeratul', race: 'Protoss', status: 'alive'}
145
+ end
146
+ end
147
+ end
148
+ end
149
+ end
@@ -0,0 +1,13 @@
1
+ require 'mongodb_model'
2
+
3
+ require 'rspec_ext'
4
+ require 'mongodb_model/spec'
5
+
6
+ #
7
+ # Handy spec helpers
8
+ #
9
+ rspec do
10
+ def db
11
+ mongo.db
12
+ end
13
+ end