mordor 0.1.3 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +19 -0
- data/lib/mordor/collection.rb +6 -37
- data/lib/mordor/resource.rb +47 -15
- data/mordor.gemspec +3 -3
- data/spec/mordor/collection_spec.rb +79 -8
- data/spec/mordor/resource_spec.rb +56 -5
- metadata +6 -6
- data/README +0 -13
data/README.md
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
## Introduction
|
2
|
+
Small library to add DataMapper style resources for MongoDB.
|
3
|
+
|
4
|
+
```ruby
|
5
|
+
class ExampleResource
|
6
|
+
include Mordor::Resource
|
7
|
+
|
8
|
+
attribute :first, :index => true
|
9
|
+
attribute :second
|
10
|
+
attribute :third, :finder_method => :find_by_third_attribute
|
11
|
+
end
|
12
|
+
```
|
13
|
+
|
14
|
+
This adds attr_accessors to the ExampleResource for each attribute, plus adds finder methods of the form
|
15
|
+
`find_by_{attribute}`. The naming convention can be overridden by using the optional `:finder_method` option,
|
16
|
+
as can be seen with the third attribute.
|
17
|
+
|
18
|
+
When the `:index => true` option is set, indices are ensured before each query on
|
19
|
+
the collection. Indices are descending by default, but this can be changed by also supplying a `:index_type => Mongo::ASCENDING` option.
|
data/lib/mordor/collection.rb
CHANGED
@@ -7,22 +7,6 @@ module Mordor
|
|
7
7
|
@cursor = cursor
|
8
8
|
end
|
9
9
|
|
10
|
-
def to_a
|
11
|
-
array = []
|
12
|
-
unless @cursor.is_a? Array
|
13
|
-
@cursor.each do |element|
|
14
|
-
if element.is_a? @klass
|
15
|
-
array << element
|
16
|
-
else
|
17
|
-
array << @klass.new(element)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
else
|
21
|
-
array = @cursor.dup
|
22
|
-
end
|
23
|
-
array
|
24
|
-
end
|
25
|
-
|
26
10
|
def each
|
27
11
|
@cursor.each do |element|
|
28
12
|
if element.is_a? @klass
|
@@ -31,21 +15,13 @@ module Mordor
|
|
31
15
|
yield @klass.new(element)
|
32
16
|
end
|
33
17
|
end
|
18
|
+
@cursor.rewind! unless @cursor.is_a? Array
|
34
19
|
end
|
35
20
|
|
36
|
-
def
|
37
|
-
|
38
|
-
@cursor.first ? @klass.new(@cursor.first) : nil
|
39
|
-
else
|
40
|
-
result = @cursor.first
|
41
|
-
@cursor.rewind!
|
42
|
-
result ? @klass.new(result) : nil
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
def size
|
47
|
-
@cursor.count
|
21
|
+
def size(regard_limits_and_offsets = true)
|
22
|
+
@cursor.is_a?(Array) ? @cursor.count : @cursor.count(regard_limits_and_offsets)
|
48
23
|
end
|
24
|
+
alias :count :size
|
49
25
|
|
50
26
|
def method_missing(method, *args, &block)
|
51
27
|
if @cursor.respond_to?(method)
|
@@ -55,15 +31,8 @@ module Mordor
|
|
55
31
|
end
|
56
32
|
end
|
57
33
|
|
58
|
-
def to_json
|
59
|
-
|
60
|
-
res = {
|
61
|
-
collection_name => []
|
62
|
-
}
|
63
|
-
each do |elem|
|
64
|
-
res[collection_name] << elem.to_hash
|
65
|
-
end
|
66
|
-
res.to_json
|
34
|
+
def to_json(*args)
|
35
|
+
to_a.to_json(*args)
|
67
36
|
end
|
68
37
|
|
69
38
|
def merge(other_collection)
|
data/lib/mordor/resource.rb
CHANGED
@@ -28,7 +28,9 @@ module Mordor
|
|
28
28
|
when Hash
|
29
29
|
value = replace_params(value)
|
30
30
|
when Date, DateTime
|
31
|
-
value = value.to_time
|
31
|
+
value = value.to_time.getlocal
|
32
|
+
when Time
|
33
|
+
value = value.getlocal
|
32
34
|
when BigDecimal
|
33
35
|
value = value.to_f
|
34
36
|
when Array
|
@@ -81,6 +83,10 @@ module Mordor
|
|
81
83
|
result
|
82
84
|
end
|
83
85
|
|
86
|
+
def to_json(*args)
|
87
|
+
to_hash.merge(:_id => _id).to_json(*args)
|
88
|
+
end
|
89
|
+
|
84
90
|
module ClassMethods
|
85
91
|
def create(attributes = {})
|
86
92
|
resource = self.new(attributes)
|
@@ -89,7 +95,7 @@ module Mordor
|
|
89
95
|
end
|
90
96
|
|
91
97
|
def all(options = {})
|
92
|
-
Collection.new(self,
|
98
|
+
Collection.new(self, perform_collection_find({}, options))
|
93
99
|
end
|
94
100
|
|
95
101
|
def collection
|
@@ -105,7 +111,7 @@ module Mordor
|
|
105
111
|
if id.is_a?(String)
|
106
112
|
id = BSON::ObjectId.from_string(id)
|
107
113
|
end
|
108
|
-
if attributes =
|
114
|
+
if attributes = perform_collection_find_one(:_id => id)
|
109
115
|
new(attributes)
|
110
116
|
else
|
111
117
|
nil
|
@@ -116,12 +122,13 @@ module Mordor
|
|
116
122
|
@connection ||= Mordor.connection
|
117
123
|
end
|
118
124
|
|
125
|
+
|
119
126
|
def find_by_id(id)
|
120
127
|
get(id)
|
121
128
|
end
|
122
129
|
|
123
130
|
def find(query, options = {})
|
124
|
-
Collection.new(self,
|
131
|
+
Collection.new(self, perform_collection_find(query, options))
|
125
132
|
end
|
126
133
|
|
127
134
|
def find_by_day(day, options = {})
|
@@ -137,17 +144,21 @@ module Mordor
|
|
137
144
|
end_of_day = (day.to_date + 1).to_datetime.to_date.to_time
|
138
145
|
end
|
139
146
|
hash = {:at => {'$gte' => start, '$lt' => end_of_day}}
|
140
|
-
|
141
|
-
cursor = collection.find({:at => {'$gte' => start, '$lt' => end_of_day}}, options).to_a
|
142
|
-
else
|
143
|
-
cursor = collection.find({:at => {'$gte' => start, '$lt' => end_of_day}})
|
144
|
-
end
|
147
|
+
cursor = perform_collection_find({:at => {'$gte' => start, '$lt' => end_of_day}}, options)
|
145
148
|
Collection.new(self, cursor)
|
146
149
|
end
|
147
150
|
|
151
|
+
|
148
152
|
def attribute(name, options = {})
|
149
|
-
@attributes
|
153
|
+
@attributes ||= []
|
154
|
+
@indices ||= []
|
155
|
+
@index_types ||= {}
|
156
|
+
|
150
157
|
@attributes << name unless @attributes.include?(name)
|
158
|
+
if options[:index]
|
159
|
+
@indices << name unless @indices.include?(name)
|
160
|
+
@index_types[name] = options[:index_type] ? options[:index_type] : Mongo::DESCENDING
|
161
|
+
end
|
151
162
|
|
152
163
|
method_name = options.key?(:finder_method) ? options[:finder_method] : "find_by_#{name}"
|
153
164
|
|
@@ -156,15 +167,36 @@ module Mordor
|
|
156
167
|
attr_accessor name
|
157
168
|
|
158
169
|
def self.#{method_name}(value, options = {})
|
159
|
-
|
160
|
-
col = collection.find({:#{name} => value}, options).to_a
|
161
|
-
else
|
162
|
-
col = collection.find(:#{name} => value)
|
163
|
-
end
|
170
|
+
col = perform_collection_find({:#{name} => value}, options)
|
164
171
|
Collection.new(self, col)
|
165
172
|
end
|
166
173
|
EOS
|
167
174
|
end
|
175
|
+
|
176
|
+
private
|
177
|
+
def perform_collection_find(query, options = {})
|
178
|
+
ensure_indices
|
179
|
+
collection.find(query, options)
|
180
|
+
end
|
181
|
+
|
182
|
+
def perform_collection_find_one(query, options = {})
|
183
|
+
ensure_indices
|
184
|
+
collection.find_one(query, options)
|
185
|
+
end
|
186
|
+
|
187
|
+
def ensure_indices
|
188
|
+
indices.each do |index|
|
189
|
+
collection.ensure_index( [ [index.to_s, index_types[index]] ] )
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
def indices
|
194
|
+
@indices ||= []
|
195
|
+
end
|
196
|
+
|
197
|
+
def index_types
|
198
|
+
@index_types ||= {}
|
199
|
+
end
|
168
200
|
end
|
169
201
|
end
|
170
202
|
end
|
data/mordor.gemspec
CHANGED
@@ -2,8 +2,8 @@ Gem::Specification.new do |s|
|
|
2
2
|
s.name = "mordor"
|
3
3
|
|
4
4
|
# Do not set the version and date field manually, this is done by the release script
|
5
|
-
s.version = "0.
|
6
|
-
s.date = "2011-
|
5
|
+
s.version = "0.2.0"
|
6
|
+
s.date = "2011-12-23"
|
7
7
|
|
8
8
|
s.summary = "mordor"
|
9
9
|
s.description = <<-eos
|
@@ -29,6 +29,6 @@ Gem::Specification.new do |s|
|
|
29
29
|
|
30
30
|
# The files and test_files directives are set automatically by the release script.
|
31
31
|
# Do not change them by hand, but make sure to add the files to the git repository.
|
32
|
-
s.files = %w(.gitignore Gemfile Gemfile.lock README Rakefile lib/mordor.rb lib/mordor/collection.rb lib/mordor/resource.rb lib/mordor/version.rb mordor.gemspec spec/mordor/collection_spec.rb spec/mordor/connection_spec.rb spec/mordor/resource_spec.rb spec/spec.opts spec/spec_helper.rb tasks/github-gem.rake)
|
32
|
+
s.files = %w(.gitignore Gemfile Gemfile.lock README.md Rakefile lib/mordor.rb lib/mordor/collection.rb lib/mordor/resource.rb lib/mordor/version.rb mordor.gemspec spec/mordor/collection_spec.rb spec/mordor/connection_spec.rb spec/mordor/resource_spec.rb spec/spec.opts spec/spec_helper.rb tasks/github-gem.rake)
|
33
33
|
end
|
34
34
|
|
@@ -4,9 +4,9 @@ describe "with respect to collections" do
|
|
4
4
|
class TestResource
|
5
5
|
include Mordor::Resource
|
6
6
|
|
7
|
-
attribute :first
|
8
|
-
attribute :second
|
9
|
-
attribute :third,
|
7
|
+
attribute :first, :index => true
|
8
|
+
attribute :second, :index => true, :index_type => Mongo::ASCENDING
|
9
|
+
attribute :third, :finder_method => :find_by_third_attribute
|
10
10
|
end
|
11
11
|
|
12
12
|
describe "serialization" do
|
@@ -28,11 +28,82 @@ describe "with respect to collections" do
|
|
28
28
|
|
29
29
|
json_collection = JSON.parse(json_collection)
|
30
30
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
31
|
+
json_collection.size.should == 5
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
describe "converting to array" do
|
36
|
+
before :all do
|
37
|
+
clean_sheet
|
38
|
+
|
39
|
+
5.times do |index|
|
40
|
+
res = TestResource.new(:first => "#{index}_first", :second => "#{index}_second", :third => "#{index}_third")
|
41
|
+
res.save.should be_true
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be possible to convert a collection to an array" do
|
46
|
+
collection = TestResource.find_by_first("1_first")
|
47
|
+
collection.to_a.should be_a Array
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should be possible to convert multiple times after iterating using each" do
|
51
|
+
collection = TestResource.find_by_first("1_first")
|
52
|
+
collection.each do |resource|
|
53
|
+
resource.first
|
54
|
+
end
|
55
|
+
array1 = collection.to_a
|
56
|
+
array2 = collection.to_a
|
57
|
+
array1.size.should == array2.size
|
58
|
+
end
|
59
|
+
|
60
|
+
it "should be possible to convert a collection to an array multiple times" do
|
61
|
+
collection = TestResource.find_by_first("1_first")
|
62
|
+
array1 = collection.to_a
|
63
|
+
array2 = collection.to_a
|
64
|
+
array1.size.should == array2.size
|
65
|
+
end
|
66
|
+
|
67
|
+
it "should convert the collection to an array with the same size" do
|
68
|
+
collection = TestResource.find_by_first("1_first")
|
69
|
+
collection_size = collection.size
|
70
|
+
collection.to_a.size.should == collection_size
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
describe "counting" do
|
75
|
+
|
76
|
+
before :all do
|
77
|
+
clean_sheet
|
78
|
+
|
79
|
+
5.times do |index|
|
80
|
+
res = TestResource.new(:first => "#{index}_first", :second => "#{index}_second", :third => "#{index}_third")
|
81
|
+
res.save.should be_true
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should default to taking in account limits" do
|
86
|
+
TestResource.find({}, {:limit => 3}).count.should == 3
|
87
|
+
end
|
88
|
+
|
89
|
+
it "should not take in account limits when requested" do
|
90
|
+
TestResource.find({}, {:limit => 3}).count(false).should == 5
|
91
|
+
end
|
92
|
+
|
93
|
+
it "should not take in account skips when requested" do
|
94
|
+
TestResource.find({}, {:skip => 2}).count(false).should == 5
|
95
|
+
end
|
96
|
+
|
97
|
+
it "should not take in account skips and limits when requested" do
|
98
|
+
TestResource.find({}, {:skip => 1, :limit => 3}).count(false).should == 5
|
99
|
+
end
|
100
|
+
|
101
|
+
it "should take in account skips by defaults" do
|
102
|
+
TestResource.find({}, {:skip => 2}).count.should == 3
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should take in account skips and limits by default" do
|
106
|
+
TestResource.find({}, {:skip => 1, :limit => 3}).count.should == 3
|
36
107
|
end
|
37
108
|
end
|
38
109
|
|
@@ -1,12 +1,22 @@
|
|
1
1
|
require File.join(File.dirname(__FILE__), '..', '/spec_helper.rb')
|
2
2
|
|
3
3
|
describe "with respect to resources" do
|
4
|
-
|
5
|
-
|
4
|
+
before :each do
|
5
|
+
class TestResource
|
6
|
+
include Mordor::Resource
|
7
|
+
|
8
|
+
attribute :first, :index => true
|
9
|
+
attribute :second, :index => true, :index_type => Mongo::ASCENDING
|
10
|
+
attribute :third, :finder_method => :find_by_third_attribute
|
11
|
+
|
12
|
+
# Put this in here again to ensure the original method is still here
|
13
|
+
class_eval do
|
14
|
+
def self.ensure_indices
|
15
|
+
collection.ensure_index( indices.map{|index| [index.to_s, Mongo::DESCENDING]} ) if indices.any?
|
16
|
+
end
|
6
17
|
|
7
|
-
|
8
|
-
|
9
|
-
attribute :third, :finder_method => :find_by_third_attribute
|
18
|
+
end
|
19
|
+
end
|
10
20
|
end
|
11
21
|
|
12
22
|
it "should create accessor methods for all attributes" do
|
@@ -23,6 +33,47 @@ describe "with respect to resources" do
|
|
23
33
|
TestResource.methods.should include "find_by_third_attribute"
|
24
34
|
end
|
25
35
|
|
36
|
+
it "should ensure indices when the option :index => true is given" do
|
37
|
+
TestResource.send(:indices).should include :first
|
38
|
+
end
|
39
|
+
|
40
|
+
it "should default to descending indices" do
|
41
|
+
TestResource.send(:index_types).keys.should include :first
|
42
|
+
TestResource.send(:index_types)[:first].should == Mongo::DESCENDING
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should be possible to set index type using the 'index_type' option" do
|
46
|
+
TestResource.send(:index_types).keys.should include :second
|
47
|
+
TestResource.send(:index_types)[:second].should == Mongo::ASCENDING
|
48
|
+
end
|
49
|
+
|
50
|
+
it "should call ensure_index on the collection for each index when a query is performed" do
|
51
|
+
TestResource.class_eval do
|
52
|
+
def self.ensure_count
|
53
|
+
@count ||= 0
|
54
|
+
end
|
55
|
+
|
56
|
+
def self.ensure_count=(val)
|
57
|
+
@count = val
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
def self.do_ensure_indices
|
62
|
+
indices.each do |index|
|
63
|
+
collection.ensure_index( [ [index.to_s, index_types[index]] ] )
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def self.ensure_indices
|
68
|
+
self.ensure_count = self.ensure_count + 1
|
69
|
+
self.do_ensure_indices
|
70
|
+
end
|
71
|
+
end
|
72
|
+
TestResource.create({:first => 'first', :second => 'second', :third => 'third'})
|
73
|
+
TestResource.all()
|
74
|
+
TestResource.ensure_count.should == 1
|
75
|
+
end
|
76
|
+
|
26
77
|
context "with respect to replacing params" do
|
27
78
|
before :each do
|
28
79
|
clean_sheet
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: mordor
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 23
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
-
|
10
|
-
version: 0.
|
8
|
+
- 2
|
9
|
+
- 0
|
10
|
+
version: 0.2.0
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Jan-Willem Koelewijn
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2011-
|
19
|
+
date: 2011-12-23 00:00:00 +01:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|
@@ -174,7 +174,7 @@ files:
|
|
174
174
|
- .gitignore
|
175
175
|
- Gemfile
|
176
176
|
- Gemfile.lock
|
177
|
-
- README
|
177
|
+
- README.md
|
178
178
|
- Rakefile
|
179
179
|
- lib/mordor.rb
|
180
180
|
- lib/mordor/collection.rb
|
data/README
DELETED
@@ -1,13 +0,0 @@
|
|
1
|
-
Small library to add DataMapper style resources for MongoDB.
|
2
|
-
|
3
|
-
class ExampleResource
|
4
|
-
include Mordor::Resource
|
5
|
-
|
6
|
-
attribute :first
|
7
|
-
attribute :second
|
8
|
-
attribute :third, :finder_method => :find_by_third_attribute
|
9
|
-
end
|
10
|
-
|
11
|
-
This adds attr_accessors to the ExampleResource for each attribute, plus adds finder methods of the form
|
12
|
-
find_by_{attribute}. The naming convention can be overridden by using the optional :finder_method option,
|
13
|
-
as can be seen with the third attribute.
|