guacamole 0.1.0 → 0.2.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: 65f6f1c73821edaf59fae8fea0554389f9426a9c
4
- data.tar.gz: 4eb7f2737b833d830680804d0681b39612e4e27d
3
+ metadata.gz: 2522fab030888fc0ee9601790aabd2134c6f32dc
4
+ data.tar.gz: 400562752f398045f858bbe9edf3c40d621fcc4c
5
5
  SHA512:
6
- metadata.gz: 3d73b44a1c7111fe19d662f3ede415f2b574d1502b90644050e029ae330869ceec50b32d621d8863c8b45f0ded991997a6753701cfeb4ef976774f94ab9ea63d
7
- data.tar.gz: 95bed05003e2f5a2796b7e53b03a9c7620e2a325b3b47697be15e451c8be813ecd1c45eaffb0c4c1113fa0777e2d1d2146dded64698bdb7638252e0db265f298
6
+ metadata.gz: 8c1b397cab789fee57a5a98eb76e46f9c422b466747cd9be272591cc66aee47829253c484ffd500e9fe0755fc255d43df55742546404ecf618a536f27538ab18
7
+ data.tar.gz: 19f830e89f65c7c4c8404a4ce49559920a6a3eac6e0bbe0eab34671f944a49bc0412d530aaad984fb0fd5cba7bd77ffbbd5c6dc8d1bc3e1248a5605972e0e8c3
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- ruby-2.0.0-p353
1
+ ruby-2.1.2
data/.travis.yml CHANGED
@@ -5,12 +5,13 @@ before_script:
5
5
  rvm:
6
6
  - 1.9.3
7
7
  - 2.0.0
8
+ - 2.1.2
8
9
  - jruby-19mode
9
10
  - jruby-head
10
11
  - rbx-19mode
11
12
  - ruby-head
12
13
  env:
13
- - ARANGODB_DISABLE_AUTHENTIFICATION=true VERSION=1.4.0-beta2
14
+ - ARANGODB_DISABLE_AUTHENTIFICATION=true VERSION=2.0
14
15
  matrix:
15
16
  allow_failures:
16
17
  - rvm: jruby-19mode
