mongocore 0.1.1 → 0.1.2

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.
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