===========================
Ruby And Rails Integrations
===========================

The Ruby Client
===============

The ``elasticsearch``
`Rubygem <http://rubygems.org/gems/elasticsearch>`__ provides a
low-level client for communicating with an Elasticsearch cluster, fully
compatible with other official clients.

Full documentation is hosted at
`Github <http://github.com/elasticsearch/elasticsearch-ruby>`__ and
`RubyDoc <http://rubydoc.info/gems/elasticsearch>`__ — this
documentation provides only an overview of features.

Elasticsearch Version Compatibility
-----------------------------------

The Ruby API is compatible with both Elasticsearch 0.90.x and 1.0.x
versions, you have to install a matching `gem
version <http://rubygems.org/gems/elasticsearch/versions>`__, though:

+--------------------------------------+--------------------------------------+
| Elasticsearch version                | Ruby gem version                     |
+======================================+======================================+
| 0.90.x                               | 0.4.x                                |
+--------------------------------------+--------------------------------------+
| 1.x                                  | 1.x                                  |
+--------------------------------------+--------------------------------------+

Installation
------------

Install the Ruby gem for Elasticsearch **1.x**:

.. code:: sh

    gem install elasticsearch

…or add it do your Gemfile:

.. code:: ruby

    gem 'elasticsearch'

Install the Ruby gem for Elasticsearch **0.90.x**:

.. code:: sh

    gem install elasticsearch -v 0.4.10

…or add it do your Gemfile:

.. code:: ruby

    gem 'elasticsearch', '~> 0.4'

Example Usage
-------------

.. code:: ruby

    require 'elasticsearch'

    client = Elasticsearch::Client.new log: true

    client.cluster.health

    client.index index: 'my-index', type: 'my-document', id: 1, body: { title: 'Test' }

    client.indices.refresh index: 'my-index'

    client.search index: 'my-index', body: { query: { match: { title: 'test' } } }

Features at a Glance
--------------------

-  Pluggable logging and tracing

-  Plugabble connection selection strategies (round-robin, random,
   custom)

-  Pluggable transport implementation, customizable and extendable

-  Pluggable serializer implementation

-  Request retries and dead connections handling

-  Node reloading (based on cluster state) on errors or on demand

-  Modular API implementation

-  100% REST API coverage

Transport and API
-----------------

The ``elasticsearch`` gem combines two separate Ruybygems:

-  ```elasticsearch-transport`` <https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-transport>`__
   provides a HTTP Ruby client for connecting to the Elasticsearch
   cluster,

-  ```elasticsearch-api`` <https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-api>`__
   provides a Ruby API for the Elasticsearch RESTful API.

Please see their respective documentation for configuration options and
technical details.

Notably, the documentation and comprehensive examples for all the API
methods is contained in the source, and available online at
`Rubydoc <http://rubydoc.info/gems/elasticsearch-api/Elasticsearch/API/Actions>`__.

Keep in mind, that for optimal performance, you should use a HTTP
library which supports persistent ("keep-alive") HTTP connections.

Extensions
----------

The
```elasticsearch-extensions`` <https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-extensions>`__
Rubygem provides a number of extensions to the core client, such as an
API to programatically launch Elasticsearch clusters (eg. for testing
purposes), and more.

Please see its
`documentation <https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-extensions>`__
for more information.

ActiveModel / ActiveRecord
==========================

The ``elasticsearch-model``
`Rubygem <http://rubygems.org/gems/elasticsearch-model>`__ provides
integration with Ruby domain objects ("models"), commonly found e.g. in
Ruby on Rails applications.

It uses the ``elasticsearch`` Rubygem as the client communicating with
the Elasticsearch cluster.

Features at a Glance
--------------------

-  ActiveModel integration with adapters for ActiveRecord and Mongoid

-  Enumerable-based wrapper for search results

-  ActiveRecord::Relation-based wrapper for returning search results as
   records

-  Convenience model methods such as ``search``, ``mapping``,
   ``import``, etc

-  Support for Kaminari and WillPaginate pagination

-  Extension implemented via proxy object to shield model namespace from
   collisions

-  Convenience methods for (re)creating the index, setting up mappings,
   indexing documents, …

Usage
-----

