epiphy 0.0.1 → 0.1.0

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: 3c60ab2f9d0a39156bab381f3217ad2c8fd210d8
4
- data.tar.gz: 24fde7963aa8d74479e2a90030928b7fc8fc7d89
3
+ metadata.gz: 346e101f2179b4b096e7d9e38ef7c08879598e99
4
+ data.tar.gz: fc54f4cf44e3a1e25e79d10f5ecd2e85bd0bff0c
5
5
  SHA512:
6
- metadata.gz: 1e18a93aef681e795efd164d3467f7136fe6f938bea9d08448cfe854b4a2a4a50dd4b5ea4bc46c54a18f0bd6996c902c747449dd9448a0f3fd83cf1694ab39e5
7
- data.tar.gz: f3549f8a25a32cc5bc2f5a6c565e2a081dd029653d499be1aa28743e293fa975de93c7f8b1a12b0915bb3e9d1153d5e25cbc156ada19fa2fc8c656a9c70f5b8c
6
+ metadata.gz: a8823aac0ef0a54099141567fcc3155d3289ca71d08b39b506f14ed668bb073f78d99a622d3090a804997f69370ec36841d7c256b7ff98c507fc057c3e4e100e
7
+ data.tar.gz: e6fd39cb0525b115d1fb6bfb35d094ef3f1661902f4db8bfbb5924eef21f3b74281ed71db385a19ce00bcac225ad8398ba302f8e5d49d200d1a4baa1b842bc74
data/EXAMPLE.md ADDED
@@ -0,0 +1,173 @@
1
+ # Epiphy
2
+
3
+ This is a guide that helps you to getting started with [**Epiphy**](https://github.com/kureikain/epiphy). This file is inspired by Lotus::Model
4
+
5
+ ## Gems
6
+
7
+ First of all, we need to setup a `Gemfile`.
8
+
9
+ ```ruby
10
+ source 'https://rubygems.org'
11
+
12
+ gem 'epiphy'
13
+ ```
14
+
15
+ Then we can fetch the dependencies with `bundle install`.
16
+
17
+ ## Setup
18
+
19
+ We need to feed `Epiphy` with an adapter. Adapter is a lighweight wrap
20
+ contains a RethinkDB connection and its run option.
21
+
22
+ ```
23
+ # Default connect to localhost, 28015, no auth key, use database 'test'
24
+ # by default
25
+ connection = Epiphy::Connection.create
26
+ adapter = Epiphy::Adapter::RethinkDB.new connection, 'test'
27
+ RethinkDB::Repository.configure do |r|
28
+ r.adapter = adapter
29
+ end
30
+
31
+ # Or merge them all
32
+ RethinkDB::Repository.configure do |r|
33
+ r.adapter = Epiphy::Adapter::RethinkDB.new(Epiphy::Connection.create)
34
+ end
35
+
36
+ # Or connect to a different host, use database `cms`
37
+ RethinkDB::Repository.configure do |r|
38
+ r.adapter = Epiphy::Adapter::RethinkDB.new Epiphy::Connection.create({:host => '192.168.1.2'}, 'cms')
39
+ end
40
+
41
+ ```
42
+
43
+ ## Entities
44
+
45
+ We have two entities in our application: `Author` and `Article`.
46
+ `Author` is a `Struct`, Epiphy can persist it.
47
+ `Article` has a small API concerning its publishing process.
48
+
49
+ ```ruby
50
+ Author = Struct.new(:id, :name) do
51
+ def initialize(attributes = {})
52
+ @id, @name = attributes.values_at(:id, :name)
53
+ end
54
+ end
55
+
56
+ class Article
57
+ include Epiphy::Entity
58
+ self.attributes = :author_id, :title, :comments_count, :published # id is implicit
59
+
60
+ def published?
61
+ !!published
62
+ end
63
+
64
+ def publish!
65
+ @published = true
66
+ end
67
+ end
68
+ ```
69
+
70
+ ## Repositories
71
+
72
+ In order to persist and query the entities above, we define two corresponding repositories:
73
+
74
+ ```ruby
75
+ class AuthorRepository
76
+ include Epiphy::Repository
77
+ end
78
+
79
+ class ArticleRepository
80
+ include Epiphy::Repository
81
+
82
+ def self.most_recent_by_author(author, limit = 8)
83
+ query do
84
+ where(author_id: author.id).
85
+ desc(:id).
86
+ limit(limit)
87
+ end
88
+ end
89
+
90
+ def self.most_recent_published_by_author(author, limit = 8)
91
+ most_recent_by_author(author, limit).published
92
+ end
93
+
94
+ def self.published
95
+ query do
96
+ where(published: true)
97
+ end
98
+ end
99
+
100
+ def self.drafts
101
+ exclude published
102
+ end
103
+
104
+ def self.rank
105
+ published.desc(:comments_count)
106
+ end
107
+
108
+ def self.best_article_ever
109
+ rank.limit(1).first
110
+ end
111
+
112
+ def self.comments_average
113
+ query.average(:comments_count)
114
+ end
115
+ end
116
+ ```
117
+
118
+ ## Persist
119
+
120
+ Let's instantiate and persist some objects for our example:
121
+
122
+ ```ruby
123
+ author = Author.new(name: 'Luca')
124
+ AuthorRepository.create(author)
125
+
126
+ articles = [
127
+ Article.new(title: 'Announcing Epiphy', author_id: author.id, comments_count: 123, published: true),
128
+ Article.new(title: 'Introducing Epiphy::Router', author_id: author.id, comments_count: 63, published: true),
129
+ Article.new(title: 'Introducing Epiphy::Controller', author_id: author.id, comments_count: 82, published: true),
130
+ Article.new(title: 'Introducing Epiphy', author_id: author.id)
131
+ ]
132
+
133
+ articles.each do |article|
134
+ ArticleRepository.create(article)
135
+ end
136
+ ```
137
+
138
+ ## Query
139
+
140
+ We can use repositories to query the database and return the entities we're looking for:
141
+
142
+ ```ruby
143
+ ArticleRepository.first # => return the first article
144
+ ArticleRepository.last # => return the last article
145
+
146
+ ArticleRepository.published # => return all the published articles
147
+ ArticleRepository.drafts # => return all the drafts
148
+
149
+ ArticleRepository.rank # => all the published articles, sorted by popularity
150
+
151
+ ArticleRepository.best_article_ever # => the most commented article
152
+
153
+ ArticleRepository.comments_average # => calculates the average of comments across all the published articles.
154
+
155
+ ArticleRepository.most_recent_by_author(author) # => most recent articles by an author (drafts and published).
156
+ ArticleRepository.most_recent_published_by_author(author) # => most recent published articles by an author
157
+ ```
158
+
159
+ ## Business logic
160
+
161
+ As we've seen above, `Article` implements an API for publishing.
162
+ We're gonna use that logic to alter the state of an article (from draft to published) and then we use the repository to persist this new state.
163
+
164
+ ```ruby
165
+ article = ArticleRepository.drafts.first
166
+
167
+ article.published? # => false
168
+ article.publish!
169
+
170
+ article.published? # => true
171
+
172
+ ArticleRepository.update(article)
173
+ ```
@@ -1,5 +1,5 @@
1
1
  require 'epiphy/adapter/error'
2
- #require 'epiphy/adapter/helper'
2
+
3
3
  module Epiphy
4
4
  module Adapter
5
5
  class Rethinkdb
@@ -102,6 +102,7 @@ module Epiphy
102
102
  raise ArgumentError, 'Missing query block' unless block_given?
103
103
  if block_given?
104
104
  rql = get_table(table, database)
105
+ @current_rql = rql
105
106
  rql = yield(rql, r)
106
107
  end
107
108
  rql.run(@connection)
@@ -125,9 +126,15 @@ module Epiphy
125
126
  end
126
127
 
127
128
  # Insert a document.
129
+ #
130
+ # When the ID is already existed, we simply return the ID if insert
131
+ # succesful. Or, the generated ID will be returned.
132
+ #
128
133
  # @param collection [Symbol the target collection
129
134
  # @param entity [#id, #id=] the entity to create
130
135
  # @return [Object] the entity
136
+ #
137
+ # @raise
131
138
  #
132
139
  # @api private
133
140
  # @since 0.0.1
@@ -136,12 +143,17 @@ module Epiphy
136
143
  result = query table: collection do |r|
137
144
  r.insert(entity)
138
145
  end
139
- rescue
140
- return false
146
+ rescue RethinkDB::RqlRuntimeError => e
147
+ raise e
141
148
  end
142
149
 
143
150
  if result["inserted"]==1
144
- result["generated_keys"].first
151
+ return entity["id"] if result["generated_keys"].nil?
152
+ result["generated_keys"].first
153
+ else
154
+ if result['first_error'].include? 'Duplicate primary key'
155
+ raise Epiphy::Model::EntityExisted, 'Duplicate primary key'
156
+ end
145
157
  end
146
158
  end
147
159
 
@@ -179,8 +191,31 @@ module Epiphy
179
191
  query table: collection do |r|
180
192
  r
181
193
  end
182
- rescue
183
- return false
194
+ rescue RethinkDB::RqlRuntimeError => e
195
+ raise Epiphy::Model::RuntimeError, e.message
196
+ rescue Exception =>e
197
+ raise Epiphy::Model::RuntimeError, e.message
198
+ end
199
+ end
200
+
201
+ # Count entity in table
202
+ #
203
+ # @param collection [Symbol] the target collection (it must be mapped).
204
+ #
205
+ # @return [Integer] How many record?
206
+ #
207
+ # @api private
208
+ # @since 0.2.0
209
+ def count(collection)
210
+ # TODO consider to make this lazy (aka remove #all)
211
+ begin
212
+ query table: collection do |r|
213
+ r.count
214
+ end
215
+ rescue RethinkDB::RqlRuntimeError => e
216
+ raise Epiphy::Model::RuntimeError, e.message
217
+ rescue Exception =>e
218
+ raise Epiphy::Model::RuntimeError, e.message
184
219
  end
185
220
  end
186
221
 
@@ -243,8 +278,8 @@ module Epiphy
243
278
  return result['deleted']
244
279
  end
245
280
  return false
246
- rescue
247
- return false
281
+ rescue RethinkDB::RqlRuntimeError => e
282
+ raise Epiphy::Model::RuntimeError, e.message
248
283
  end
249
284
  end
250
285
 
@@ -256,10 +291,14 @@ module Epiphy
256
291
  #
257
292
  # @api private
258
293
  # @since 0.1.0
259
- def first(collection)
260
- _first(
261
- query(collection).asc(_identity(collection))
262
- )
294
+ def first(collection, order_by: nil)
295
+ begin
296
+ query table: collection do |q,r|
297
+ q.order_by(r.asc(order_by)).nth(0)
298
+ end
299
+ rescue RethinkDB::RqlRuntimeError => e
300
+ return nil
301
+ end
263
302
  end
264
303
 
265
304
  # Returns the last record in the given collection.
@@ -270,21 +309,18 @@ module Epiphy
270
309
  #
271
310
  # @api private
272
311
  # @since 0.1.0
273
- def last(collection)
274
- _first(
275
- query(collection).desc(_identity(collection))
276
- )
312
+ def last(collection, order_by: nil)
313
+ begin
314
+ query table: collection do |q, r|
315
+ q.order_by(r.desc(order_by)).nth(0)
316
+ end
317
+ rescue RethinkDB::RqlRuntimeError => e
318
+ return nil
319
+ end
320
+
277
321
  end
278
322
 
279
323
  private
280
- def _collection(name)
281
- raise NotImplementedError
282
- end
283
-
284
- def _mapped_collection(name)
285
- @mapper.collection(name)
286
- end
287
-
288
324
  def _find(collection, id)
289
325
  identity = _identity(collection)
290
326
  query(collection).where(identity => _id(collection, identity, id))
@@ -0,0 +1,14 @@
1
+ module Epiphy
2
+ module Entity
3
+
4
+ # Add created_at and updated_at field to an entity.
5
+ #
6
+ #
7
+ module Timestamp
8
+ def self.included(base)
9
+ base.send :attr_accessor, :_ts
10
+ end
11
+ end
12
+
13
+ end
14
+ end
data/lib/epiphy/model.rb CHANGED
@@ -9,6 +9,10 @@ module Epiphy
9
9
  #
10
10
  # @since 0.1.0
11
11
  module Model
12
+
13
+ class RuntimeError < RethinkDB::RqlRuntimeError
14
+
15
+ end
12
16
  # Error for not found entity
13
17
  #
14
18
  # @since 0.1.0
@@ -33,5 +37,9 @@ module Epiphy
33
37
  # @see epiphy::Repository.update
34
38
  class NonPersistedEntityError < ::StandardError
35
39
  end
40
+
41
+ class EntityExisted < ::StandardError
42
+
43
+ end
36
44
  end
37
45
  end
@@ -1,6 +1,7 @@
1
1
  require 'lotus/utils/class_attribute'
2
2
  require 'epiphy/repository/configuration'
3
3
  require 'epiphy/repository/cursor'
4
+ require 'epiphy/repository/helper'
4
5
 
5
6
  module Epiphy
6
7
  # Mediates between the entities and the persistence layer, by offering an API
@@ -215,6 +216,7 @@ module Epiphy
215
216
  end
216
217
 
217
218
  module ClassMethods
219
+ include Epiphy::Repository::Helper
218
220
  # Assigns an adapter.
219
221
  #
220
222
  # Epiphy::Repository is shipped with an adapters:
@@ -289,7 +291,8 @@ module Epiphy
289
291
  # Creates a record in the database for the given entity.
290
292
  # It assigns the `id` attribute, in case of success.
291
293
  #
292
- # If already persisted (`id` present) it does nothing.
294
+ # If already persisted (`id` present), it will try to insert use that id
295
+ # and will raise an error if the `id` is already exist
293
296
  #
294
297
  # @param entity [#id,#id=] the entity to create
295
298
  #
@@ -314,10 +317,16 @@ module Epiphy
314
317
  #
315
318
  # ArticleRepository.create(article) # no-op
316
319
  def create(entity)
317
- unless entity.id
320
+ #unless entity.id
321
+ begin
318
322
  result = @adapter.create(collection, to_document(entity))
319
323
  entity.id = result
324
+ rescue Epiphy::Model::EntityExisted => e
325
+ raise e
326
+ rescue RethinkDB::RqlRuntimeError => e
327
+ raise Epiphy::Model::RuntimeError, e.message
320
328
  end
329
+ #end
321
330
  end
322
331
 
323
332
  # Updates a record in the database corresponding to the given entity.
@@ -504,8 +513,13 @@ module Epiphy
504
513
  # end
505
514
  #
506
515
  # ArticleRepository.first # => nil
507
- def first
508
- @adapter.first(collection)
516
+ def first(order_by=:id)
517
+ result = @adapter.first(collection, order_by: order_by)
518
+ if result
519
+ to_entity result
520
+ else
521
+ result
522
+ end
509
523
  end
510
524
 
511
525
  # Returns the last entity in the database.
@@ -533,8 +547,12 @@ module Epiphy
533
547
  # end
534
548
  #
535
549
  # ArticleRepository.last # => nil
536
- def last
537
- @adapter.last(collection)
550
+ def last(order_by=:id)
551
+ if result = @adapter.last(collection, order_by: order_by)
552
+ to_entity result
553
+ else
554
+ nil
555
+ end
538
556
  end
539
557
 
540
558
  # Deletes all the records from the current collection.
@@ -553,22 +571,16 @@ module Epiphy
553
571
  # ArticleRepository.clear # deletes all the records
554
572
  def clear
555
573
  @adapter.clear(collection)
556
- end
574
+ end
557
575
 
558
- # Create a collection storage in database.
576
+ # Count the entity in this collection
559
577
  #
560
- def create_collection
561
- query do |r|
562
- r.table_create(self.collection)
563
- end
564
- end
565
-
566
- # Drop a collection storage in database
567
- #
568
- def drop_collection
569
- query do |r|
570
- r.table_drop(self.collection)
571
- end
578
+ # @param void
579
+ # @return Interget
580
+ # @api public
581
+ # @since 0.2.0
582
+ def count
583
+ @adapter.count(collection)
572
584
  end
573
585
 
574
586
  private
@@ -585,27 +597,34 @@ module Epiphy
585
597
  # The returned query SHOULD refer to the entire collection by default.
586
598
  #
587
599
  # Queries can be reused and combined together. See the example below.
588
- # IMPORTANT: This feature works only with the Sql adapter.
589
600
  #
590
601
  # A repository is storage independent.
591
602
  # All the queries are delegated to the current adapter, which is
592
603
  # responsible to implement a querying API.
593
604
  #
594
- # Epiphy::Model is shipped with two adapters:
605
+ # Epiphy::Model is shipped with adapter:
595
606
  #
596
- # * SqlAdapter, which yields a Epiphy::Model::Adapters::Sql::Query
597
- # * MemoryAdapter, which yields a Epiphy::Model::Adapters::Memory::Query
607
+ # * RethinkDB: which yields a RethinkDB::ReQL class.
598
608
  #
599
- # @param blk [Proc] a block of code that is executed in the context of a
600
- # query
609
+ # By default, all return items will be convert into its entity. The
610
+ # behavious can change by alter `to_entity` parameter
601
611
  #
612
+ # @param to_entity [Boolean][Optional] to convert the result back to a
613
+ # entity class or not.
614
+ #
615
+ # @param blk [Proc] a block of code that is executed in the context of a
616
+ # query.
617
+ # The block will be passed two parameters. First parameter is the `reql`
618
+ # which is building. the second parameter is th `r` top name space of
619
+ # RethinkDB. By doing this, Repository doesn't have to include
620
+ # RethinkDB::Shortcuts
621
+ #
602
622
  # @return a query, the type depends on the current adapter
603
623
  #
604
624
  # @api public
605
625
  # @since 0.1.0
606
626
  #
607
- # @see Epiphy::Model::Adapters::Sql::Query
608
- # @see Epiphy::Model::Adapters::Memory::Query
627
+ # @see Epiphy::Adapters::Rethinkdb
609
628
  #
610
629
  # @example
611
630
  # require 'epiphy/model'
@@ -646,9 +665,27 @@ module Epiphy
646
665
  # query.average(:comments_count)
647
666
  # end
648
667
  # end
649
- def query(&blk)
650
- @adapter.query(collection, self, &blk)
668
+ def query(to_entity: true, &blk)
669
+ result = @adapter.query(table: collection, &blk)
670
+ require 'pp'
671
+ if result.is_a? RethinkDB::Cursor
672
+ return Epiphy::Repository::Cursor.new result do |item|
673
+ to_entity(item)
674
+ end
675
+ end
676
+
677
+ if result.is_a? Array
678
+ result.map! do |item|
679
+ to_entity(item)
680
+ end
681
+ end
682
+
683
+ if result.is_a? Hash
684
+ return to_entity(result)
685
+ end
686
+ result
651
687
  end
688
+
652
689
 
653
690
  # Negates the filtering conditions of a given query with the logical
654
691
  # opposite operator.
@@ -0,0 +1,28 @@
1
+ module Epiphy
2
+ module Repository
3
+ module Helper
4
+
5
+ # Find the first record matching the
6
+ #
7
+ # @param Keyword argument [field_name: value]
8
+ # @return Entity [Object]
9
+ # @raise Epiphy::Model::EntityNotFound if not found
10
+ #
11
+ # @api public
12
+ # @since 0.2.0
13
+ def find_by(**option)
14
+ begin
15
+ query do |r|
16
+ r.filter(option).nth(0)
17
+ end
18
+ rescue RethinkDB::RqlRuntimeError => e
19
+ #raise RethinkDB::RqlRuntimeError
20
+ raise Epiphy::Model::EntityNotFound if e.message.include?("Index out of bounds")
21
+ end
22
+ end
23
+
24
+ #private :where, :desc#, :exlude
25
+ end
26
+ end
27
+ end
28
+
@@ -0,0 +1,19 @@
1
+ module Epiphy
2
+ module Schema
3
+ # Create a collection storage in database.
4
+ #
5
+ def create_collection
6
+ query do |r|
7
+ r.table_create(self.collection)
8
+ end
9
+ end
10
+
11
+ # Drop a collection storage in database
12
+ #
13
+ def drop_collection
14
+ query do |r|
15
+ r.table_drop(self.collection)
16
+ end
17
+ end
18
+ end
19
+ end
@@ -2,5 +2,5 @@ module Epiphy
2
2
  # Defines the version
3
3
  #
4
4
  # @since 0.0.1
5
- VERSION = '0.0.1'.freeze
5
+ VERSION = '0.1.0'.freeze
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: epiphy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vinh
@@ -59,18 +59,20 @@ executables: []
59
59
  extensions: []
60
60
  extra_rdoc_files: []
61
61
  files:
62
+ - EXAMPLE.md
62
63
  - README.md
63
64
  - lib/epiphy.rb
64
65
  - lib/epiphy/adapter/error.rb
65
- - lib/epiphy/adapter/helper.rb
66
- - lib/epiphy/adapter/model.rb
67
66
  - lib/epiphy/adapter/rethinkdb.rb
68
67
  - lib/epiphy/connection.rb
69
68
  - lib/epiphy/entity.rb
69
+ - lib/epiphy/entity/timestamp.rb
70
70
  - lib/epiphy/model.rb
71
71
  - lib/epiphy/repository.rb
72
72
  - lib/epiphy/repository/configuration.rb
73
73
  - lib/epiphy/repository/cursor.rb
74
+ - lib/epiphy/repository/helper.rb
75
+ - lib/epiphy/scheme.rb
74
76
  - lib/epiphy/version.rb
75
77
  homepage: http://rubygems.org/gems/hola
76
78
  licenses:
@@ -1,114 +0,0 @@
1
- module Epiphy
2
- module Adapter
3
- class Rethinkdb
4
- # RethinkDB method related. Should be in its helper
5
- def insert_object
6
- get_table.insert(
7
- safe_params.merge(
8
- id: params[:id],
9
- created_at: Time.now,
10
- updated_at: Time.now
11
- ).merge(parents)
12
- ).run(@connection)
13
- :created
14
- end
15
-
16
- def update_object
17
- get_table.update(
18
- safe_params.merge(
19
- id: params[:id],
20
- updated_at: Time.now
21
- )
22
- ).run(@connection)
23
- :ok
24
- end
25
-
26
- def replace_object
27
- get_table.replace(
28
- safe_params.merge(
29
- id: params[:id],
30
- created_at: Time.now,
31
- updated_at: Time.now
32
- ).merge(parents)
33
- ).run(@connection)
34
- :ok
35
- end
36
-
37
- def delete_object
38
- get_table.get(params[:id]).delete(
39
- :durability => "hard", :return_vals => false
40
- ).run(@connection)
41
- :no_content
42
- end
43
-
44
- def sort(qry)
45
- ordering = params[:sort].split(",").map do |attr|
46
- if attr[0] == "-"
47
- r.desc(attr[1..-1].to_sym)
48
- else
49
- r.asc(attr.to_sym)
50
- end
51
- end
52
-
53
- qry.order_by(*ordering)
54
- end
55
-
56
- def select(qry)
57
- qry = qry.get_all(*params[:ids].split(",")) if params[:ids]
58
- qry
59
- end
60
-
61
- def parents
62
- params.select {|k,v| k.match(/\A[a-z0-9_]+_id\z/i) }.compact
63
- end
64
-
65
- def filter(qry)
66
- parents.empty? ? qry : qry.filter(parents)
67
- end
68
-
69
- def attrs
70
- [ :id ]
71
- end
72
-
73
- def get_range(qry)
74
- begin
75
- rhdr = request.headers[:HTTP_RANGE].split("=")
76
-
77
- if rhdr[0] == collection
78
- qry = qry[Range.new(*rhdr[1].split("-").map(&:to_i))]
79
- end
80
- rescue Exception => e
81
- puts e.message
82
- raise Exception.new(:bad_request)
83
- end
84
- qry
85
- end
86
-
87
- def get_records
88
- qry = get_table
89
- qry = sort(qry) if params[:sort]
90
-
91
- fields = if params[:fields]
92
- params[:fields].split(",").map {|f| f.to_sym }.select do |field|
93
- attrs.include? field
94
- end
95
- else
96
- attrs
97
- end
98
-
99
- qry = filter(select(qry)).pluck(fields)
100
- qry = get_range(qry) if request.headers[:HTTP_RANGE]
101
-
102
- qry.run(@connection).map do |record|
103
- record.merge(href: some_url(record["id"]))
104
- end
105
- end
106
-
107
- def get_object
108
- get_table.filter(parents.merge({id: params[:id]})).pluck(attrs).run(@connection).first
109
- end
110
-
111
- end
112
- end
113
- end
114
-
@@ -1,99 +0,0 @@
1
- require 'errors'
2
-
3
- class Rethink
4
- include RethinkDB::Shortcuts
5
- include RethinkdbHelper
6
- include Errors
7
-
8
- def initialize
9
- create_connect_if_need
10
- @r = @@r.table(self.class.name.downcase)
11
- end
12
-
13
- def all
14
- self
15
- end
16
-
17
- # Get a single element by primary key
18
- def single(id)
19
- @r = @r.get(id)
20
- self
21
- end
22
-
23
- # Return raw RethinkDB object
24
- def raw_query
25
- @r
26
- end
27
-
28
- def reset
29
- @r = @@r.table self.class.name.downcase
30
- end
31
-
32
- # Run a RQL
33
- def get(r=nil)
34
- if r.nil?
35
- r = @r
36
- end
37
- r.run(@@rdb_connection)
38
- end
39
-
40
- [:update, "get_all", :limit, :order_by, :slice, :count, :filter].each do |name|
41
- define_method(name) do |*arg, &block|
42
- @r = @r.send(name, *arg, &block)
43
- self
44
- end
45
- end
46
-
47
- # Command work ona single object
48
- #{:destroy => :delete}.each do |public_name, name|
49
- #define_method(public_name) do |*arg, &block|
50
- #r = @@r.table self.class.name.downcase
51
- #r.get(*arg)
52
- #r.send(name, *arg, &block)
53
- #r.run @@rdb_connection
54
- #end
55
- #end
56
-
57
- def destroy(id)
58
- r = @@r.table self.class.name.downcase
59
- r.get(id)
60
- .delete()
61
- .run(@@rdb_connection)
62
- end
63
-
64
- # Validation
65
- def self.validate(args)
66
- if args.has_key? :errors
67
- raise ValidationError.new('Bad request', args[:errors])
68
- end
69
-
70
- args
71
- end
72
-
73
- def self.validate_present(args, *keys)
74
- for k in keys
75
- unless args.has_key?(k) and args[k].present?
76
- args[:errors] ||= {}
77
- args[:errors][k] ||= []
78
- args[:errors][k] << "can't be blank."
79
- end
80
- end
81
- args
82
- end
83
-
84
- def self.validate_email(args)
85
- if args.has_key? :email
86
- args[:email].downcase!
87
-
88
- unless args[:email].present? and
89
- args[:email].match EMAIL_REGEX
90
-
91
- args[:errors] ||= {}
92
- args[:errors][:email] ||= []
93
- args[:errors][:email] << "is invalid."
94
- end
95
- end
96
- args
97
- end
98
- end
99
-