data/CHANGELOG.md ADDED
@@ -0,0 +1,39 @@
1
+ ## Version 0.2.0
2
+
3
+ **Codename: Into the Storm**
4
+
5
+ This is a quick follow up release to fix some bugs and to introduce some experimental AQL support to get people better started with Guacamole and ArangoDB.
6
+
7
+ Notable changes are:
8
+
9
+ * Improvements to the README (thanks to @janpieper, @tisba, @ujjwalt)
10
+ * Fix the loading of ActiveSupport (#57, #59)
11
+ * Updated to Ashikawa::Core 0.11.0 (#60)
12
+ * Automatically add `app/collections` to the autoload path (#52)
13
+ * Build against Ruby 2.1.2 (#56)
14
+ * Add an experimental support for AQL (#51)
15
+
16
+ **Note**: As of today release name will be taken from Blind Guardian song titles \m/
17
+
18
+
19
+ ## Version 0.1.0
20
+
21
+ **Codename: The Dawn**
22
+
23
+ This is the very first release of Guacamole. Please be aware that is alpha software and we don't recommend it to be used in production systems. It is meant to be used in prototypes to help people getting started with ArangoDB in the context of a Rails application. We love to hear about your feedback and impressions on this project.
24
+
25
+ The main features we added in this release:
26
+
27
+ * Added an Identity Map
28
+ * Added lazy associations
29
+ * Fixed hamster dependency
30
+ * Added database related rake tasks
31
+ * Added basic Rails generators
32
+ * Significant improvements to the README, including a getting started guide
33
+ * Using the latest Ashikawa::Core version
34
+ * Some internal improvement to optimize the development process
35
+
36
+
37
+ ## Version 0.0.1
38
+
39
+ Merely a release but a proof of concept.
data/README.md CHANGED
@@ -11,7 +11,7 @@ Guacamole is an Object Document Mapper (ODM) for the multi-model NoSQL database
11
11
  * Reflect the nature of NoSQL in general and ArangoDB in particular
12
12
  * Focus on long-term maintainability of your application
13
13
 
14
- While the first two points don't need any further explanation we want to lay out the motivation behind the last point: 'Ease of use' is very important to us, but we made some fundamental decisions which will cause a stepper learning curve than other libraries, notably ActiveRecord. If you have a traditional Rails background you will find some things quite different. We decided to go this direction, because we think it better suites the features of ArangoDB. Applying the semantics of a different environment maybe helps with the first steps but will become problematic if you further advance in your understanding of the possibilities.
14
+ While the first two points don't need any further explanation we want to lay out the motivation behind the last point: 'Ease of use' is very important to us, but we made some fundamental decisions which will cause a steeper learning curve than other libraries, notably ActiveRecord. If you have a traditional Rails background you will find some things quite different. We decided to go this direction, because we think it better suites the features of ArangoDB. Applying the semantics of a different environment may help with the first steps but will become problematic if you further advance in your understanding of the possibilities.
15
15
 
16
16
  That said we still think we provide a sufficient API that is quite easy to get hold of. It is just a bit different from what you were doing with ActiveRecord.
17
17
 
@@ -19,7 +19,7 @@ For a high-level introduction you can also refer to [this presentation](https://
19
19
 
20
20
  ## Getting started (with a fresh Rails application)
21
21
 
22
- Since Guacamole is in an alpha state we suggest you create a new Rails application to play around with it. We don't recommend adding it to a production application.
22
+ Since Guacamole is in an alpha state we suggest you to create a new Rails application to play around with it. We don't recommend adding it to a production application.
23
23
 
24
24
  First of all create your shiny new application, without ActiveRecord of course:
25
25
 
@@ -71,11 +71,11 @@ Now where everything is set up we can go ahead and create our application's logi
71
71
 
72
72
  ## Usage
73
73
 
74
- One of the key features of Guacamole is the implementation of the [Data Mapper Patter](http://martinfowler.com/eaaCatalog/dataMapper.html). This brings a lot of good things along, like
74
+ One of the key features of Guacamole is the implementation of the [Data Mapper Pattern](http://martinfowler.com/eaaCatalog/dataMapper.html). This brings a lot of good things along, like
75
75
 
76
- * Improved testability
77
- * Separation of Concern and
78
- * Easier to support databasefeatures like embedded objects
76
+ * improved testability
77
+ * separation of concerns and
78
+ * easier to support database features like embedded objects
79
79
 
80
80
  The gist of the pattern is you have two classes where you would have one when you use ActiveRecord: A `Collection` and a `Model`. The `Collection` is responsible for getting data from and writing data to the database. The `Model` represents the domain logic (i.e. attributes) and has no idea what a database is. Due to this you could far easier test the domain logic without a database dependency. But you have always two (or more) classes around. The following will introduce you to both those classes.
81
81
 
@@ -99,7 +99,7 @@ class Pony
99
99
  end
100
100
  ```
101
101
 
102
- Since the database doesn't know anything about a schema we must define the attributes in the model class itself. At the same time this has the advantage to open the model class and see what attributes it has. An attribute is defined with the `attribute` class method. We use [Virtus](https://github.com/solnic/virtus) for this purpose. Basically you add give the attribute a name and a type. The type have to be the actual class and **not** a string representation of the class. You could even define collection classes:
102
+ Since the database doesn't know anything about a schema we must define the attributes in the model class itself. At the same time this has the advantage to open the model class and see what attributes it has. An attribute is defined with the `attribute` class method. We use [Virtus](https://github.com/solnic/virtus) for this purpose. Basically you give the attribute a name and a type. The type have to be the actual class and **not** a string representation of the class. You could even define collection classes:
103
103
 
104
104
  ```ruby
105
105
  class Pony
@@ -109,7 +109,7 @@ class Pony
109
109
  end
110
110
  ```
111
111
 
112
- For further reference what is possible please refer to the [Virtus documentation](http://rubydoc.info/gems/virtus/1.0.2/frames). One thing to add here, whenever you assign a value to an attribute Virtus will perform a type coercion:
112
+ For further reference what is possible please refer to the [Virtus documentation](http://rubydoc.info/gems/virtus/1.0.2/frames). One thing to note here: Whenever you assign a value to an attribute Virtus will perform a type coercion:
113
113
 
114
114
  ```ruby
115
115
  pinkie_pie = Pony.new
@@ -121,11 +121,11 @@ pinkie_pie.type = "Earthpony"
121
121
 
122
122
  #### Timestamps
123
123
 
124
- We will automatically add time stamp columns to all models when you include `Guacamole::Model`. We eventually will make this configurable, but for now it is not.
124
+ We will automatically add both a `created_at` and an `updated_at` attribute to all your models. Both will hold a `DateTime` and will be populated on creating or updating the model in the database.
125
125
 
126
126
  #### The ID of a model
127
127
 
128
- In ArangoDB a document has three internal fields: `_id`, `_key` and `_rev`. For a detailed explanation how these three work together please refer to the [ArangoDB documentation](https://www.arangodb.org/manuals/2/HandlingDocuments.html#HandlingDocumentsIntro). Within Guacamole we will always you the `_key` because it is enough the identify any document within a collection. Both the `_key` and `_rev` attribute are available through the `Guacamole::Model#key` and `Guacamole::Model#rev` attribute. You don't have to do anything for this, we will take care of this for you.
128
+ In ArangoDB a document has three internal fields: `_id`, `_key` and `_rev`. For a detailed explanation how these three work together please refer to the [ArangoDB documentation](https://www.arangodb.org/manuals/2/HandlingDocuments.html#HandlingDocumentsIntro). Within Guacamole we will always use the `_key` because it is enough the identify any document within a collection. Both the `_key` and `_rev` attribute are available through the `Guacamole::Model#key` and `Guacamole::Model#rev` attribute. You don't have to do anything for this, we will take care of this for you.
129
129
 
130
130
  Additionally you will find an `id` method on you models. This is just an alias for `key`. This was added for `ActiveModel::Conversion` compliance. You **should always** use `key`.
131
131
 
@@ -175,7 +175,7 @@ Currently your options what you can do with a collection are quire limited. We w
175
175
  * Mapping embedded models
176
176
  * Realizing basic associations
177
177
 
178
- For all the mapping related parts you don't have any configuration options yet, but have to stick with the conventions. Obviously this will change in the future but for now there more important parts to work on. Before we dig deeper into the mapping of embedded or associated models let us look at the CRUD functionality.
178
+ For all the mapping related parts you don't have any configuration options yet, but have to stick with the conventions. Obviously this will change in the future but for now there are more important parts to work on. Before we dig deeper into the mapping of embedded or associated models let us look at the CRUD functionality.
179
179
 
180
180
  #### Create models
181
181
 
@@ -235,7 +235,7 @@ We're well aware this is not sufficient for building sophisticated applications.
235
235
 
236
236
  ### Mapping
237
237
 
238
- As the name "Data Mapper" suggests there is some sort of mapping going on behind the scenes. The mapping relates to the process of _mapping_ documents from the database to the domain models.
238
+ As the name "Data Mapper" suggests there is some sort of mapping going on behind the scenes. The mapping relates to the process of _mapping_ documents from the database to the domain models.
239
239
 
240
240
  The `Collection` class will lookup the appropriate `Model` class based on its own name (i.e.: the `PoniesCollection` will look for a `Pony` class). Currently there is no option to configure this so you're stuck with our conventions (for now):
241
241
 
@@ -254,15 +254,24 @@ Without any configuration we will just map the attributes present in your domain
254
254
  }
255
255
  ```
256
256
 
257
- When we receive this document and map it against the above mentioned model there will be no `occupation` attribute be present:
257
+ When we receive this document and map it against the `Pony` model there won't be a `occupation` attribute:
258
258
 
259
259
  ```ruby
260
+ class Pony
261
+ include Guacamole::Model
262
+
263
+ attribute :name, String
264
+ attribute :color, String
265
+ end
266
+
260
267
  pony = PoniesCollection.by_key "303"
268
+ pony.color
269
+ # => 'green'
261
270
  pony.occupation
262
271
  # => NoMethodError: undefined method `occupation' for #<Pony:0x00000105fc77f8>
263
272
  ```
264
273
 
265
- Currently there is not option to change the mapping of attributes. If you want to map more or less attributes you should create another model for that purpose.
274
+ Currently there is no option to change the mapping of attributes. If you want to map more or less attributes you should create another model for that purpose.
266
275
 
267
276
  #### Associations
268
277
 
@@ -393,7 +402,7 @@ Guacamole is a very young project. A lot of stuff is missing but still, if you w
393
402
 
394
403
  Currently we're not providing any testing helper, thus you need to make sure to cleanup the database yourself before each run. You can look at the [`spec/acceptance/spec_helper.rb`](https://github.com/triAGENS/guacamole/blob/master/spec/acceptance/spec_helper.rb) of Guacamole for inspiration of how to do that.
395
404
 
396
- For test data generation we're using the awesome [Fabrication gem](http://www.fabricationgem.org/). Again you find some usage examples in under Guacamole's own acceptance tests. We didn't tested Factory Girl yet, but it eventually will work, too.
405
+ For test data generation we're using the awesome [Fabrication gem](http://www.fabricationgem.org/). Again you find some usage examples in Guacamole's own acceptance tests. We didn't tested Factory Girl yet, but it eventually will work, too.
397
406
 
398
407
  ### Authentication
399
408
 
@@ -415,6 +424,26 @@ While there are a lot of open issues we would like to present you a high level o
415
424
  * An example Rails application to be used as both an acceptance test suite and a head start for Guacamole and ArangoDB
416
425
  * An AQL query builder
417
426
 
427
+ ### Experimental AQL Support
428
+
429
+ As mentioned before we're working on [something more sophisticated to support AQL](https://github.com/moonglum/brazil/issues/8). But this will not be finished any time soon. Meanwhile you could play with the experimental AQL support:
430
+
431
+ ```ruby
432
+ config.guacamole.experimental_features = [:aql_support]
433
+ ```
434
+
435
+ After that you can perform very basic queries like this one:
436
+
437
+ ```ruby
438
+ PoniesCollection.by_aql('FILTER pony.name == @name', name: 'Rainbow Dash')
439
+ ```
440
+
441
+ The result of this will a correctly mapped Array of `Pony` models.
442
+
443
+ **Note**: Please use only this form to pass parameters into a query. Using string interpolation will leave you vulnerable to AQL-injections.
444
+
445
+ For more information about usage please refer to the RDoc and the code.
446
+
418
447
  ## Issues or Questions
419
448
 
420
449
  If you find a bug in this gem, please report it on [our tracker](https://github.com/triAGENS/guacamole/issues). We use [Waffle.io](https://waffle.io/triagens/guacamole) to manage the tickets – go there to see the current status of the ticket. If you have a question, just contact us via the [mailing list](https://groups.google.com/forum/?fromgroups#!forum/ashikawa) – we are happy to help you :smile:
data/config/reek.yml CHANGED
@@ -22,7 +22,6 @@ DuplicateMethodCall:
22
22
  exclude:
23
23
  - Guacamole::DocumentModelMapper#document_to_model
24
24
  - Guacamole::DocumentModelMapper#model_to_document
25
- - Guacamole::Configuration#_add_missing_methods_to_database
26
25
  max_calls: 1
27
26
  allow_calls: []
28
27
  FeatureEnvy:
@@ -34,7 +33,8 @@ IrresponsibleModule:
34
33
  - - !ruby/regexp /Generators/
35
34
  LongParameterList:
36
35
  enabled: true
37
- exclude: []
36
+ exclude:
37
+ - Guacamole::Collection::ClassMethods#by_aql
38
38
  max_params: 2
39
39
  overrides:
40
40
  initialize:
@@ -45,8 +45,7 @@ LongYieldList:
45
45
  max_params: 2
46
46
  NestedIterators:
47
47
  enabled: true
48
- exclude:
49
- - Guacamole::Configuration#_add_missing_methods_to_database
48
+ exclude: []
50
49
  max_allowed_nesting: 2
51
50
  ignore_iterators: []
52
51
  NilCheck:
@@ -64,7 +63,7 @@ TooManyInstanceVariables:
64
63
  TooManyMethods:
65
64
  enabled: true
66
65
  exclude: []
67
- max_methods: 10
66
+ max_methods: 20
68
67
  TooManyStatements:
69
68
  enabled: true
70
69
  exclude:
@@ -73,8 +72,6 @@ TooManyStatements:
73
72
  - Guacamole::DocumentModelMapper#model_to_document
74
73
  - Guacamole::Collection::ClassMethods#create_document_from
75
74
  - Guacamole::Collection::ClassMethods#create_referenced_by_models_of
76
- - Guacamole::Configuration#_add_missing_methods_to_database
77
- - Guacamole::Configuration#create_database_connection_from
78
75
  max_statements: 5
79
76
  UncommunicativeMethodName:
80
77
  enabled: true
data/guacamole.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
10
10
  spec.email = ['moonglum@moonbeamlabs.com', 'dirk.breuer@gmail.com']
11
11
  spec.description = %q{ODM for ArangoDB}
12
12
  spec.summary = %q{An ODM for ArangoDB that uses the DataMapper pattern.}
13
- spec.homepage = 'https://github.com/triAGENS/guacamole'
13
+ spec.homepage = 'http://guacamolegem.org'
14
14
  spec.license = 'Apache License 2.0'
15
15
 
16
16
  spec.files = `git ls-files`.split($/)
@@ -18,7 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(spec)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'ashikawa-core', '~> 0.10.0'
21
+ spec.add_dependency 'ashikawa-core', '~> 0.11.0'
22
22
  spec.add_dependency 'virtus', '~> 1.0.1'
23
23
  spec.add_dependency 'activesupport', '>= 4.0.0'
24
24
  spec.add_dependency 'activemodel', '>= 4.0.0'
data/lib/guacamole.rb CHANGED
@@ -1,8 +1,7 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
- require 'active_support/core_ext'
4
-
5
3
  require 'guacamole/version'
4
+ require 'guacamole/exceptions'
6
5
  require 'guacamole/configuration'
7
6
  require 'guacamole/model'
8
7
  require 'guacamole/collection'
@@ -0,0 +1,101 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module Guacamole
4
+ # Build an AQL query for ArangoDB
5
+ class AqlQuery < Query
6
+ # The AQL fragment to be added into the complete query
7
+ attr_accessor :aql_fragment
8
+
9
+ # The associated collection
10
+ attr_reader :collection
11
+
12
+ # The additional options
13
+ attr_reader :options
14
+
15
+ # Create a new AqlQuery
16
+ #
17
+ # @param [Guacamole::Collection] collection The collection class to be used
18
+ # @param [Class] mapper The class of the mapper to use
19
+ # @param [Hash] options Additional options for query execution
20
+ # @option options [String] :return_as ('RETURN #{model_name}') A custom `RETURN` statement
21
+ # @option options [Boolean] :mapping (true) Should the mapping be performed?
22
+ def initialize(collection, mapper, options = {})
23
+ @collection = collection
24
+ super(collection.connection.query, mapper)
25
+ @options = default_options.merge(options)
26
+ end
27
+
28
+ # Set the bind parameters
29
+ #
30
+ # @param [Hash] bind_parameters All the bind parameters
31
+ def bind_parameters=(bind_parameters)
32
+ @options[:bind_vars] = bind_parameters
33
+ end
34
+
35
+ # Get the bind parameters
36
+ #
37
+ # @return [Hash] All the bind parameters
38
+ def bind_parameters
39
+ @options[:bind_vars]
40
+ end
41
+
42
+ # Creates an AQL string based on the `aql_fragment`,
43
+ # the collection and model information.
44
+ #
45
+ # @return [String] An AQL string ready to be send to Arango
46
+ def aql_string
47
+ aql_string = "FOR #{model_name} IN #{collection_name} #{aql_fragment} #{return_as}"
48
+ Guacamole.logger.debug "[AQL] #{aql_string} | bind_parameters: #{bind_parameters}"
49
+ aql_string
50
+ end
51
+
52
+ # The RETURN part of the query
53
+ #
54
+ # @return [String] Either the default `RETURN model_name` or a custom string
55
+ def return_as
56
+ options[:return_as]
57
+ end
58
+
59
+ # Should the mapping step be perfomed? If set to false we will return the raw document.
60
+ #
61
+ # @return [Boolean] Either if the mapping should be perfomed or not
62
+ def perform_mapping?
63
+ options[:mapping]
64
+ end
65
+
66
+ # The default options to be set for the query
67
+ #
68
+ # @return [Hash] The default options
69
+ def default_options
70
+ {
71
+ return_as: "RETURN #{model_name}",
72
+ mapping: true
73
+ }
74
+ end
75
+
76
+ private
77
+
78
+ # The name of the model to be used in the query
79
+ def model_name
80
+ mapper.model_class.model_name.element
81
+ end
82
+
83
+ # The name of the collection to be used in the query
84
+ def collection_name
85
+ collection.collection_name
86
+ end
87
+
88
+ # Executes an AQL query with bind parameters
89
+ #
90
+ # @see Query#perfom_query
91
+ def perfom_query(iterator_with_mapping, &block)
92
+ iterator = perform_mapping? ? iterator_with_mapping : iterator_without_mapping(&block)
93
+ connection.execute(aql_string, options).each(&iterator)
94
+ end
95
+
96
+ # An iterator to be used if no mapping should be performed
97
+ def iterator_without_mapping(&block)
98
+ ->(document) { block.call document }
99
+ end
100
+ end
101
+ end
@@ -1,8 +1,10 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
3
  require 'guacamole/query'
4
+ require 'guacamole/aql_query'
4
5
 
5
6
  require 'ashikawa-core'
7
+ require 'active_support'
6
8
  require 'active_support/concern'
7
9
  require 'active_support/core_ext/string/inflections'
8
10
 
@@ -207,6 +209,38 @@ module Guacamole
207
209
  query
208
210
  end
209
211
 
212
+ # Find models with simple AQL queries
213
+ #
214
+ # Since Simple Queries are quite limited in their possibilities you will need to
215
+ # use AQL for more advanced data retrieval. Currently there is only a very basic
216
+ # and experimental support for AQL. Eventually we will replace it with an advanced
217
+ # query builder DSL. Due to this, we deactivated this feature per default. You
218
+ # need to activate it with {Configuration#aql_support}:
219
+ #
220
+ # Guacamole::Configuration.aql_support = :experimental
221
+ #
222
+ # If not activated it we will raise an error.
223
+ #
224
+ # @param [String] aql_fragment An AQL string that will will be put between the
225
+ # `FOR x IN coll` and the `RETURN x` part.
226
+ # @param [Hash<Symbol, String>] bind_parameters The parameters to be passed into the query
227
+ # @param [Hash] options Additional options for the query execution
228
+ # @option options [String] :return_as ('RETURN #{model_name}') A custom `RETURN` statement
229
+ # @option options [Boolean] :mapping (true) Should the mapping be performed?
230
+ # @return [Query]
231
+ # @raise [AQLNotSupportedError] If `aql_support` was not activated
232
+ # @note Please use always bind parameters since they provide at least some form
233
+ # of protection from AQL injection.
234
+ # @see https://www.arangodb.org/manuals/2/Aql.html AQL Documentation
235
+ def by_aql(aql_fragment, bind_parameters = {}, options = {})
236
+ raise AQLNotSupportedError unless Guacamole.configuration.experimental_features.include?(:aql_support)
237
+
238
+ query = AqlQuery.new(self, mapper, options)
239
+ query.aql_fragment = aql_fragment
240
+ query.bind_parameters = bind_parameters
241
+ query
242
+ end
243
+
210
244
  # Get all Models stored in the collection
211
245
  #
212
246
  # The result can be limited (and should be for most datasets)
@@ -1,9 +1,10 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
 
3
+ require 'active_support'
4
+ require 'active_support/core_ext'
3
5
  require 'logger'
4
6
  require 'forwardable'
5
7
  require 'ashikawa-core'
6
- require 'active_support/core_ext'
7
8
  require 'yaml'
8
9
 
9
10
  require 'guacamole/document_model_mapper'
@@ -70,10 +71,18 @@ module Guacamole
70
71
  # @!visibility protected
71
72
  attr_accessor :database, :default_mapper, :logger
72
73
 
74
+ AVAILABLE_EXPERIMENTAL_FEATURES = [
75
+ :aql_support
76
+ ]
77
+
73
78
  class << self
74
79
  extend Forwardable
75
80
 
76
- def_delegators :configuration, :database, :database=, :default_mapper=, :logger=
81
+ def_delegators :configuration,
82
+ :database, :database=,
83
+ :default_mapper=,
84
+ :logger=,
85
+ :experimental_features=, :experimental_features
77
86
 
78
87
  def default_mapper
79
88
  configuration.default_mapper || (self.default_mapper = Guacamole::DocumentModelMapper)
@@ -104,16 +113,12 @@ module Guacamole
104
113
  end
105
114
 
106
115
  def create_database_connection_from(config)
107
- database = Ashikawa::Core::Database.new do |arango_config|
116
+ Ashikawa::Core::Database.new do |arango_config|
108
117
  arango_config.url = db_url_from(config)
109
118
  arango_config.username = config['username']
110
119
  arango_config.password = config['password']
111
120
  arango_config.logger = logger
112
121
  end
113
-
114
- _add_missing_methods_to_database(database)
115
-
116
- database
117
122
  end
118
123
 
119
124
  def db_url_from(config)
@@ -129,49 +134,21 @@ module Guacamole
129
134
  default_logger.level = Logger::INFO
130
135
  default_logger
131
136
  end
137
+ end
132
138
 
133
- # FIXME: This is not here to stay! Kill it with fire!
134
- #
135
- # As soon Ashikawa::Core provides those features
136
- # (https://github.com/triAGENS/ashikawa-core/issues/83) immediately
137
- # remove this hack. But while this is ugly as hell it ensures we don't
138
- # need to change any other related code. Just remove this and we're good.
139
- def _add_missing_methods_to_database(database)
140
- database.singleton_class.instance_eval do
141
- # The raw Faraday connection
142
- define_method(:raw_connection) do
143
- @connection.connection
144
- end
145
-
146
- # The base URI to the ArangoDB server
147
- define_method(:arangodb_uri) do |additional_path = ''|
148
- uri = raw_connection.url_prefix
149
- base_uri = [uri.scheme, '://', uri.host, ':', uri.port].join
150
- URI.join(base_uri, additional_path)
151
- end
152
-
153
- # Database name query method
154
- define_method(:name) do
155
- database_regexp = %r{_db/(?<db_name>\w+)/_api}
156
- raw_connection.url_prefix.to_s.match(database_regexp)['db_name']
157
- end
158
-
159
- # Creates the database
160
- define_method(:create) do
161
- raw_connection.post(arangodb_uri('/_api/database'), name: name)
162
- end
163
-
164
- # Drops the database
165
- define_method(:drop) do
166
- raw_connection.delete(arangodb_uri("/_api/database/#{name}"))
167
- end
168
-
169
- # Truncate the database
170
- define_method(:truncate) do
171
- collections.each { |collection| collection.truncate! }
172
- end
173
- end
174
- end
139
+ # A list of active experimental features. Refer to `AVAILABLE_EXPERIMENTAL_FEATURES` to see
140
+ # what can be activated.
141
+ #
142
+ # @return [Array<Symbol>] The activated experimental features. Defaults to `[]`
143
+ def experimental_features
144
+ @experimental_features || []
145
+ end
146
+
147
+ # Experimental features to activate
148
+ #
149
+ # @param [Array<Symbol>] features A list of experimental features to activate
150
+ def experimental_features=(features)
151
+ @experimental_features = features
175
152
  end
176
153
  end
177
154
  end
@@ -0,0 +1,10 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ module Guacamole
4
+ class GenericError < StandardError; end
5
+ class AQLNotSupportedError < GenericError
6
+ def initialize(msg = 'AQL is an experimental feature. Please activate it in the config: https://github.com/triAGENS/guacamole#experimental-aql-support')
7
+ super
8
+ end
9
+ end
10
+ end
@@ -1,7 +1,8 @@
1
1
  # -*- encoding : utf-8 -*-
2
+
3
+ require 'active_support'
2
4
  require 'active_support/concern'
3
- # Cherry Pick not possible
4
- require 'active_model'
5
+ require 'active_model' # Cherry Pick not possible
5
6
  require 'virtus'
6
7
 
7
8
  module Guacamole
@@ -4,7 +4,6 @@ module Guacamole
4
4
  # Build a query for ArangoDB
5
5
  class Query
6
6
  include Enumerable
7
-
8
7
  # Connection to the database
9
8
  #
10
9
  # @return [Ashikawa::Core::Collection]
@@ -39,16 +38,10 @@ module Guacamole
39
38
  # Iterate over the result of the query
40
39
  #
41
40
  # This will execute the query you have build
42
- def each
41
+ def each(&block)
43
42
  return to_enum(__callee__) unless block_given?
44
43
 
45
- iterator = ->(document) { yield mapper.document_to_model(document) }
46
-
47
- if example
48
- connection.by_example(example, options).each(&iterator)
49
- else
50
- connection.all(options).each(&iterator)
51
- end
44
+ perfom_query ->(document) { block.call mapper.document_to_model(document) }, &block
52
45
  end
53
46
 
54
47
  # Limit the results of the query
@@ -79,5 +72,22 @@ module Guacamole
79
72
  example == other.example
80
73
  end
81
74
  alias_method :eql?, :==
75
+
76
+ private
77
+
78
+ # Performs the query against the database connection.
79
+ #
80
+ # This can be changed by subclasses to implement other types
81
+ # of queries, such as AQL queries.
82
+ #
83
+ # @param [Lambda] iterator To be called on each document returned from
84
+ # the database
85
+ def perfom_query(iterator, &block)
86
+ if example
87
+ connection.by_example(example, options).each(&iterator)
88
+ else
89
+ connection.all(options).each(&iterator)
90
+ end
91
+ end
82
92
  end
83
93
  end
@@ -15,6 +15,11 @@ module Guacamole
15
15
 
16
16
  config.guacamole = ::Guacamole::Configuration
17
17
 
18
+ # Add app/collections to autoload_paths
19
+ initializer 'guacamole.setup_autoload_paths', before: :set_autoload_paths do |app|
20
+ app.config.autoload_paths += %W(#{app.config.root}/app/collections)
21
+ end
22
+
18
23
  # We're not doing migrations (yet)
19
24
  config.send(:app_generators).orm :guacamole, migration: false
20
25
 
@@ -1,5 +1,5 @@
1
1
  # -*- encoding : utf-8 -*-
2
2
  module Guacamole
3
3
  # Current version of the gem
4
- VERSION = '0.1.0'
4
+ VERSION = '0.2.0'
5
5
  end
@@ -0,0 +1,70 @@
1
+ # -*- encoding : utf-8 -*-
2
+
3
+ require 'guacamole'
4
+ require 'acceptance/spec_helper'
5
+
6
+ class Pony
7
+ include Guacamole::Model
8
+
9
+ attribute :name, String
10
+ attribute :color, String
11
+ attribute :type, Array[String]
12
+ end
13
+
14
+ class PoniesCollection
15
+ include Guacamole::Collection
16
+ end
17
+
18
+ describe 'BasicAQLSupport' do
19
+ subject { PoniesCollection }
20
+
21
+ let(:pegasus_pony) { Fabricate(:pony, type: ['Pegasus']) }
22
+ let(:earth_pony) { Fabricate(:pony, type: ['Earthpony'], name: 'Candy Mane') }
23
+ let(:unicorn_pegasus_pony) { Fabricate(:pony, type: ['Pegasus', 'Unicorn']) }
24
+
25
+ context 'with experimental AQL support enabled' do
26
+ before do
27
+ Guacamole.configuration.experimental_features = [:aql_support]
28
+
29
+ [pegasus_pony, earth_pony, unicorn_pegasus_pony]
30
+ end
31
+
32
+ it 'should retrieve models by simple AQL queries' do
33
+ pony_by_name = PoniesCollection.by_aql('FILTER pony.name == @name', name: 'Candy Mane').first
34
+ expect(pony_by_name).to eq earth_pony
35
+ end
36
+
37
+ it 'should retrieve models by more complex AQL queries' do
38
+ ponies_by_type = PoniesCollection.by_aql('FILTER POSITION(pony.type, @pony_type, false) == true',
39
+ pony_type: 'Pegasus')
40
+ expect(ponies_by_type).to include unicorn_pegasus_pony
41
+ expect(ponies_by_type).to include pegasus_pony
42
+ end
43
+
44
+ it 'should allow a custom RETURN statement' do
45
+ custom_color = 'fancy white pink with sparkles'
46
+ pony_by_name = PoniesCollection.by_aql('FILTER pony.name == @name',
47
+ { name: 'Candy Mane' },
48
+ return_as: %Q{RETURN MERGE(pony, {"color": "#{custom_color}"})}).first
49
+ expect(pony_by_name.color).to eq custom_color
50
+ end
51
+
52
+ it 'should allow to disable the mapping' do
53
+ pony_hash = PoniesCollection.by_aql('FILTER pony.name == @name',
54
+ { name: 'Candy Mane' },
55
+ mapping: false ).first
56
+ expect(pony_hash).to be_an(Ashikawa::Core::Document)
57
+ end
58
+ end
59
+
60
+ context 'without experimental AQL support enabled' do
61
+ before do
62
+ Guacamole.configuration.experimental_features = []
63
+ end
64
+
65
+ it 'should raise an error accessing the AQL feature' do
66
+ expect { PoniesCollection.by_aql("random AQL fragment") }.to raise_error(Guacamole::AQLNotSupportedError)
67
+ end
68
+ end
69
+
70
+ end
@@ -3,6 +3,7 @@
3
3
  $LOAD_PATH.unshift(File.dirname(__FILE__))
4
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
5
5
 
6
+ require 'active_support'
6
7
  require 'fabrication'
7
8
  require 'faker'
8
9
  require 'logging'
@@ -59,6 +60,6 @@ RSpec.configure do |config|
59
60
  end
60
61
 
61
62
  config.before(:each) do
62
- Guacamole.configuration.database.collections.each { |collection| collection.truncate! }
63
+ Guacamole.configuration.database.truncate
63
64
  end
64
65
  end
@@ -1,7 +1,7 @@
1
1
  # -*- encoding: utf-8 -*-
2
2
 
3
3
  class Book
4
- include Guacamole::Model
4
+ extend ActiveSupport::Autoload
5
5
  include Guacamole::Model
6
6
 
7
7
  autoload :Author, 'fabricators/author'
@@ -0,0 +1,7 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Fabricator(:pony) do
4
+ name { Faker::Name.name }
5
+ color { %w(purple pink blue yellow green white).sample }
6
+ type { %w(Pegasus Earthpony Unicorn).sample }
7
+ end
@@ -3,15 +3,15 @@
3
3
  DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
4
4
  cd $DIR
5
5
 
6
- # VERSION=1.4.devel
7
6
  NAME=ArangoDB-$VERSION
8
7
 
9
8
  if [ ! -d "$DIR/$NAME" ]; then
10
9
  # download ArangoDB
11
- echo "wget http://www.arangodb.org/travisCI/$NAME.tar.gz"
12
- wget http://www.arangodb.org/travisCI/$NAME.tar.gz
10
+ echo "wget http://www.arangodb.org/repositories/travisCI/$NAME.tar.gz"
11
+ wget http://www.arangodb.org/repositories/travisCI/$NAME.tar.gz
13
12
  echo "tar zxf $NAME.tar.gz"
14
13
  tar zvxf $NAME.tar.gz
14
+ mv `find . -type d -name "ArangoDB-*"` $NAME
15
15
  fi
16
16
 
17
17
  ARCH=$(arch)
@@ -19,30 +19,24 @@ PID=$(echo $PPID)
19
19
  TMP_DIR="/tmp/arangodb.$PID"
20
20
  PID_FILE="/tmp/arangodb.$PID.pid"
21
21
  ARANGODB_DIR="$DIR/$NAME"
22
-
23
- ARANGOD="${ARANGODB_DIR}/bin/arangod"
24
- if [ "$ARCH" == "x86_64" ]; then
25
- ARANGOD="${ARANGOD}_x86_64"
26
- fi
22
+ ARANGOD="${ARANGODB_DIR}/bin/arangod_x86_64"
27
23
 
28
24
  # create database directory
29
25
  mkdir ${TMP_DIR}
30
26
 
31
- echo "Starting arangodb '${ARANGOD}'"
27
+ echo "Starting ArangoDB '${ARANGOD}'"
32
28
 
33
29
  ${ARANGOD} \
34
- --database.directory ${TMP_DIR} \
35
- --configuration none \
30
+ --database.directory ${TMP_DIR} \
31
+ --configuration none \
36
32
  --server.endpoint tcp://127.0.0.1:8529 \
33
+ --javascript.app-path ${ARANGODB_DIR}/js/apps \
37
34
  --javascript.startup-directory ${ARANGODB_DIR}/js \
38
- --server.admin-directory ${ARANGODB_DIR}/html/admin \
39
35
  --javascript.modules-path ${ARANGODB_DIR}/js/server/modules:${ARANGODB_DIR}/js/common/modules:${ARANGODB_DIR}/js/node \
40
36
  --javascript.package-path ${ARANGODB_DIR}/js/npm:${ARANGODB_DIR}/js/common/test-data/modules \
41
- --javascript.action-directory ${ARANGODB_DIR}/js/actions \
42
- --javascript.app-path ${ARANGODB_DIR}/js/apps \
43
- --database.maximal-journal-size 1048576 \
44
- --server.disable-admin-interface ${ARANGODB_DISABLE_AUTHENTIFICATION} \
45
- --server.disable-authentication true \
37
+ --javascript.action-directory ${ARANGODB_DIR}/js/actions \
38
+ --database.maximal-journal-size 1048576 \
39
+ --server.disable-authentication ${ARANGODB_DISABLE_AUTHENTIFICATION} \
46
40
  --javascript.gc-interval 1 &
47
41
 
48
42
  sleep 2
@@ -57,7 +51,7 @@ if [ "x$process" == "x" ]; then
57
51
  fi
58
52
 
59
53
  echo "Waiting until ArangoDB is ready on port 8529"
60
- while [[ -z `curl -s 'http://127.0.0.1:8529/_api/version' ` ]] ; do
54
+ while [[ -z `curl --basic --user 'root:' -s 'http://127.0.0.1:8529/_api/version' ` ]] ; do
61
55
  echo -n "."
62
56
  sleep 2s
63
57
  done
@@ -126,4 +126,21 @@ describe Guacamole::Configuration do
126
126
  subject.load 'config_file.yml'
127
127
  end
128
128
  end
129
+
130
+ describe 'experimental_features' do
131
+ let(:fresh_config) { Guacamole::Configuration.new }
132
+
133
+ after do
134
+ subject.experimental_features = []
135
+ end
136
+
137
+ it 'should default to none' do
138
+ expect(fresh_config.experimental_features).to be_empty
139
+ end
140
+
141
+ it 'should accept a list of features to activate' do
142
+ subject.experimental_features = [:aql_support]
143
+ expect(subject.experimental_features).to include :aql_support
144
+ end
145
+ end
129
146
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: guacamole
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Dohmen
@@ -9,132 +9,132 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-05-08 00:00:00.000000000 Z
12
+ date: 2014-05-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: ashikawa-core
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  requirements:
18
- - - ~>
18
+ - - "~>"
19
19
  - !ruby/object:Gem::Version
20
- version: 0.10.0
20
+ version: 0.11.0
21
21
  type: :runtime
22
22
  prerelease: false
23
23
  version_requirements: !ruby/object:Gem::Requirement
24
24
  requirements:
25
- - - ~>
25
+ - - "~>"
26
26
  - !ruby/object:Gem::Version
27
- version: 0.10.0
27
+ version: 0.11.0
28
28
  - !ruby/object:Gem::Dependency
29
29
  name: virtus
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
- - - ~>
32
+ - - "~>"
33
33
  - !ruby/object:Gem::Version
34
34
  version: 1.0.1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
39
- - - ~>
39
+ - - "~>"
40
40
  - !ruby/object:Gem::Version
41
41
  version: 1.0.1
42
42
  - !ruby/object:Gem::Dependency
43
43
  name: activesupport
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
- - - '>='
46
+ - - ">="
47
47
  - !ruby/object:Gem::Version
48
48
  version: 4.0.0
49
49
  type: :runtime
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
- - - '>='
53
+ - - ">="
54
54
  - !ruby/object:Gem::Version
55
55
  version: 4.0.0
56
56
  - !ruby/object:Gem::Dependency
57
57
  name: activemodel
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
- - - '>='
60
+ - - ">="
61
61
  - !ruby/object:Gem::Version
62
62
  version: 4.0.0
63
63
  type: :runtime
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
- - - '>='
67
+ - - ">="
68
68
  - !ruby/object:Gem::Version
69
69
  version: 4.0.0
70
70
  - !ruby/object:Gem::Dependency
71
71
  name: hamster
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
- - - ~>
74
+ - - "~>"
75
75
  - !ruby/object:Gem::Version
76
76
  version: 1.0.1.pre.rc.1
77
77
  type: :runtime
78
78
  prerelease: false
79
79
  version_requirements: !ruby/object:Gem::Requirement
80
80
  requirements:
81
- - - ~>
81
+ - - "~>"
82
82
  - !ruby/object:Gem::Version
83
83
  version: 1.0.1.pre.rc.1
84
84
  - !ruby/object:Gem::Dependency
85
85
  name: fabrication
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
- - - ~>
88
+ - - "~>"
89
89
  - !ruby/object:Gem::Version
90
90
  version: 2.8.1
91
91
  type: :development
92
92
  prerelease: false
93
93
  version_requirements: !ruby/object:Gem::Requirement
94
94
  requirements:
95
- - - ~>
95
+ - - "~>"
96
96
  - !ruby/object:Gem::Version
97
97
  version: 2.8.1
98
98
  - !ruby/object:Gem::Dependency
99
99
  name: faker
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
- - - ~>
102
+ - - "~>"
103
103
  - !ruby/object:Gem::Version
104
104
  version: 1.2.0
105
105
  type: :development
106
106
  prerelease: false
107
107
  version_requirements: !ruby/object:Gem::Requirement
108
108
  requirements:
109
- - - ~>
109
+ - - "~>"
110
110
  - !ruby/object:Gem::Version
111
111
  version: 1.2.0
112
112
  - !ruby/object:Gem::Dependency
113
113
  name: logging
114
114
  requirement: !ruby/object:Gem::Requirement
115
115
  requirements:
116
- - - ~>
116
+ - - "~>"
117
117
  - !ruby/object:Gem::Version
118
118
  version: 1.8.1
119
119
  type: :development
120
120
  prerelease: false
121
121
  version_requirements: !ruby/object:Gem::Requirement
122
122
  requirements:
123
- - - ~>
123
+ - - "~>"
124
124
  - !ruby/object:Gem::Version
125
125
  version: 1.8.1
126
126
  - !ruby/object:Gem::Dependency
127
127
  name: pry
128
128
  requirement: !ruby/object:Gem::Requirement
129
129
  requirements:
130
- - - ~>
130
+ - - "~>"
131
131
  - !ruby/object:Gem::Version
132
132
  version: 0.9.12
133
133
  type: :development
134
134
  prerelease: false
135
135
  version_requirements: !ruby/object:Gem::Requirement
136
136
  requirements:
137
- - - ~>
137
+ - - "~>"
138
138
  - !ruby/object:Gem::Version
139
139
  version: 0.9.12
140
140
  description: ODM for ArangoDB
@@ -145,12 +145,13 @@ executables: []
145
145
  extensions: []
146
146
  extra_rdoc_files: []
147
147
  files:
148
- - .gitignore
149
- - .hound.yml
150
- - .rspec
151
- - .ruby-version
152
- - .travis.yml
153
- - .yardopts
148
+ - ".gitignore"
149
+ - ".hound.yml"
150
+ - ".rspec"
151
+ - ".ruby-version"
152
+ - ".travis.yml"
153
+ - ".yardopts"
154
+ - CHANGELOG.md
154
155
  - CONTRIBUTING.md
155
156
  - Gemfile
156
157
  - Gemfile.devtools
@@ -166,9 +167,11 @@ files:
166
167
  - config/yardstick.yml
167
168
  - guacamole.gemspec
168
169
  - lib/guacamole.rb
170
+ - lib/guacamole/aql_query.rb
169
171
  - lib/guacamole/collection.rb
170
172
  - lib/guacamole/configuration.rb
171
173
  - lib/guacamole/document_model_mapper.rb
174
+ - lib/guacamole/exceptions.rb
172
175
  - lib/guacamole/identity_map.rb
173
176
  - lib/guacamole/model.rb
174
177
  - lib/guacamole/proxies/proxy.rb
@@ -191,6 +194,7 @@ files:
191
194
  - lib/rails/generators/rspec/collection/templates/collection_spec.rb.tt
192
195
  - log/.gitkeep
193
196
  - spec/acceptance/.gitkeep
197
+ - spec/acceptance/aql_spec.rb
194
198
  - spec/acceptance/association_spec.rb
195
199
  - spec/acceptance/basic_spec.rb
196
200
  - spec/acceptance/config/guacamole.yml
@@ -201,6 +205,7 @@ files:
201
205
  - spec/fabricators/book.rb
202
206
  - spec/fabricators/book_fabricator.rb
203
207
  - spec/fabricators/comment_fabricator.rb
208
+ - spec/fabricators/pony.rb
204
209
  - spec/setup/arangodb.sh
205
210
  - spec/spec_helper.rb
206
211
  - spec/unit/.gitkeep
@@ -212,7 +217,7 @@ files:
212
217
  - spec/unit/model_spec.rb
213
218
  - spec/unit/query_spec.rb
214
219
  - tasks/adjustments.rake
215
- homepage: https://github.com/triAGENS/guacamole
220
+ homepage: http://guacamolegem.org
216
221
  licenses:
217
222
  - Apache License 2.0
218
223
  metadata: {}
@@ -222,22 +227,23 @@ require_paths:
222
227
  - lib
223
228
  required_ruby_version: !ruby/object:Gem::Requirement
224
229
  requirements:
225
- - - '>='
230
+ - - ">="
226
231
  - !ruby/object:Gem::Version
227
232
  version: '0'
228
233
  required_rubygems_version: !ruby/object:Gem::Requirement
229
234
  requirements:
230
- - - '>='
235
+ - - ">="
231
236
  - !ruby/object:Gem::Version
232
237
  version: '0'
233
238
  requirements: []
234
239
  rubyforge_project:
235
- rubygems_version: 2.2.0
240
+ rubygems_version: 2.2.2
236
241
  signing_key:
237
242
  specification_version: 4
238
243
  summary: An ODM for ArangoDB that uses the DataMapper pattern.
239
244
  test_files:
240
245
  - spec/acceptance/.gitkeep
246
+ - spec/acceptance/aql_spec.rb
241
247
  - spec/acceptance/association_spec.rb
242
248
  - spec/acceptance/basic_spec.rb
243
249
  - spec/acceptance/config/guacamole.yml
@@ -248,6 +254,7 @@ test_files:
248
254
  - spec/fabricators/book.rb
249
255
  - spec/fabricators/book_fabricator.rb
250
256
  - spec/fabricators/comment_fabricator.rb
257
+ - spec/fabricators/pony.rb
251
258
  - spec/setup/arangodb.sh
252
259
  - spec/spec_helper.rb
253
260
  - spec/unit/.gitkeep