elasticsearch/elasticsearch-rails — pull request #91 by karmi (2014-04-28 17:28:57+00:00)
Title: Persistence implementation: ActiveRecord pattern

Implement an ActiveRecord-based persistence for model, oriented mainly towards Rails applications, similar to `Tire::Persistence`.

Using the `Elasticsearch::Persistence::Repository` from #71, this patch adds support for the [ActiveRecord pattern](http://www.martinfowler.com/eaaCatalog/activeRecord.html) of persistance for Ruby objects in Elasticsearch.

The goal is to have a 1:1 implementation to the ActiveRecord::Base implementation,
allowing to use it as a drop-in replacement for similar OxMs in Rails applications,
with minimal changes to the model definition and application code.

The model implementation uses [Virtus](https://github.com/solnic/virtus)
for handling the model attributes, and [ActiveModel](https://github.com/rails/rails/tree/master/activemodel)
for validations, callbacks, and similar model-related features.

```ruby
require 'elasticsearch/persistence/model'

class Person
include Elasticsearch::Persistence::Model

settings index: { number_of_shards: 1 }

attribute :name, String,
mapping: { fields: {
name: { type: 'string', analyzer: 'snowball' },
raw: { type: 'string', analyzer: 'keyword' }
} }

attribute :birthday, Date
attribute :department, String
attribute :salary, Integer
attribute :admin, Boolean, default: false

validates :name, presence: true

before_save do
puts "About to save: #{self}"
end
end

Person.gateway.create_index! force: true

person = Person.create name: 'John Smith', salary: 10_000
# About to save: #
# => #

person.id
# => "zNf3yxZDQsOTZfNfTX4E5A"

person = Person.find(person.id)
# => #

person.salary
# => 10000

person.increment :salary
# => { ... "_version"=>2}
person.salary
# => 10001

person.update admin: true
# => { ... "_version"=>3}

Person.search('smith').to_a
# => [#]
```

## TODO

- [x] ActiveRecord (Model) pattern
- [x] Integration tests
- [ ] Example application for Model (Rails)