mongocore 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 930f0c5ba53f15b7014cb473803554975acf1679
4
- data.tar.gz: 6d84ab1c806b72b558641f89cbb3608d7ee34c79
3
+ metadata.gz: 55808be92e72f178a15d79162ce306e93697af46
4
+ data.tar.gz: 616b1fa1123ee89dae66153e1b5702679a829310
5
5
  SHA512:
6
- metadata.gz: 750dcd341fee0a1266951f93705d6aeb02a03f5b0ef44af2c439ccc5d2db0d284da1d241a325393982662b88a436b61cecf768850547d252e0842dfd1fc6b42c
7
- data.tar.gz: 9a98403d956ae87fec94e8833a6bdd6acd9d0ed9ea2c4979629b84ce0f69ff72b6542b04da5b87cd6dfb657f239cdccea37c371d9574647959714080d65a902e
6
+ metadata.gz: c3ca71c855ad06198b6d4d05c8a5abf8816868c53d649caeeb81b9063f72657ce70f6e773d4c7d4a171a06c291279d1524e1153376ba3670f841e748c23eb91b
7
+ data.tar.gz: e33647c2848cc8d04dc6db9db061c2009637e6e1714c7a74996744efd2ad64e62a60feda4d1137d4f5257a0e7c033c9a79e43a9938df11fcafc43de86d33eea5
data/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ **Version 0.1.0** - *2017-01-06*
2
+
3
+ - Fixed gemspec issues
4
+
1
5
  **Version 0.1.0** - *2017-01-05*
2
6
 
3
7
  - Automatic saving of created_at and updated_at keys if they exist
data/README.md CHANGED
@@ -7,11 +7,11 @@ The perfect companion for Sinatra or other Rack-based web frameworks.
7
7
  With Mongocore you can do:
8
8
 
9
9
  * Insert, update and delete
10
- * Finding, sorting, limit, defaults
11
- * Scopes, associations, validations
10
+ * Finding, sorting, limit, skip, defaults
11
+ * Scopes, associations, validations, pagination
12
12
  * Read and write access control for each key
13
13
  * Request cache, counter cache, track changes
14
- * Automatic timestamps, tagged keys
14
+ * Automatic timestamps, tagged keys, json
15
15
 
16
16
  The schema is specified with a YAML file which supports default values, data types, and security levels for each key.
17
17
 
@@ -21,10 +21,9 @@ Please read [the source code](https://github.com/fugroup/mongocore/tree/master/l
21
21
  | -------------------------------------- | ----- | ------- | ------------- |
22
22
  | [Mongoid](http://mongoid.com) | 256 | 14371 | 10590 |
23
23
  | [MongoMapper](http://mongomapper.com) | 91 | 200 | 4070 |
24
- | [Mongocore](http://mongocore.com) | 7 | 224 | 354 |
24
+ | [Mongocore](http://mongocore.com) | 8 | 224 | 354 |
25
25
 
26
26
  <br>
27
- If you are looking for something even lighter, we also [have Minimongo,](https://github.com/fugroup/minimongo) the world's tiniest MongoDB library.
28
27
 
29
28
  The tests are written [using Futest,](https://github.com/fugroup/futest) try it out if you haven't, it makes testing so much fun.
30
29
 
@@ -57,6 +56,9 @@ Mongocore.access = true
57
56
  # Enable timestamps, auto-save created_at and updated_at keys
58
57
  Mongocore.timestamps = true
59
58
 
59
+ # Pagination results per page
60
+ Mogocore.per_page = 20
61
+
60
62
  # Enable debug to see caching information and help
61
63
  Mongocore.debug = false
62
64
  ```
@@ -64,6 +66,9 @@ Mongocore.debug = false
64
66
  ### Usage
65
67
 
66
68
  ```ruby
69
+ # Set up connection to database engine
70
+ Mongocore.db = Mongo::Client.new(['127.0.0.1:27017'], :database => "mongocore_#{ENV['RACK_ENV']}")
71
+
67
72
  # Create a new document
68
73
  m = Model.new
69
74
  m.duration = 59
@@ -93,6 +98,11 @@ f = query.first
93
98
  # All
94
99
  m = Model.find.all
95
100
 
101
+ # Pagination returns an array
102
+ m = Model.find.paginate
103
+ m = Model.find.paginate(:per_page => 10, :page => 5)
104
+ m.total # => Total number of results
105
+
96
106
  # All of these can be used:
97
107
  # https://docs.mongodb.com/manual/reference/operator/query-comparison
98
108
  m = Model.find(:house => {:$ne => nil, :$eq => 'Nice'}).last
@@ -193,10 +203,17 @@ Mongocore.db[:models].indexes.create_one({:key => 1})
193
203
  Mongocore.db[:models].indexes.create_one({:key => 1}, :unique => true)
194
204
  ```
195
205
 
196
- ### Schema
197
- For keys, defaults, description, counters, associations, scopes and accessors, use a schema file written in [YAML.](http://yaml.org)
206
+ ### Schema and models
207
+ Each model defined using a [YAML.](http://yaml.org) schema file. This is where you define keys, defaults, description, counters, associations, access, tags, scopes and accessors.
208
+
209
+ The default schema file location is `APP_ROOT/config/db/schema/*.yml`, so if you have a model called Parent, create a yml file called parent.yml.
210
+
211
+ You can change the shema file location like this:
212
+ ```ruby
213
+ Mongocore.schema = File.join(Dir.pwd, 'your', 'schema', 'path')
214
+ ```
198
215
 
199
- #### Parent example schema
216
+ #### Parent example schema, has many Models
200
217
  ```yml
201
218
 
202
219
  # The meta is information about your model
@@ -206,7 +223,8 @@ meta:
206
223
 
207
224
  keys:
208
225
 
209
- # Use the _id everywhere. The id can be used for whatever you want.
226
+ # Define the _id field for all your models. The id field (without _)
227
+ # is an alias to _id, but always returns a string instead of a BSON::ObjectId
210
228
  # @desc: Describes the key, can be used for documentation.
211
229
  # @type: object_id, string, integer, float, boolean, time, hash, array
212
230
  # @default: the default value for the key when you call .new
@@ -253,7 +271,7 @@ many:
253
271
  ```
254
272
 
255
273
 
256
- #### Model example schema
274
+ #### Model example schema, belongs to Parent
257
275
 
258
276
  ```yml
259
277
  meta:
@@ -57,7 +57,7 @@ module Mongocore
57
57
  a[:_id] ? @saved = true : a[:_id] = BSON::ObjectId.new
58
58
 
59
59
  # The errors hash
60
- @errors = Hash.new{|h, k| h[k] = []}
60
+ @errors = Mongocore::Errors.new{|h, k| h[k] = []}
61
61
 
62
62
  # Defaults
63
63
  self.class.schema.defaults.each{|k, v| write(k, v)}
@@ -79,15 +79,15 @@ module Mongocore
79
79
  # Save attributes to db
80
80
  def save(o = {})
81
81
  # Send :validate => true to validate
82
- return nil unless valid? if o[:validate]
82
+ return false unless valid? if o[:validate]
83
83
 
84
84
  # Create a new query
85
- filter(:save){mq(self.class, {:_id => @_id}).update(attributes)}
85
+ filter(:save){mq(self.class, {:_id => @_id}).update(attributes).ok?}
86
86
  end
87
87
 
88
88
  # Update document in db
89
89
  def update(a = {})
90
- a.each{|k, v| write(k, v)}; filter(:update){single.update(a)}
90
+ a.each{|k, v| write(k, v)}; filter(:update){single.update(a).ok?}
91
91
  end
92
92
 
93
93
  # Delete a document in db
@@ -132,9 +132,10 @@ module Mongocore
132
132
 
133
133
  # JSON format, pass tags as symbols: to_json(:badge, :gun)
134
134
  def to_json(*args)
135
- attributes(*args).to_json
135
+ a = attributes(*args); a.delete(:_id); {:id => id}.merge(a).to_json
136
136
  end
137
137
 
138
+
138
139
  # # # # # # # # # # # # # # # #
139
140
  # Validation methods
140
141
  #
@@ -225,6 +226,11 @@ module Mongocore
225
226
  super
226
227
  end
227
228
 
229
+ # Alias for _id but returns string
230
+ def id
231
+ @_id ? @_id.to_s : nil
232
+ end
233
+
228
234
  end
229
235
 
230
236
 
@@ -269,6 +275,17 @@ module Mongocore
269
275
  find({}, {}, :limit => n)
270
276
  end
271
277
 
278
+ # Skip
279
+ def skip(n = 0)
280
+ find({}, {}, :skip => n)
281
+ end
282
+
283
+ # Fields (projection)
284
+ def fields(o = {})
285
+ find({}, {}, :fields => o)
286
+ end
287
+
288
+
272
289
  # # # # # # # # #
273
290
  # After, before and validation filters
274
291
  # Pass a method name as symbol or a block
@@ -0,0 +1,5 @@
1
+ module Mongocore
2
+ class Errors < Hash
3
+
4
+ end
5
+ end
@@ -0,0 +1,8 @@
1
+ # Extensions for ruby classes
2
+
3
+ class Array
4
+
5
+ # Holds the total number of pagination results
6
+ attr_accessor :total
7
+
8
+ end
@@ -12,11 +12,18 @@ module Mongocore
12
12
 
13
13
  attr_accessor :model, :collection, :colname, :query, :options, :store, :cache
14
14
 
15
- # These options will be deleted before doing the find
15
+ # Mongocore query initializer
16
16
  def initialize(m, q = {}, o = {}, s = {})
17
- # Support find passing a ID
17
+
18
+ # Support find passing an ID
18
19
  q = {:_id => oid(q)} unless q.is_a?(Hash)
19
20
 
21
+ # Support passing :id as :_id
22
+ q[:_id] = q.delete(:id) if q[:id]
23
+
24
+ # Support passing _id as a string
25
+ q[:_id] = oid(q[:_id]) if q[:_id].is_a?(String)
26
+
20
27
  # Storing model class. The instance can be found in store[:source]
21
28
  @model = m
22
29
 
@@ -27,7 +34,7 @@ module Mongocore
27
34
  @collection = Mongocore.db[@colname]
28
35
 
29
36
  # Storing query and options. Sort and limit is stored in options
30
- s[:sort] ||= {}; s[:limit] ||= 0; s[:chain] ||= []; s[:source] ||= nil
37
+ s[:sort] ||= {}; s[:limit] ||= 0; s[:chain] ||= []; s[:source] ||= nil; s[:fields] ||= {}; s[:skip] ||= 0
31
38
  @query, @options, @store = q, o, s
32
39
 
33
40
  # Set up cache
@@ -41,7 +48,7 @@ module Mongocore
41
48
 
42
49
  # Cursor
43
50
  def cursor
44
- @collection.find(@query, @options).sort(@store[:sort]).limit(@store[:limit])
51
+ @collection.find(@query, @options).projection(@store[:fields]).skip(@store[:skip]).sort(@store[:sort]).limit(@store[:limit])
45
52
  end
46
53
 
47
54
  # Update
@@ -85,6 +92,28 @@ module Mongocore
85
92
  fetch(:to_a).map{|d| first(d)}
86
93
  end
87
94
 
95
+ # Paginate
96
+ def paginate(o = {})
97
+
98
+ # Get total count before applying pagination
99
+ total = fetch(:count)
100
+
101
+ # Set page, defaults to 1
102
+ o[:page] = o[:page].to_i; o[:page] = 1 if o[:page] < 1
103
+
104
+ # Set results per page, defaults to 20 in Mongocore.per_page setting
105
+ o[:per_page] = o[:per_page].to_i; o[:per_page] = Mongocore.per_page if o[:per_page] < 1
106
+
107
+ # Skip results
108
+ store[:skip] = o[:per_page] * (o[:page] - 1)
109
+
110
+ # Apply limit
111
+ store[:limit] = o[:per_page]
112
+
113
+ # Fetch the result as array
114
+ fetch(:to_a).map{|d| first(d)}.tap{|r| r.total = total}
115
+ end
116
+
88
117
  # Fetch docs, pass type :first, :to_a or :count
89
118
  def fetch(t)
90
119
  cache.get(t) if Mongocore.cache
@@ -95,7 +124,7 @@ module Mongocore
95
124
 
96
125
  # Sort
97
126
  def sort(o = {})
98
- find(@query, options, @store.tap{store[:sort].merge!(o)})
127
+ find(@query, @options, @store.tap{store[:sort].merge!(o)})
99
128
  end
100
129
 
101
130
  # Limit
@@ -103,6 +132,16 @@ module Mongocore
103
132
  find(@query, @options, @store.tap{store[:limit] = n})
104
133
  end
105
134
 
135
+ # Skip
136
+ def skip(n = 0)
137
+ find(@query, @options, @store.tap{store[:skip] = n})
138
+ end
139
+
140
+ # Fields (projection)
141
+ def fields(o = {})
142
+ find(@query, @options, @store.tap{store[:fields].merge!(o)})
143
+ end
144
+
106
145
  # Cache key
107
146
  def key
108
147
  @key ||= "#{@model}#{@query.sort}#{@options.sort}#{@store.values}"
data/lib/mongocore.rb CHANGED
@@ -15,7 +15,7 @@ module Mongocore
15
15
  # @license: MIT, contributions are welcome.
16
16
  # # # # # #
17
17
 
18
- class << self; attr_accessor :db, :schema, :cache, :access, :timestamps, :debug; end
18
+ class << self; attr_accessor :db, :schema, :cache, :access, :timestamps, :per_page, :debug; end
19
19
 
20
20
  # Schema path is $app_root/config/db/schema/:model_name.yml
21
21
  @schema = File.join(Dir.pwd, 'config', 'db', 'schema')
@@ -29,10 +29,15 @@ module Mongocore
29
29
  # Enable timestamps, auto-save created_at and updated_at fields
30
30
  @timestamps = true
31
31
 
32
+ # Pagination results per page
33
+ @per_page = 20
34
+
32
35
  # Debug option
33
36
  @debug = false
34
37
  end
35
38
 
39
+ require_relative 'mongocore/ext'
40
+ require_relative 'mongocore/errors'
36
41
  require_relative 'mongocore/document'
37
42
  require_relative 'mongocore/query'
38
43
  require_relative 'mongocore/schema'
data/mongocore.gemspec CHANGED
@@ -1,9 +1,9 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = 'mongocore'
3
- s.version = '0.1.1'
4
- s.date = '2017-01-05'
3
+ s.version = '0.1.2'
4
+ s.date = '2017-10-11'
5
5
  s.summary = "MongoDB ORM implementation on top of the Ruby MongoDB driver"
6
- s.description = "Does validations, associations, scopes, filters, counter cache, request cache, and nested queries. Using a YAML schema file, which supports default values, data types, and security levels for each key."
6
+ s.description = "Does validations, associations, scopes, filters, pagination, counter cache, request cache, and nested queries. Using a YAML schema file, which supports default values, data types, and security levels for each key."
7
7
  s.authors = ["Fugroup Limited"]
8
8
  s.email = 'mail@fugroup.net'
9
9
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mongocore
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Fugroup Limited
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-01-05 00:00:00.000000000 Z
11
+ date: 2017-10-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: mongo
@@ -66,9 +66,9 @@ dependencies:
66
66
  - - ">="
67
67
  - !ruby/object:Gem::Version
68
68
  version: '0'
69
- description: Does validations, associations, scopes, filters, counter cache, request
70
- cache, and nested queries. Using a YAML schema file, which supports default values,
71
- data types, and security levels for each key.
69
+ description: Does validations, associations, scopes, filters, pagination, counter
70
+ cache, request cache, and nested queries. Using a YAML schema file, which supports
71
+ default values, data types, and security levels for each key.
72
72
  email: mail@fugroup.net
73
73
  executables: []
74
74
  extensions: []
@@ -86,6 +86,8 @@ files:
86
86
  - lib/mongocore/access.rb
87
87
  - lib/mongocore/cache.rb
88
88
  - lib/mongocore/document.rb
89
+ - lib/mongocore/errors.rb
90
+ - lib/mongocore/ext.rb
89
91
  - lib/mongocore/filters.rb
90
92
  - lib/mongocore/query.rb
91
93
  - lib/mongocore/schema.rb
@@ -112,7 +114,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
112
114
  version: '0'
113
115
  requirements: []
114
116
  rubyforge_project:
115
- rubygems_version: 2.5.1
117
+ rubygems_version: 2.6.12
116
118
  signing_key:
117
119
  specification_version: 4
118
120
  summary: MongoDB ORM implementation on top of the Ruby MongoDB driver