Add the library to your Gemfile:

.. code:: ruby

    gem 'elasticsearch-rails'

Include the extension module in your model class:

.. code:: ruby

    class Article < ActiveRecord::Base
      include Elasticsearch::Model
    end

Import some data and perform a search:

.. code:: ruby

    Article.import

    response = Article.search 'fox dog'
    response.took
    # => 3

It is possible to either return results as model instances, or decorated
documents from Elasticsearch, with the ``records`` and ``results``
methods, respectively:

.. code:: ruby

    response.records.first
    # Article Load (0.4ms)  SELECT "articles".* FROM "articles"  WHERE ...
    => #<Article id: 3, title: "Foo " ...>

    response.results.first._score
    # => 0.02250402

    response.results.first._source.title
    # => "Quick brown fox"

Please see the full
`documentation <https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-model>`__
for more information.

Ruby On Rails
=============

The ``elasticsearch-rails``
`Rubygem <http://rubygems.org/gems/elasticsearch-rails>`__ provides
features suitable for Ruby on Rails applications.

Features at a Glance
--------------------

-  Rake tasks for importing data from application models

-  Integration with Rails' instrumentation framework

-  Templates for generating example Rails application

Example applications
--------------------

You can generate a fully working example Ruby on Rails application with
templates provides.

Please refer to the
`documentation <https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-rails>`__
for more information.

Persistence
===========

The ``elasticsearch-persistence``
`Rubygem <http://rubygems.org/gems/elasticsearch-persistence>`__
provides persistence layer for Ruby domain objects.

It supports two design patterns for integrating with your objects:
*repository* and *active record*.

Repository
----------

The ``Elasticsearch::Persistence::Repository`` module provides an
implementation of the repository pattern and allows to save, delete,
find and search objects stored in Elasticsearch, as well as configure
mappings and settings for the index.

Features At a Glance
~~~~~~~~~~~~~~~~~~~~

-  Access to the Elasticsearch client

-  Setting the index name, document type, and object class for
   deserialization

-  Composing mappings and settings for the index

-  Creating, deleting or refreshing the index

-  Finding or searching for documents

-  Providing access both to domain objects and hits for search results

-  Providing access to the Elasticsearch response for search results
   (aggregations, total, …)

-  Defining the methods for serialization and deserialization

Usage
~~~~~

Let’s have a simple plain old Ruby object (PORO):

.. code:: ruby

    class Note
      attr_reader :attributes

      def initialize(attributes={})
        @attributes = attributes
      end

      def to_hash
        @attributes
      end
    end

Let’s create a default, "dumb" repository, as a first step:

.. code:: ruby

    require 'elasticsearch/persistence'
    repository = Elasticsearch::Persistence::Repository.new

We can save a ``Note`` instance into the repository, find it, search it,
delete it:

.. code:: ruby

    note = Note.new id: 1, text: 'Test'

    repository.save(note)
    # PUT http://localhost:9200/repository/note/1
    # > {"id":1,"text":"Test"}
    # < {"_index":"repository","_type":"note","_id":"1","_version":1,"created":true}

    n = repository.find(1)
    # GET http://localhost:9200/repository/_all/1
    # < {"_index":"repository","_type":"note","_id":"1","_version":2,"found":true, "_source" : {"id":1,"text":"Test"}}
    => <Note:0x007fcbfc0c4980 @attributes={"id"=>1, "text"=>"Test"}>

    repository.search(query: { match: { text: 'test' } }).first
    # GET http://localhost:9200/repository/_search
    # > {"query":{"match":{"text":"test"}}}
    # < {"took":2, ... "hits":{"total":1, ... "hits":[{ ... "_source" : {"id":1,"text":"Test"}}]}}
    => <Note:0x007fcbfc1c7b70 @attributes={"id"=>1, "text"=>"Test"}>

    repository.delete(note)
    # DELETE http://localhost:9200/repository/note/1
    # < {"found":true,"_index":"repository","_type":"note","_id":"1","_version":3}
    => {"found"=>true, "_index"=>"repository", "_type"=>"note", "_id"=>"1", "_version"=>2}

The repository module provides a number of features and facilities to
configure and customize the behaviour, as well as support for extending
your own, custom repository class.

