README.md in guacamole-0.2.0 vs README.md in guacamole-0.3.0
- old
+ new
@@ -1,8 +1,9 @@
[![RubyDoc](http://img.shields.io/badge/📄-RubyDoc-be1d77.svg)](http://rubydoc.info/gems/guacamole/frames)
[![Build Status](http://img.shields.io/travis/triAGENS/guacamole.svg)](https://travis-ci.org/triAGENS/guacamole)
[![Code Climate](http://img.shields.io/codeclimate/github/triAGENS/guacamole.svg)](https://codeclimate.com/github/triAGENS/guacamole)
+[![Inline docs](http://inch-ci.org/github/triAGENS/guacamole.svg)](http://inch-ci.org/github/triAGENS/guacamole)
[![Gem Version](http://img.shields.io/gem/v/guacamole.svg)](https://rubygems.org/gems/guacamole)
# Guacamole
Guacamole is an Object Document Mapper (ODM) for the multi-model NoSQL database [ArangoDB](https://www.arangodb.org/). Its main goal is to support easy integration into Ruby on Rails but will likely work in other Rack-based frameworks as well. There are a couple of design goals behind Guacamole which should drive all our development effort:
@@ -22,11 +23,11 @@
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.
First of all create your shiny new application, without ActiveRecord of course:
```shell
-rails new -O $my_awesome_app
+rails new --skip-active-record $my_awesome_app
```
Add this line to your application's Gemfile:
```ruby
@@ -37,10 +38,28 @@
```shell
bundle install
```
+### Adding Guacamole to an existing Rails application
+
+Maybe you're bold and want to add Guacamole to an existing Rails application. In this case some things are different, because you already have an ORM configured. Throughout the remaining README you will find examples of using generators and rake tasks to support you. All the generators must be invoked with the `--orm guacamole` flag. Without this you will generate both, ActiveRecord and Guacamole files:
+
+```shell
+bundle exec rails generate model pony name:string birthday:date color:string --orm guacamole
+```
+
+Guacamole will not overwrite existing rake tasks and thus you need to invoke them with under the guacamole namespace:
+
+```shell
+rake db:guacamole:create
+rake db:guacamole:purge
+rake db:guacamole:drop
+```
+
+Everything else should work as described in the README. If you encounter any errors while working with an existing Rails application, please let us know.
+
### Configuration
After you created the application and installed the dependencies the first thing you need is a configuration file. The database connection is pretty much configured as expected: With a YAML file. Luckily you don't have to create this file by yourself but you can use a generator to do it for you:
```shell
@@ -57,10 +76,12 @@
password: ''
username: ''
database: 'pony_blog_development'
```
+**Note**: If you use something like [dotenv](https://github.com/bkeepers/dotenv) we will process the config file with ERB before loading the YAML. Another way to configure the database connection is to provide a connection URI like this: `http://user:pass@localhost:8529/_db/pony_ville_db`. If you don't use authentication, just skip the user/password part. The connection URI must be provided as the environment variable `DATABASE_URL` and has precedence over the config file.
+
After you created a configuration file you can create the database as in any other Rails project:
```shell
bundle exec rake db:create
```
@@ -152,11 +173,11 @@
As the model doesn't know anything about the database you cannot define database-dependent validations here (i.e.: uniqueness). This logic has to be handled in the `Collection`. That said, we have no strategy how to model this in the `Collection`. If you have any idea about this we would love to hear about it.
### Collections
-Collections are your gateway to the database. They persist your models and offer querying for them. They will translate the raw data from the database to your domain models and vice versa. By convention they are the pluralized version of the model with the suffix `Collection`. So given the model from above, this could be the according collection:
+Collections are your gateway to the database. They persist your models and offer querying for them. They will translate the raw data from the database to your domain models and vice versa. By convention they are the pluralized version of the model with the suffix `Collection`. So given the model from above, this could be the following collection:
```ruby
class PoniesCollection
include Guacamole::Collection
end
@@ -307,17 +328,17 @@
As you can see, from the model perspective there is nothing special about an embedded association. It is just another attribute on the `Post` class. How this is stored will be configured where it is handled: In the `PostsCollection`. Within the `map` block you put all the mapping related configuration. The `embeds` method will make sure that `Comment`s are correctly stored and received within the database. Be aware that embedded models will not have any `_key`, `_id` or `_rev` attribute. But they will have the time stamp attributes correctly populated. Within ArangoDB the resulting document will look like this:
```json
{
- "_id": [...],
- "_rev": [...],
- "_key": [...],
+ "_id": "...",
+ "_rev": "...",
+ "_key": "...",
"title": "The grand blog post",
"body": "Lorem ipsum [...]",
"create_at": "2014-05-03T16:55:43+02:00",
- "updated_at": "2014-05-03T16:55:43+02:00"
+ "updated_at": "2014-05-03T16:55:43+02:00",
"comments": [
{
"text": "This was really a grand blog post",
"create_at": "2014-05-08T16:55:43+02:00",
"updated_at": "2014-05-08T16:55:43+02:00"
@@ -326,10 +347,11 @@
"text": "I don't think it was that great",
"create_at": "2014-05-04T16:55:43+02:00",
"updated_at": "2014-05-04T16:55:43+02:00"
}
]
+}
```
**Note**: Again this will only work if you stick with the convention. So far there is no support to configure this more fine grained.
#### References
@@ -369,11 +391,11 @@
class PostsCollection
include Guacamole::Collection
map do
- references :user
+ references :author
end
end
```
Under the hood we will add an `author_id` to all posts holding the reference to the author. As a user this will be completely transparent for you:
@@ -392,28 +414,142 @@
AuthorsCollection.save author
# => Will save both the author and the post
```
+### Callbacks
+
+Guacamole allows you to define callbacks for various actions performed on a model. Those callbacks need to be defined in a dedicate class per model. For example to hash the password of a user prior creating the document in the database you would write something like the following:
+
+```ruby
+class UserCallbacks
+ include Guacamole::Callbacks
+
+ before_create :encrypt_password
+
+ def encrypt_password
+ object.encrypted_password = BCrypt::Password.create(object.password)
+ end
+end
+```
+
+Whenever callbacks needs to be executed for a model we create an instance of the specified callback with that model. You have access to the model via the `object` method. To specify a callback for a model you must use the `callbacks` method in that model:
+
+```ruby
+class User
+ include Guacamole::Model
+
+ callbacks :user_callbacks
+end
+```
+
+You can define define callbacks for the following actions:
+
+ * `before_validate`
+ * `around_validate`
+ * `after_validate`
+ * `before_save`
+ * `around_save`
+ * `after_save`
+ * `before_create`
+ * `around_create`
+ * `after_create`
+ * `before_update`
+ * `around_update`
+ * `after_update`
+ * `before_delete`
+ * `around_delete`
+ * `after_delete`
+
+The order of the callback execution is as follows:
+
+**Creating an object**
+
+ * `before_validation`
+ * `after_validation`
+ * `before_save`
+ * `around_save`
+ * `before_create`
+ * `around_create`
+ * `after_create`
+ * `after_save`
+
+**Updating an object**
+
+ * `before_validation`
+ * `after_validation`
+ * `before_save`
+ * `around_save`
+ * `before_update`
+ * `around_update`
+ * `after_update`
+ * `after_save`
+
+**Destroying an object**
+
+ * `before_delete`
+ * `around_delete`
+ * `after_delete`
+
+The order of the callback execution is as follows:
+
+**Creating an object**
+
+ 1. `before_validation`
+ 2. `after_validation`
+ 3. `before_save`
+ 4. `around_save`
+ 5. `before_create`
+ 6. `around_create`
+ 7. `after_create`
+ 8. `after_save`
+
+**Updating an object**
+
+ 1. `before_validation`
+ 2. `after_validation`
+ 3. `before_save`
+ 4. `around_save`
+ 5. `before_update`
+ 6. `around_update`
+ 7. `after_update`
+ 8. `after_save`
+
+**Destroying an object**
+
+ 1. `before_delete`
+ 2. `around_delete`
+ 3. `after_delete`
+
+#### Generator Support
+
+Of course we provide a generator to help you setting the required files up:
+
+```shell
+rails generate guacamole:callbacks pony
+```
+
+This will create the callback file, a test template and adds the appropriate register call to the model file.
+
## Integration into the Rails Ecosystemâ„¢
Guacamole is a very young project. A lot of stuff is missing but still, if you want to get started with ArangoDB and are using Ruby/Rails it will give you a nice head start. Besides a long TODO list we want to hint to some points to help you integrate Guacamole with the rest of the Rails ecosystem:
### Testing
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.
-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.
+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 haven't tested Factory Girl yet but it eventually will work too.
### Authentication
-Any integration into an authentication framework need to be done by you. At this time we have nothing to share with you about this topic.
+Any integration into an authentication framework needs to be done by you. At this time we have nothing to share with you about this topic.
### Forms
-While we not tested them they should probably work due to the ActiveModel compliance. But again, this not confirmed and you need to try it out by yourself.
+While we haven't tested them, they should probably work due to the ActiveModel compliance. But again, this is not confirmed and you need to try it out yourself.
-If you give Guacamole a try, please feel free to ask us any question or give us feedback to anything on your mind. This is really crucial for us and we would be more than happy to hear back from you.
+If you give Guacamole a try, please feel free to ask us any question or give us feedback about anything on your mind. This is really crucial for us and we would be more than happy to hear back from you.
## Todos
While there are a lot of open issues we would like to present you a high level overview of upcoming features: