guacamole 0.1.0 → 0.2.0
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 +4 -4
- data/.ruby-version +1 -1
- data/.travis.yml +2 -1
- data/CHANGELOG.md +39 -0
- data/README.md +44 -15
- data/config/reek.yml +4 -7
- data/guacamole.gemspec +2 -2
- data/lib/guacamole.rb +1 -2
- data/lib/guacamole/aql_query.rb +101 -0
- data/lib/guacamole/collection.rb +34 -0
- data/lib/guacamole/configuration.rb +26 -49
- data/lib/guacamole/exceptions.rb +10 -0
- data/lib/guacamole/model.rb +3 -2
- data/lib/guacamole/query.rb +19 -9
- data/lib/guacamole/railtie.rb +5 -0
- data/lib/guacamole/version.rb +1 -1
- data/spec/acceptance/aql_spec.rb +70 -0
- data/spec/acceptance/spec_helper.rb +2 -1
- data/spec/fabricators/book.rb +1 -1
- data/spec/fabricators/pony.rb +7 -0
- data/spec/setup/arangodb.sh +12 -18
- data/spec/unit/configuration_spec.rb +17 -0
- metadata +39 -32
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA1:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: 2522fab030888fc0ee9601790aabd2134c6f32dc
         | 
| 4 | 
            +
              data.tar.gz: 400562752f398045f858bbe9edf3c40d621fcc4c
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 8c1b397cab789fee57a5a98eb76e46f9c422b466747cd9be272591cc66aee47829253c484ffd500e9fe0755fc255d43df55742546404ecf618a536f27538ab18
         | 
| 7 | 
            +
              data.tar.gz: 19f830e89f65c7c4c8404a4ce49559920a6a3eac6e0bbe0eab34671f944a49bc0412d530aaad984fb0fd5cba7bd77ffbbd5c6dc8d1bc3e1248a5605972e0e8c3
         | 
    
        data/.ruby-version
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            ruby-2. | 
| 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= | 
| 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  | 
| 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  | 
| 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 | 
            -
              *  | 
| 77 | 
            -
              *  | 
| 78 | 
            -
              *  | 
| 76 | 
            +
              * improved testability
         | 
| 77 | 
            +
              * separation of concerns and
         | 
| 78 | 
            +
              * easier to support database | 
| 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  | 
| 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  | 
| 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  | 
| 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  | 
| 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  | 
| 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  | 
| 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  | 
| 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:  | 
| 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      = ' | 
| 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. | 
| 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
    
    
| @@ -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
         | 
    
        data/lib/guacamole/collection.rb
    CHANGED
    
    | @@ -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, | 
| 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 | 
            -
                     | 
| 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 | 
            -
             | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                   | 
| 139 | 
            -
             | 
| 140 | 
            -
             | 
| 141 | 
            -
             | 
| 142 | 
            -
             | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 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
         | 
    
        data/lib/guacamole/model.rb
    CHANGED
    
    
    
        data/lib/guacamole/query.rb
    CHANGED
    
    | @@ -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 | 
            -
                   | 
| 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
         | 
    
        data/lib/guacamole/railtie.rb
    CHANGED
    
    | @@ -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 |  | 
    
        data/lib/guacamole/version.rb
    CHANGED
    
    
| @@ -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. | 
| 63 | 
            +
                Guacamole.configuration.database.truncate
         | 
| 63 64 | 
             
              end
         | 
| 64 65 | 
             
            end
         | 
    
        data/spec/fabricators/book.rb
    CHANGED
    
    
    
        data/spec/setup/arangodb.sh
    CHANGED
    
    | @@ -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  | 
| 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 | 
            -
              -- | 
| 43 | 
            -
              -- | 
| 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. | 
| 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- | 
| 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. | 
| 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. | 
| 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:  | 
| 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. | 
| 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
         |