Skip to content
This repository has been archived by the owner on May 25, 2021. It is now read-only.

moonglum/brazil

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

29 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Brazil

Project Brazil
Homepage https://github.com/moonglum/brazil
Documentation RubyDoc
CI Build Status
Code Metrics Code Climate Code Climate Coverage
Gem Version Not available as a gem yet
Dependencies Dependency Status

Cover Image

'Ere I am, J.H. ...The ghost in the machine. — Mr. Helpmann

This is a spike to see how the DSL should look like. There's no gem on Rubygems yet, you have to install it from this repository. There are still some important parts of AQL missing, I will add them over the next days to this spike. The code is messy as this is only a spike 😉 I would love your feedback on the API!

Brazil is an experimental Ruby DSL for creating queries for the ArangoDB in the the Arango Query Language. Brazil is also the fifth biggest producer of Avocados (according to Wikipedia) and an amazing movie. As chance would have it, the spike of this gem was done on my way to Brazil. Brazil is not intended to be a Object Document Mapper, but to be used by the ODM to build the queries. The DSL is inspired by both the Sequel and the ActiveRecord gems.

If you want to try it out this gem has an executable called brazil which will connect to your local ArangoDB running on the standard port. You can try out all examples below – it will store the example data in the database if you want. To run it you need to install both ashikawa-core and pry:

gem install ashikawa-core
gem install pry
brazil

ArangoDB

ArangoDB is...

[...] a distributed open-source database with a flexible data model for documents, graphs, and key-values. Build high performance applications using a convenient sql-like query language or JavaScript extensions.

Installation

Check out the repository from Github. cd into the folder and run:

bundle
bundle exec rake install

Usage

In our examples we will use a collection of characters and their cast from the movie 'Brazil'. We will work our way through AQL using Brazil to generate the queries.

The basic form

When you're querying using Brazil each of the queries needs at least two things: One or more for_all calls and exactly one return_as call. You can imagine that a query always iterates over each of the documents in a collection (there are of course indexes etc. that allow a lot of shortcuts, but for a basic mental model you can imagine it like this). For all the documents you selected, you have to specify what exactly you want to return. In the simplest case this is the entire document.

  • for_all('variable_name', in_collection: 'collection_name'): Iterate over all documents in the collection with the name collection_name – in each iteration call the current document variable_name.
  • return_as: In its basic form it takes the name of a variable as a String. This will return the entire document denoted by the variable.

If, for example, you want to iterate over all characters in the characters collection and return each one of them, you could do that as follows:

query = Query.for_all('character', in_collection: 'characters').return_as('character')

A more sophisticated return_as or: Projections

In a lot of cases, you may want to influence the form of each of the returned documents. In relational algebra this is known as a projection. With Brazil you can do this by providing a block to the return_as statement instead of a String. This block will be provided with a document on which you can then define the attributes you want. Typically the value for these attributes will be an attribute from one of the variables you defined. For this purpose, all variables you define in a for_all statement will be made available in the context of the block. You can access their attributes to set the attributes of your result document. If for example you want to iterate over all documents in the casting collection and return a document with a name attribute for each which has the value of the actor attribute of the document, you could do it like this:

query = Query.for_all('cast', in_collection: 'casting').return_as do |result|
  result['name'] = cast['actor']
end

You can also set the result to a fixed value:

query = Query.for_all('cast', in_collection: 'casting').return_as do |result|
  result['rating'] = 'awesome'
end

Filtering the results

You probably don't want all of the documents in a collection. AQL allows you to filter your results. In Brazil you can do that by chaining a filter_by statement into your query builder. In this statement you can use different operators to check if you want this document to be in your collection. Let us start with the equality operator. In the following statement we want to get all characters that have the name "Sam Lawry" and return the according document:

query = Query.for_all('character', in_collection: 'characters')
  .filter_by { character['name'] == 'Sam Lawry' }
  .return_as('character')

Sorting

If you want to sort the result via certain criteria, use the sort_by function in Brazil. Sort takes a block where you can give an attribute name of a variable to sort. If for example you want to sort all characters using their name in ascending order, you could do it as follows:

query = Query.for_all('character', in_collection: 'characters')
  .sort_by { character['name'] }
  .return_as('character')

If instead you want to sort in descending order, you could do that as follows:

query = Query.for_all('character', in_collection: 'characters')
  .sort_by { descending(character['name']) }
  .return_as('character')

It is also possible to sort via multiple criteria. In this case you need to provide a block with the criteria in order from most significant to least significant:

query = Query.for_all('character', in_collection: 'characters')
  .sort_by { [character['job'], character['name']] }
  .return_as('character')

Limit

If you only need to receive a certain number of results, you can limit the result as follows:

query = Query.for_all('character', in_collection: 'characters')
  .limit(2)
  .return_as('character')

You can also provide an offset to the limit function:

query = Query.for_all('character', in_collection: 'characters')
  .sort_by { character['name'] }
  .limit(2, offset_by: 1)
  .return_as('character')

Contributing

If you want to contribute to the project, see CONTRIBUTING.md for details. It contains information on our process and how to set up everything. The following people have contributed to this project:

About

Experimental Ruby DSL for creating AQL queries

Resources

License

Stars

Watchers

Forks

Packages

No packages published