Please refer to the
`documentation <https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-persistence#the-repository-pattern>`__
for more information.

Also, check out the `example
application <https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-persistence#example-application>`__
which demonstrates the usage patterns of the *repository* approach to
persistence.

Active Record
-------------

The ‘Elasticsearch::Persistence::Model\` module provides an
implementation of the active record pattern, with a familiar interface
for using Elasticsearch as a persistence layer in Ruby on Rails
applications. The model is fully compatible with Rails’ conventions and
helpers, such as ``url_for``.

All the methods are documented with comprehensive examples in the source
code, available also
`online <http://rubydoc.info/gems/elasticsearch-persistence/Elasticsearch/Persistence/Model>`__.

Features At a Glance
~~~~~~~~~~~~~~~~~~~~

-  Familiar interface for persistence methods from ActiveRecord

-  Common model features such as validations and callbacks

-  Methods for defining model attributes, including Elasticsearch
   mappings

-  Support for fetching data in bulk (``find_in_batches``,
   ``find_each``)

-  Decorated search results for easy access to model instances and meta
   data (such as highlights or aggregations)

-  Easy access to the underlying gateway and client

Usage
~~~~~

To use the library in a Rails application, add it to your Gemfile with a
require statement:

.. code:: ruby

    gem "elasticsearch-persistence", require: 'elasticsearch/persistence/model'

Include the module in a plain Ruby class, and set up the properties,
mappings, etc:

.. code:: ruby

    class Article
      include Elasticsearch::Persistence::Model

      # Define a plain `title` attribute
      #
      attribute :title,  String

      # Define an `author` attribute, with multiple analyzers for this field
      #
      attribute :author, String, mapping: { fields: {
                                   author: { type: 'string'},
                                   raw:    { type: 'string', analyzer: 'keyword' }
                                 } }


      # Define a `views` attribute, with default value
      #
      attribute :views,  Integer, default: 0, mapping: { type: 'integer' }

      # Validate the presence of the `title` attribute
      #
      validates :title, presence: true

      # Execute code after saving the model.
      #
      after_save { puts "Successfuly saved: #{self}" }
    end

The model attribute definition support is implemented with the
`*Virtus* <https://github.com/solnic/virtus>`__ Rubygem, and the naming,
validation, etc. features with the
`*ActiveModel* <https://github.com/rails/rails/tree/master/activemodel>`__
Rubygem.

Attribute validations work like for any other ActiveModel-compatible
implementation:

.. code:: ruby

    article = Article.new                                                                                             # => #<Article { ... }>

    article.valid?
    # => false

    article.errors.to_a
    # => ["Title can't be blank"]

We can create a new article in the database and find it:

.. code:: ruby

    Article.create id: 1, title: 'Test', author: 'John'
    # PUT http://localhost:9200/articles/article/1 [status:201, request:0.015s, query:n/a]

    article = Article.find(1)
    # => #<Article { ... }>

    article._index
    # => "articles"

    article.id
    # => "1"

    article.title
    # => "Test"

To update the model, either update the attribute and save the model or
use the ``update_attributes`` method:

.. code:: ruby

    article.title = 'Updated'

    article.save
    # => {"_index"=>"articles", "_type"=>"article", "_id"=>"1", "_version"=>2, "created"=>false}

    article.update_attributes title: 'Test', author: 'Mary'
    # => {"_index"=>"articles", "_type"=>"article", "_id"=>"1", "_version"=>3}

The implementation supports the familiar interface for updating model
timestamps and numeric attributes:

.. code:: ruby

    article.touch
    # => => { ... "_version"=>4}

    article.views
    # => 0

    article.increment :views
    article.views
    # => 1

Any callbacks defined in the model will be triggered during the
persistence operations:

.. code:: ruby

    article.save
    # Successfuly saved: #<Article {...}>

Please see the extensive documentation in the library
`README <https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-persistence#the-activerecord-pattern>`__
for detailed information.

Also, check out the `example
application <https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-persistence#example-application-1>`__
which demonstrates the usage patterns of the *active record* approach to
persistence.

Copyright and License
=====================

This software is Copyright (c) 2013 by Elasticsearch BV.

This is free software, licensed under The Apache License Version 2.0.
