hanami-rethinkdb 0.2.3

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ee0f2f4d4986d0e90672589655dbfd4386f60e40
4
+ data.tar.gz: b092fce947f9e2aeca833f7c32c5e8529b1370cf
5
+ SHA512:
6
+ metadata.gz: c9580b10916a33f686c336999f85241861562c3aa50003940d928b84f83e335600c7b84b4d4a0815b3de37e842172fde70caff0d67b16651e7f1ab696d5c9478
7
+ data.tar.gz: 5b2e0669f484ec3c24216e325589f9f293e500978c8444c3137cb82317404df1689aab95b1920121a92b57f719aea8d8379e80d978bf7384a73ebc8d8419be94
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ *.gem
15
+ mkmf.log
@@ -0,0 +1,20 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 2.0.0
5
+ - 2.1.0
6
+ - 2.1.1
7
+ - 2.1.2
8
+ - 2.1.3
9
+ - 2.1.4
10
+ - 2.1.5
11
+ - 2.2.0
12
+
13
+ before_install:
14
+ - source /etc/lsb-release && echo "deb http://download.rethinkdb.com/apt $DISTRIB_CODENAME main" | sudo tee /etc/apt/sources.list.d/rethinkdb.list
15
+ - wget -qO- http://download.rethinkdb.com/apt/pubkey.gpg | sudo apt-key add -
16
+ - sudo apt-get update -q
17
+ - sudo apt-get install rethinkdb
18
+ - sudo cp /etc/rethinkdb/default.conf.sample /etc/rethinkdb/instances.d/instance1.conf
19
+ - sudo service rethinkdb restart
20
+ - gem update bundler
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
3
+
4
+ gem 'coveralls', require: false
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Angelo Ashmore
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,73 @@
1
+ # Hanami::Model RethinkDB Adapter
2
+
3
+ This adapter implements a [Hanami::Model](https://github.com/hanami/model) persistence layer for [RethinkDB](http://rethinkdb.com).
4
+
5
+ ## Status
6
+
7
+ [![Gem Version](https://badge.fury.io/rb/hanami-rethinkdb.svg)](http://badge.fury.io/rb/hanami-rethinkdb)
8
+ [![Build Status](https://secure.travis-ci.org/angeloashmore/hanami-rethinkdb.svg?branch=master)](http://travis-ci.org/angeloashmore/hanami-rethinkdb?branch=master)
9
+ [![Coverage Status](https://img.shields.io/coveralls/angeloashmore/hanami-rethinkdb.svg)](https://coveralls.io/r/angeloashmore/hanami-rethinkdb)
10
+ [![Code Climate](https://codeclimate.com/github/angeloashmore/hanami-rethinkdb/badges/gpa.svg)](https://codeclimate.com/github/angeloashmore/hanami-rethinkdb)
11
+ [![Inline docs](http://inch-ci.org/github/angeloashmore/hanami-rethinkdb.svg?branch=master&style=flat)](http://inch-ci.org/github/angeloashmore/hanami-rethinkdb)
12
+
13
+ ## Links
14
+
15
+ * API Doc: [http://rdoc.info/gems/hanami-rethinkdb](http://rdoc.info/gems/hanami-rethinkdb)
16
+ * Bugs/Issues: [https://github.com/angeloashmore/hanami-rethinkdb/issues](https://github.com/angeloashmore/hanami-rethinkdb/issues)
17
+
18
+ ## Installation
19
+
20
+ Add this line to your application's Gemfile:
21
+
22
+ ```ruby
23
+ gem 'hanami-rethinkdb'
24
+ ```
25
+
26
+ And then execute:
27
+
28
+ $ bundle
29
+
30
+ Or install it yourself as:
31
+
32
+ $ gem install hanami-rethinkdb
33
+
34
+ ## Usage
35
+
36
+ Please refer to the [Hanami::Model](https://github.com/hanami/model#usage) docs for any details related to Entity, Repository, Data Mapper and Adapter.
37
+
38
+ ### Repository methods
39
+
40
+ See the [complete list](https://github.com/hanami/model#repositories) of Repository methods provided by ```Hanami::Model```.
41
+
42
+ Following methods are not supported since it's incompatible with RethinkDB:
43
+
44
+ * first
45
+ * last
46
+
47
+ ### Query methods
48
+
49
+ Generic query methods supported by the RethinkDB adapter:
50
+
51
+ * [all](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#all-instance_method)
52
+ * [where](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#where-instance_method)
53
+ * [limit](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#limit-instance_method)
54
+ * [order](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#order-instance_method) (alias: ```asc```)
55
+ * [desc](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#desc-instance_method)
56
+ * [sum](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#dum-instance_method)
57
+ * [average](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#average-instance_method) (alias: ```avg```)
58
+ * [max](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#max-instance_method)
59
+ * [min](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#min-instance_method)
60
+ * [count](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#count-instance_method)
61
+
62
+ RethinkDB-specific methods:
63
+
64
+ * [pluck](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#pluck-instance_method)
65
+ * [has_fields](http://rubydoc.info/gems/hanami-rethinkdb/Hanami/Model/Adapters/Rethinkdb/Query#has_fields-instance_method)
66
+
67
+ ## Contributing
68
+
69
+ 1. Fork it ( https://github.com/angeloashmore/hanami-rethinkdb/fork )
70
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
71
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
72
+ 4. Push to the branch (`git push origin my-new-feature`)
73
+ 5. Create a new Pull Request
@@ -0,0 +1,17 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'bundler/gem_tasks'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.pattern = 'test/**/*_test.rb'
7
+ t.libs.push 'test'
8
+ end
9
+
10
+ namespace :test do
11
+ task :coverage do
12
+ ENV['COVERAGE'] = 'true'
13
+ Rake::Task['test'].invoke
14
+ end
15
+ end
16
+
17
+ task default: :test
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hanami/rethinkdb/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'hanami-rethinkdb'
8
+ spec.version = Hanami::Rethinkdb::VERSION
9
+ spec.authors = ['Angelo Ashmore']
10
+ spec.email = ['angeloashmore@gmail.com']
11
+ spec.summary = 'RethinkDB adapter for Hanami::Model'
12
+ spec.description = 'RethinkDB adapter for Hanami::Model'
13
+ spec.homepage = 'https://github.com/angeloashmore/hanami-rethinkdb'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = `git ls-files`.split("\n")
17
+ spec.executables = spec.files.grep(/^bin\//) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(/^(test|spec|features)\//)
19
+ spec.require_paths = ['lib']
20
+
21
+ spec.add_runtime_dependency 'hanami-model', '~> 0.5'
22
+ spec.add_runtime_dependency 'rethinkdb', '~> 2.2'
23
+ spec.add_runtime_dependency 'activesupport', '~> 4.2'
24
+
25
+ spec.add_development_dependency 'bundler', '~> 1.6'
26
+ spec.add_development_dependency 'minitest', '~> 5.8'
27
+ spec.add_development_dependency 'minitest-line', '~> 0.6.3'
28
+ spec.add_development_dependency 'rake', '~> 11.1'
29
+ end
@@ -0,0 +1,2 @@
1
+ require 'hanami/model' # rubocop:disable Style/FileName
2
+ require 'hanami/model/adapters/rethinkdb_adapter'
@@ -0,0 +1,332 @@
1
+ require 'delegate'
2
+ require 'active_support/core_ext/hash/indifferent_access'
3
+ require 'rethinkdb'
4
+ require 'hanami/utils/kernel'
5
+
6
+ module Hanami
7
+ module Model
8
+ module Adapters
9
+ module Rethinkdb
10
+
11
+ require 'hanami/model/coercer'
12
+
13
+ class Now < Hanami::Model::Coercer
14
+ def self.dump(value)
15
+ Hanami::Utils::Kernel.Time(value)
16
+ end
17
+
18
+ def self.load(value)
19
+ value.to_datetime if value.respond_to? :to_datetime
20
+ end
21
+ end
22
+
23
+ # Maps a RethinkDB database table and perfoms manipulations on it.
24
+ #
25
+ # @api private
26
+ # @since 0.1.0
27
+ class Collection < SimpleDelegator
28
+ include RethinkDB::Shortcuts
29
+
30
+ # Initialize a collection
31
+ #
32
+ # @param connection [RethinkDB::Connection] the connection to the
33
+ # database
34
+ # @param dataset [RethinkDB::RQL] the dataset that maps a table or a
35
+ # subset of it
36
+ # @param mapped_collection [Hanami::Model::Mapping::Collection] a
37
+ # mapped collection
38
+ #
39
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection]
40
+ #
41
+ # @api private
42
+ # @since 0.1.0
43
+ def initialize(connection, dataset, mapped_collection)
44
+ super(dataset)
45
+ @connection, @mapped_collection = connection, mapped_collection
46
+ end
47
+
48
+ # Creates a document for the given entity and assigns an id.
49
+ #
50
+ # @param entity [Object] the entity to persist
51
+ #
52
+ # @see Hanami::Model::Adapters::Rethinkdb::Command#create
53
+ #
54
+ # @return the primary key of the created document
55
+ #
56
+ # @api private
57
+ # @since 0.1.0
58
+ def insert(entity)
59
+ serialized_entity = _serialize(entity)
60
+
61
+ response = _run do
62
+ super(serialized_entity)
63
+ end
64
+
65
+ serialized_entity[_identity] = response['generated_keys'].first
66
+
67
+ _deserialize([serialized_entity]).first
68
+ end
69
+
70
+ # Updates the document corresponding to the given entity.
71
+ #
72
+ # @param entity [Object] the entity to persist
73
+ #
74
+ # @see Hanami::Model::Adapters::Rethinkdb::Command#update
75
+ #
76
+ # @api private
77
+ # @since 0.1.0
78
+ def update(entity)
79
+ serialized_entity = _serialize(entity)
80
+
81
+ response = _run do
82
+ super(serialized_entity)
83
+ end
84
+
85
+ _deserialize([serialized_entity]).first
86
+ end
87
+
88
+ # Deletes the current scope.
89
+ #
90
+ # @see Hanami::Model::Adapters::Rethinkdb::Command#delete
91
+ #
92
+ # @api private
93
+ # @since 0.1.0
94
+ def delete
95
+ _run do
96
+ super
97
+ end
98
+ end
99
+
100
+ # Filters the current scope with a `filter` directive.
101
+ #
102
+ # @param args [Array] the array of arguments
103
+ #
104
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#where
105
+ #
106
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection] the filtered
107
+ # collection
108
+ #
109
+ # @api private
110
+ # @since 0.1.0
111
+ def filter(*args)
112
+ _collection(super, @mapped_collection)
113
+ end
114
+
115
+ # Filters the current scope with a `pluck` directive.
116
+ #
117
+ # @param args [Array] the array of arguments
118
+ #
119
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#pluck
120
+ #
121
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection] the filtered
122
+ # collection
123
+ #
124
+ # @api private
125
+ # @since 0.1.0
126
+ def pluck(*args)
127
+ _collection(super, @mapped_collection)
128
+ end
129
+
130
+ # Filters the current scope with a `has_fields` directive.
131
+ #
132
+ # @param args [Array] the array of arguments
133
+ #
134
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#has_fields
135
+ #
136
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection] the filtered
137
+ # collection
138
+ #
139
+ # @api private
140
+ # @since 0.1.0
141
+ def has_fields(*args) # rubocop:disable Style/PredicateName
142
+ _collection(super, @mapped_collection)
143
+ end
144
+
145
+ # Filters the current scope with a `limit` directive.
146
+ #
147
+ # @param args [Array] the array of arguments
148
+ #
149
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#limit
150
+ #
151
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection] the filtered
152
+ # collection
153
+ #
154
+ # @api private
155
+ # @since 0.1.0
156
+ def limit(*args)
157
+ _collection(super, @mapped_collection)
158
+ end
159
+
160
+ # Filters the current scope with an `order_by` directive.
161
+ #
162
+ # @param args [Array] the array of arguments
163
+ #
164
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#order
165
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#desc
166
+ #
167
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection] the filtered
168
+ # collection
169
+ #
170
+ # @api private
171
+ # @since 0.1.0
172
+ def order_by(*args)
173
+ _collection(super, @mapped_collection)
174
+ end
175
+
176
+ # Returns the sum of the values for the given field.
177
+ #
178
+ # @param args [Array] the array of arguments
179
+ #
180
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#sum
181
+ #
182
+ # @return [Numeric]
183
+ #
184
+ # @api private
185
+ # @since 0.1.0
186
+ def sum(*args)
187
+ _run do
188
+ super
189
+ end
190
+ end
191
+
192
+ # Returns the average of the values for the given column.
193
+ #
194
+ # @param args [Array] the array of arguments
195
+ #
196
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#avg
197
+ #
198
+ # @return [Numeric]
199
+ #
200
+ # @api private
201
+ # @since 0.1.0
202
+ def avg(*args)
203
+ _run do
204
+ super.default(nil)
205
+ end
206
+ end
207
+
208
+ # Returns the maximum value for the given field.
209
+ #
210
+ # @param args [Array] the array of arguments
211
+ #
212
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#max
213
+ #
214
+ # @return [Numeric]
215
+ #
216
+ # @api private
217
+ # @since 0.1.0
218
+ def max(field, *args)
219
+ _run do
220
+ super[field].default(nil)
221
+ end
222
+ end
223
+
224
+ # Returns the minimum value for the given field.
225
+ #
226
+ # @param args [Array] the array of arguments
227
+ #
228
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#min
229
+ #
230
+ # @return [Numeric]
231
+ #
232
+ # @api private
233
+ # @since 0.1.0
234
+ def min(field, *args)
235
+ _run do
236
+ super[field].default(nil)
237
+ end
238
+ end
239
+
240
+ # Returns a count of the documents for the current conditions.
241
+ #
242
+ # @param args [Array] the array of arguments
243
+ #
244
+ # @see Hanami::Model::Adapters::Rethinkdb::Query#count
245
+ #
246
+ # @return [Numeric]
247
+ #
248
+ # @api private
249
+ # @since 0.1.0
250
+ def count
251
+ _run do
252
+ super
253
+ end
254
+ end
255
+
256
+ # Resolves self by fetching the documents from the database and
257
+ # translating them into entities.
258
+ #
259
+ # @return [Array] the result of the query
260
+ #
261
+ # @api private
262
+ # @since 0.1.0
263
+ def to_a
264
+ _deserialize(
265
+ _run do
266
+ self
267
+ end
268
+ )
269
+ end
270
+
271
+ alias_method :execute, :to_a
272
+
273
+ private
274
+
275
+ # Serialize the given entity before to persist in the database.
276
+ #
277
+ # @return [Hash] the serialized entity
278
+ #
279
+ # @api private
280
+ # @since 0.1.0
281
+ def _serialize(entity)
282
+ @mapped_collection.serialize(entity)
283
+ end
284
+
285
+ # Deserialize a set of documents fetched from the database.
286
+ #
287
+ # @note ActiveSupport's HashWithIndifferentAccess is used to solve an
288
+ # incompatibility between Hanami::Model's use of symbols and
289
+ # RethinkDB's use of strings.
290
+ #
291
+ # @param documents [Array] a set of raw documents
292
+ #
293
+ # @api private
294
+ # @since 0.1.0
295
+ def _deserialize(documents)
296
+ @mapped_collection.deserialize(
297
+ documents.map(&:with_indifferent_access)
298
+ )
299
+ end
300
+
301
+ # Name of the identity field in database.
302
+ #
303
+ # @return [Symbol] the identity name
304
+ #
305
+ # @api private
306
+ # @since 0.2.1
307
+ def _identity
308
+ @mapped_collection.identity
309
+ end
310
+
311
+ # Returns a collection with the connection automatically included.
312
+ #
313
+ # @return [Hanami::Model::Adapters::Rethinkdb::Collection]
314
+ #
315
+ # @api private
316
+ # @since 0.1.0
317
+ def _collection(*args)
318
+ Collection.new(@connection, *args)
319
+ end
320
+
321
+ # Run the enclosed block on the database.
322
+ #
323
+ # @api private
324
+ # @since 0.1.0
325
+ def _run
326
+ yield.run(@connection)
327
+ end
328
+ end
329
+ end
330
+ end
331
+ end
332
+ end