<commit_before>## HyperMapper in Rails

This tutorial will walk through the construction of a basic application using HyperDex, HyperMapper and Rails.  Like any good Hello World demo, we'll be building a very basic blogging application. 

You can see the finished application in the [example source code](https://github.com/goggin13/HyperMapperExamples/tree/master/HyperMapperDemo).  This is just a skeletal app; if you would like to look at a slightly more polished implementation of this same basic code, [check one out here](https://github.com/goggin13/HyperMapperExamples/tree/master/hyper_blog).

### Prerequisites

We'll start presuming you have Ruby >= 1.9.3, Rails 3.2.x and HyperDex 1.0. 

Additionally, I presume that you have built Rails applications before.  If you're familiar with
[HyperDex](http://hyperdex.org/) that doesn't hurt, but you should be just fine getting through 
this tutorial without any previous HyperDex experience.

If you don't feel like meddling with set up tasks, you may wish to do the tutorial on an EC2 instance.  We have 
provided an AMI with all of the requisite software (ami-51dfb338).

The AMI has all of the required libraries checked out as git repositories and it is  
 
**NOT RECOMMENDED FOR USE IN PRODUCTION**

The current package releases of HyperDex do not yet support the ruby client; a subsequent release should fix this issue.  Just the cost of being on the bleeding edge.  

## Starting HyperDex

If you are using the AMI, then these two commands will fire up a HyperDex coordinator and a single daemon.

```
./tasks/start_local_coordinator.sh  
./tasks/start_local_daemon.sh
```

If you are running on your own machine, these commands will do the same:  

```
hyperdex coordinator -f -l 127.0.0.1 -p 1982 --daemon  
hyperdex daemon -f --listen=127.0.0.1 \  
                   --listen-port=2012 \  
                   --coordinator=127.0.0.1 \  
                   --coordinator-port=1982 \  
                   --data=/home/ubuntu/data/daemon_data \  
                   --daemon  
```

Note that both of these commands should be run from their own directory; the hyperdex programs like to write log files to their current directory, and they will conflict with one another.  The scripts on the AMI will take care of this for you.  

## Creating the Rails Application

We'll start with a new blank Rails app.  

```
~/# rails new HyperMapperDemo --skip-active-record
```

Add the HyperMapper gem to your Gemfile

```
gem 'hyper_mapper', git: 'https://github.com/goggin13/HyperMapper.git'
```

And run 

```
bundle install
```

## HyperDex config

Add the following two files to tell HyperMapper about your HyperDex installation:

config/hyper_mapper.yml

```
host: 127.0.0.1
port: 1982
```

config/initializers/hyper_mapper.rb

```
require 'hyper_mapper'
HyperMapper::Config.load_from_file 'config/hyper_mapper.yml'
```

## Users

Now we can start with the standard Rails generate command.

```
rails generate scaffold User username:string password:string bio:text
```

We'll start with our User model. Instead of inheriting from ActiveRecord, we will include the HyperMapper::Document module.

```
class User
  include HyperMapper::Document
  
  attr_accessor :password
  
  # Determines, as in Rails, which attributes can be modified via mass assignment
  attr_accessible :username, :bio, :password
  
  # HyperMapper will generate a unique ID the first time this 
  # User is saved
  autogenerate_id
  
  # Create two attributes, :username, and :bio
  attribute :username
  attribute :bio
  
  # Things we'll need for authentication
  attribute :salt
  attribute :hashed_password
  attribute :session_id  
  
  # Maintain :created_at and :updated_at timestamps
  timestamps
    
end
```

Generating migrations is not yet supported, so we'll have to create the User space ourselves. `User.create_space` will do the work of making a call to the HyperDex client to create the new space.

```
~/# rails c
1.9.3p392 :001 > User.create_space
```


That's all it takes to start! If you fire up your Rails server you should be able to CRUD in HyperDex all the users you desire.  We aimed to support as much querying and creation functionality that you will be familiar with from using ActiveRecord in Rails.  You can call ```User.create!```, or ```User.new(username: "Matt", bio: "Hello world")```, or ```User.find('some_user_id')```.  Check out [the docs](TODO INSERT LINK) for the rest of the Document API. But for now, you don't need to touch anything, as all the code from the scaffold generator will work as is. Start your Rails server and checkout `/users` to try out your first HyperDex CRUD operations through Rails.


#### Validations
Since HyperMapper includes many of the ActiveModel modules, we have access to validators and callback hooks.

Let's add some simple validators, just like we would in a ActiveRecord model.


```
class User
  include HyperMapper::Document
  
  …
  
  validates :username, presence: true,
                       format: /[a-zA-Z\s]+/
  validates :password, presence: true, if: "hashed_password.blank?"
end
```
<commit_msg>update tutorial<commit_after>## HyperMapper in Rails

This tutorial will walk through the construction of a basic application using HyperDex, HyperMapper and Rails.  Like any good Hello World demo, we'll be building a very basic blogging application. 

You can see the finished application in the [example source code](https://github.com/goggin13/HyperMapperExamples/tree/master/HyperMapperDemo).  This is just a skeletal app; if you would like to look at a slightly more polished implementation of this same basic code, [check one out here](https://github.com/goggin13/HyperMapperExamples/tree/master/hyper_blog).

### Prerequisites

We'll start presuming you have Ruby >= 1.9.3, Rails 3.2.x and HyperDex 1.0. 

Additionally, I presume that you have built Rails applications before.  If you're familiar with
[HyperDex](http://hyperdex.org/) that doesn't hurt, but you should be just fine getting through 
this tutorial without any previous HyperDex experience.

If you don't feel like meddling with set up tasks, you may wish to do the tutorial on an EC2 instance.  We have 
provided an AMI with all of the requisite software (ami-51dfb338).

The AMI has all of the required libraries checked out as git repositories and it is  
 
**NOT RECOMMENDED FOR USE IN PRODUCTION**

The current package releases of HyperDex do not yet support the ruby client; a subsequent release should fix this issue.  Just the cost of being on the bleeding edge.  

## Starting HyperDex

If you are using the AMI, then these two commands will fire up a HyperDex coordinator and a single daemon.

```
./tasks/start_local_coordinator.sh  
./tasks/start_local_daemon.sh
```

If you are running on your own machine, these commands will do the same:  

```
hyperdex coordinator -f -l 127.0.0.1 -p 1982 --daemon  
hyperdex daemon -f --listen=127.0.0.1 \  
                   --listen-port=2012 \  
                   --coordinator=127.0.0.1 \  
                   --coordinator-port=1982 \  
                   --data=/home/ubuntu/data/daemon_data \  
                   --daemon  
```

Note that both of these commands should be run from their own directory; the hyperdex programs like to write log files to their current directory, and they will conflict with one another.  The scripts on the AMI will take care of this for you.  

## Creating the Rails Application

We'll start with a new blank Rails app.  

```
~/# rails new HyperMapperDemo --skip-active-record
```

Add the HyperMapper gem to your Gemfile

```
gem 'hyper_mapper', git: 'https://github.com/goggin13/HyperMapper.git'
```

And run 

```
bundle install
```

## HyperDex config

Add the following two files to tell HyperMapper about your HyperDex installation:

config/hyper_mapper.yml

```
host: 127.0.0.1
port: 1982
```

config/initializers/hyper_mapper.rb

```
require 'hyper_mapper'
HyperMapper::Config.load_from_file 'config/hyper_mapper.yml'
```

## Users

Now we can start with the standard Rails generate command.

```
rails generate scaffold User username:string password:string bio:text
```

We'll start with our User model. Instead of inheriting from ActiveRecord, we will include the HyperMapper::Document module.

```
class User
  include HyperMapper::Document
  
  attr_accessor :password
  
  # Determines, as in Rails, which attributes can be modified via mass assignment
  attr_accessible :username, :bio, :password
  
  # HyperMapper will generate a unique ID the first time this 
  # User is saved
  autogenerate_id
  
  # Create two attributes, :username, and :bio
  attribute :username
  attribute :bio
  
  # Things we'll need for authentication
  attribute :salt
  attribute :hashed_password
  attribute :session_id  
  
  # Maintain :created_at and :updated_at timestamps
  timestamps
    
end
```

Generating migrations is not yet supported, so we'll have to create the User space ourselves. `User.create_space` will do the work of making a call to the HyperDex client to create the new space.

```
~/# rails c
1.9.3p392 :001 > User.create_space
```


That's all it takes to start! If you fire up your Rails server you should be able to CRUD in HyperDex all the users you desire.  We aimed to support as much querying and creation functionality that you will be familiar with from using ActiveRecord in Rails.  You can call ```User.create!```, or ```User.new(username: "Matt", bio: "Hello world")```, or ```User.find('some_user_id')```.  Check out [the docs](https://github.com/goggin13/HyperMapper/blob/master/readme.md) for the rest of the Document API. But for now, you don't need to touch anything, as all the code from the scaffold generator will work as is. Start your Rails server and checkout `/users` to try out your first HyperDex CRUD operations through Rails.


#### Validations
Since HyperMapper includes many of the ActiveModel modules, we have access to validators and callback hooks.

Let's add some simple validators, just like we would in a ActiveRecord model.


```
class User
  include HyperMapper::Document
  
  …
  
  validates :username, presence: true,
                       format: /[a-zA-Z\s]+/
  validates :password, presence: true, if: "<PASSWORD>?"
end
```

{'fraction_non_alphanumeric': 0.07877312560856865, 'fraction_numerical': 0.013437195715676729, 'mean_word_length': 3.634927797833935, 'pattern_counts': {'":': 0, '<': 4, '<?xml version=': 0, '>': 8, 'https://': 7, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 8, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4378441', 'n_tokens_mistral': 3164, 'n_tokens_neox': 2837, 'n_words': 1301}