elasticsearch-model 0.1.9 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: e6ee0c4e1aa23d578d305367880c00683f8722eb
4
- data.tar.gz: e55f679c7973d5381225ca46514dd3d901a65aa4
3
+ metadata.gz: 3f2934457bc9ab48762cfab715d994d56b9421f0
4
+ data.tar.gz: 4c7ed85875ee9ab58ff390ad1e6e7a13d576807b
5
5
  SHA512:
6
- metadata.gz: e1bb3398d41326acb683669d4becd275f2f6bb9c4ef4ac8148d810c056d8e59df3ee0647f0dabaeb681d29cd94eff8fee7498fbc09cd3ec91a9abd2986bce953
7
- data.tar.gz: 7c7f7e24165e04f86494f5458944155cfa4c36f1e15acd58ede28d27372172885f74c74d1af16d6786960c0402eb0f58a24f223b58a3f865a61cb4a9f5851878
6
+ metadata.gz: df184cea73c42757b1c52afe22c009000310eaf5383d01b82055e51cb953f86701584b5afc56dadb9ef811e4ca87c92e8e67c9a7e84ef3a3bab680330c27f445
7
+ data.tar.gz: 34e576da4c6d6e0ea80ed5f175c226f1583332c29d3eb0fc8b488d4f7dbc0222ea3eba5e87001e7c3a7e79493a230cba402acfc7adcfa5b150d7e86e0a7086f0
data/.gitignore CHANGED
@@ -18,3 +18,4 @@ tmp
18
18
 
19
19
  gemfiles/3.0.gemfile.lock
20
20
  gemfiles/4.0.gemfile.lock
21
+ gemfiles/5.0.gemfile.lock
data/README.md CHANGED
@@ -1,13 +1,25 @@
1
1
  # Elasticsearch::Model
2
2
 
3
3
  The `elasticsearch-model` library builds on top of the
4
- the [`elasticsearch`](https://github.com/elasticsearch/elasticsearch-ruby) library.
4
+ the [`elasticsearch`](https://github.com/elastic/elasticsearch-ruby) library.
5
5
 
6
6
  It aims to simplify integration of Ruby classes ("models"), commonly found
7
7
  e.g. in [Ruby on Rails](http://rubyonrails.org) applications, with the
8
8
  [Elasticsearch](http://www.elasticsearch.org) search and analytics engine.
9
9
 
10
- The library is compatible with Ruby 1.9.3 and higher.
10
+ ## Compatibility
11
+
12
+ This library is compatible with Ruby 1.9.3 and higher.
13
+
14
+ The library version numbers follow the Elasticsearch major versions, and the `master` branch
15
+ is compatible with the Elasticsearch `master` branch, therefore, with the next major version.
16
+
17
+ | Rubygem | | Elasticsearch |
18
+ |:-------------:|:-:| :-----------: |
19
+ | 0.1 | → | 1.x |
20
+ | 2.x | → | 2.x |
21
+ | 5.x | → | 5.x |
22
+ | master | → | master |
11
23
 
12
24
  ## Installation
13
25
 
@@ -17,11 +29,11 @@ Install the package from [Rubygems](https://rubygems.org):
17
29
 
18
30
  To use an unreleased version, either add it to your `Gemfile` for [Bundler](http://bundler.io):
19
31
 
20
- gem 'elasticsearch-model', git: 'git://github.com/elasticsearch/elasticsearch-rails.git'
32
+ gem 'elasticsearch-model', git: 'git://github.com/elastic/elasticsearch-rails.git', branch: '5.x'
21
33
 
22
34
  or install it from a source code checkout:
23
35
 
24
- git clone https://github.com/elasticsearch/elasticsearch-rails.git
36
+ git clone https://github.com/elastic/elasticsearch-rails.git
25
37
  cd elasticsearch-rails/elasticsearch-model
26
38
  bundle install
27
39
  rake install
@@ -109,7 +121,7 @@ See the `Elasticsearch::Model` module documentation for technical information.
109
121
 
110
122
  ### The Elasticsearch client
111
123
 
112
- The module will set up a [client](https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch),
124
+ The module will set up a [client](https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch),
113
125
  connected to `localhost:9200`, by default. You can access and use it as any other `Elasticsearch::Client`:
114
126
 
115
127
  ```ruby
@@ -132,7 +144,7 @@ Elasticsearch::Model.client = Elasticsearch::Client.new log: true
132
144
  You might want to do this during your application bootstrap process, e.g. in a Rails initializer.
133
145
 
134
146
  Please refer to the
135
- [`elasticsearch-transport`](https://github.com/elasticsearch/elasticsearch-ruby/tree/master/elasticsearch-transport)
147
+ [`elasticsearch-transport`](https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-transport)
136
148
  library documentation for all the configuration options, and to the
137
149
  [`elasticsearch-api`](http://rubydoc.info/gems/elasticsearch-api) library documentation
138
150
  for information about the Ruby client API.
@@ -241,7 +253,7 @@ response.records.order(:title).to_a
241
253
  The `records` method returns the real instances of your model, which is useful when you want to access your
242
254
  model methods -- at the expense of slowing down your application, of course.
243
255
  In most cases, working with `results` coming from Elasticsearch is sufficient, and much faster. See the
244
- [`elasticsearch-rails`](https://github.com/elasticsearch/elasticsearch-rails/tree/master/elasticsearch-rails)
256
+ [`elasticsearch-rails`](https://github.com/elastic/elasticsearch-rails/tree/master/elasticsearch-rails)
245
257
  library for more information about compatibility with the Ruby on Rails framework.
246
258
 
247
259
  When you want to access both the database `records` and search `results`, use the `each_with_hit`
@@ -303,7 +315,7 @@ In a Rails controller, use the the `params[:page]` parameter to paginate through
303
315
  To initialize and include the Kaminari pagination support manually:
304
316
 
305
317
  ```ruby
306
- Kaminari::Hooks.init
318
+ Kaminari::Hooks.init if defined?(Kaminari::Hooks)
307
319
  Elasticsearch::Model::Response::Response.__send__ :include, Elasticsearch::Model::Response::Pagination::Kaminari
308
320
  ```
309
321
 
@@ -320,8 +332,8 @@ response.results.first.highlight.title
320
332
  # ["Quick brown <em>fox</em>"]
321
333
  ```
322
334
 
323
- You can pass any object which implements a `to_hash` method, or you can use your favourite JSON builder
324
- to build the search definition as a JSON string:
335
+ You can pass any object which implements a `to_hash` method, which is called automatically,
336
+ so you can use a custom class or your favourite JSON builder to build the search definition:
325
337
 
326
338
  ```ruby
327
339
  require 'jbuilder'
@@ -341,6 +353,25 @@ response.results.first.title
341
353
  # => "Quick brown fox"
342
354
  ```
343
355
 
356
+ Also, you can use the [**`elasticsearch-dsl`**](https://github.com/elastic/elasticsearch-ruby/tree/master/elasticsearch-dsl) library, which provides a specialized Ruby API for
357
+ the Elasticsearch Query DSL:
358
+
359
+ ```ruby
360
+ require 'elasticsearch/dsl'
361
+
362
+ query = Elasticsearch::DSL::Search.search do
363
+ query do
364
+ match :title do
365
+ query 'fox dogs'
366
+ end
367
+ end
368
+ end
369
+
370
+ response = Article.search query
371
+ response.results.first.title
372
+ # => "Quick brown fox"
373
+ ```
374
+
344
375
  ### Index Configuration
345
376
 
346
377
  For proper search engine function, it's often necessary to configure the index properly.
@@ -685,6 +716,18 @@ response.records.records.class
685
716
  More examples can be found in the `examples` folder. Please see the `Elasticsearch::Model::Adapter`
686
717
  module and its submodules for technical information.
687
718
 
719
+ ### Settings
720
+
721
+ The module provides a common `settings` method to customize various features.
722
+
723
+ At the moment, the only supported setting is `:inheritance_enabled`, which makes the class receiving the module
724
+ respect index names and document types of a super-class, eg. in case you're using "single table inheritance" (STI)
725
+ in Rails:
726
+
727
+ ```ruby
728
+ Elasticsearch::Model.settings[:inheritance_enabled] = true
729
+ ```
730
+
688
731
  ## Development and Community
689
732
 
690
733
  For local development, clone the repository and run `bundle install`. See `rake -T` for a list of
data/Rakefile CHANGED
@@ -4,40 +4,49 @@ desc "Run unit tests"
4
4
  task :default => 'test:unit'
5
5
  task :test => 'test:unit'
6
6
 
7
+ namespace :bundler do
8
+ desc "Install dependencies for all the Gemfiles"
9
+ task :install do
10
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/3.0.gemfile', __FILE__)}' bundle install"
11
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/4.0.gemfile', __FILE__)}' bundle install"
12
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/5.0.gemfile', __FILE__)}' bundle install"
13
+ end
14
+ end
15
+
7
16
  # ----- Test tasks ------------------------------------------------------------
8
17
 
9
18
  require 'rake/testtask'
10
19
  namespace :test do
11
- task :ci_reporter do
12
- ENV['CI_REPORTS'] ||= 'tmp/reports'
13
- require 'ci/reporter/rake/minitest'
14
- Rake::Task['ci:setup:minitest'].invoke
15
- end
16
-
17
- Rake::TestTask.new(:unit) do |test|
18
- Rake::Task['test:ci_reporter'].invoke if ENV['CI']
20
+ Rake::TestTask.new(:run_unit) do |test|
19
21
  test.libs << 'lib' << 'test'
20
22
  test.test_files = FileList["test/unit/**/*_test.rb"]
21
- # test.verbose = true
22
- # test.warning = true
23
+ test.verbose = false
24
+ test.warning = false
23
25
  end
24
26
 
25
27
  Rake::TestTask.new(:run_integration) do |test|
26
- Rake::Task['test:ci_reporter'].invoke if ENV['CI']
27
28
  test.libs << 'lib' << 'test'
28
29
  test.test_files = FileList["test/integration/**/*_test.rb"]
30
+ test.verbose = false
31
+ test.warning = false
32
+ end
33
+
34
+ desc "Run unit tests against ActiveModel 3, 4 and 5"
35
+ task :unit do
36
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/3.0.gemfile', __FILE__)}' bundle exec rake test:run_unit"
37
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/4.0.gemfile', __FILE__)}' bundle exec rake test:run_unit"
38
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/5.0.gemfile', __FILE__)}' bundle exec rake test:run_unit"
29
39
  end
30
40
 
31
- desc "Run integration tests against ActiveModel 3 and 4"
41
+ desc "Run integration tests against ActiveModel 3, 4 and 5"
32
42
  task :integration do
33
- sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/3.0.gemfile', __FILE__)}' bundle exec rake test:run_integration" unless defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
43
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/3.0.gemfile', __FILE__)}' bundle exec rake test:run_integration"
34
44
  sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/4.0.gemfile', __FILE__)}' bundle exec rake test:run_integration"
45
+ sh "BUNDLE_GEMFILE='#{File.expand_path('../gemfiles/5.0.gemfile', __FILE__)}' bundle exec rake test:run_integration"
35
46
  end
36
47
 
37
48
  desc "Run unit and integration tests"
38
49
  task :all do
39
- Rake::Task['test:ci_reporter'].invoke if ENV['CI']
40
-
41
50
  Rake::Task['test:unit'].invoke
42
51
  Rake::Task['test:integration'].invoke
43
52
  end
@@ -23,35 +23,32 @@ Gem::Specification.new do |s|
23
23
 
24
24
  s.required_ruby_version = ">= 1.9.3"
25
25
 
26
- s.add_dependency "elasticsearch", '> 0.4'
26
+ s.add_dependency "elasticsearch", '~> 1.1'
27
27
  s.add_dependency "activesupport", '> 3'
28
28
  s.add_dependency "hashie"
29
29
 
30
30
  s.add_development_dependency "bundler", "~> 1.3"
31
- s.add_development_dependency "rake", "< 11.0"
31
+ s.add_development_dependency "rake", "~> 11.1"
32
32
 
33
33
  s.add_development_dependency "elasticsearch-extensions"
34
34
 
35
35
  s.add_development_dependency "sqlite3"
36
- s.add_development_dependency "activemodel", "> 3.0"
36
+ s.add_development_dependency "activemodel", "> 3"
37
37
 
38
38
  s.add_development_dependency "oj"
39
39
  s.add_development_dependency "kaminari"
40
40
  s.add_development_dependency "will_paginate"
41
41
 
42
- s.add_development_dependency "minitest", "~> 4.2"
43
- s.add_development_dependency "test-unit" if defined?(RUBY_VERSION) && RUBY_VERSION > '2.2'
42
+ s.add_development_dependency "minitest"
43
+ s.add_development_dependency "test-unit"
44
44
  s.add_development_dependency "shoulda-context"
45
45
  s.add_development_dependency "mocha"
46
46
  s.add_development_dependency "turn"
47
47
  s.add_development_dependency "yard"
48
48
  s.add_development_dependency "ruby-prof"
49
49
  s.add_development_dependency "pry"
50
- s.add_development_dependency "ci_reporter", "~> 1.9"
51
50
 
52
- if defined?(RUBY_VERSION) && RUBY_VERSION > '1.9'
53
- s.add_development_dependency "simplecov"
54
- s.add_development_dependency "cane"
55
- s.add_development_dependency "require-prof"
56
- end
51
+ s.add_development_dependency "simplecov"
52
+ s.add_development_dependency "cane"
53
+ s.add_development_dependency "require-prof"
57
54
  end
@@ -26,7 +26,7 @@ ActiveRecord::Schema.define(version: 1) do
26
26
  end
27
27
  end
28
28
 
29
- Kaminari::Hooks.init
29
+ Kaminari::Hooks.init if defined?(Kaminari::Hooks) if defined?(Kaminari::Hooks)
30
30
 
31
31
  class Article < ActiveRecord::Base
32
32
  end
@@ -28,23 +28,23 @@ ActiveRecord::Base.establish_connection( adapter: 'sqlite3', database: ":memory:
28
28
  ActiveRecord::Schema.define(version: 1) do
29
29
  create_table :categories do |t|
30
30
  t.string :title
31
- t.timestamps
31
+ t.timestamps null: false
32
32
  end
33
33
 
34
34
  create_table :authors do |t|
35
35
  t.string :first_name, :last_name
36
- t.timestamps
36
+ t.timestamps null: false
37
37
  end
38
38
 
39
39
  create_table :authorships do |t|
40
40
  t.references :article
41
41
  t.references :author
42
- t.timestamps
42
+ t.timestamps null: false
43
43
  end
44
44
 
45
45
  create_table :articles do |t|
46
46
  t.string :title
47
- t.timestamps
47
+ t.timestamps null: false
48
48
  end
49
49
 
50
50
  create_table :articles_categories, id: false do |t|
@@ -54,9 +54,10 @@ ActiveRecord::Schema.define(version: 1) do
54
54
  create_table :comments do |t|
55
55
  t.string :text
56
56
  t.references :article
57
- t.timestamps
57
+ t.timestamps null: false
58
58
  end
59
- add_index(:comments, :article_id)
59
+
60
+ add_index(:comments, :article_id) unless index_exists?(:comments, :article_id)
60
61
  end
61
62
 
62
63
  # ----- Elasticsearch client setup ----------------------------------------------------------------
@@ -0,0 +1,12 @@
1
+ # Usage:
2
+ #
3
+ # $ BUNDLE_GEMFILE=./gemfiles/5.0.gemfile bundle install
4
+ # $ BUNDLE_GEMFILE=./gemfiles/5.0.gemfile bundle exec rake test:integration
5
+
6
+ source 'https://rubygems.org'
7
+
8
+ gemspec path: '../'
9
+
10
+ gem 'activemodel', '~> 5'
11
+ gem 'activerecord', '~> 5'
12
+ gem 'sqlite3'
@@ -31,6 +31,7 @@ require 'elasticsearch/model/response/result'
31
31
  require 'elasticsearch/model/response/results'
32
32
  require 'elasticsearch/model/response/records'
33
33
  require 'elasticsearch/model/response/pagination'
34
+ require 'elasticsearch/model/response/aggregations'
34
35
  require 'elasticsearch/model/response/suggestions'
35
36
 
36
37
  require 'elasticsearch/model/ext/active_record'
@@ -129,8 +130,13 @@ module Elasticsearch
129
130
  end
130
131
  end
131
132
 
132
- module ClassMethods
133
+ # Access the module settings
134
+ #
135
+ def self.settings
136
+ @settings ||= {}
137
+ end
133
138
 
139
+ module ClassMethods
134
140
  # Get the client common for all models
135
141
  #
136
142
  # @example Get the client
@@ -180,6 +186,24 @@ module Elasticsearch
180
186
  request = Searching::SearchRequest.new(models, query_or_payload, options)
181
187
  Response::Response.new(models, request)
182
188
  end
189
+
190
+ # Check if inheritance is enabled
191
+ #
192
+ # @note Inheritance is disabled by default.
193
+ #
194
+ def inheritance_enabled
195
+ @inheritance_enabled ||= false
196
+ end
197
+
198
+ # Enable inheritance of index_name and document_type
199
+ #
200
+ # @example Enable inheritance
201
+ #
202
+ # Elasticsearch::Model.inheritance_enabled = true
203
+ #
204
+ def inheritance_enabled=(inheritance_enabled)
205
+ @inheritance_enabled = inheritance_enabled
206
+ end
183
207
  end
184
208
  extend ClassMethods
185
209
 
@@ -26,14 +26,17 @@ module Elasticsearch
26
26
  # by redefining `to_a`, unless the user has called `order()`
27
27
  #
28
28
  sql_records.instance_exec(response.response['hits']['hits']) do |hits|
29
- define_singleton_method :to_a do
29
+ ar_records_method_name = :to_a
30
+ ar_records_method_name = :records if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 5
31
+
32
+ define_singleton_method(ar_records_method_name) do
30
33
  if defined?(::ActiveRecord) && ::ActiveRecord::VERSION::MAJOR >= 4
31
34
  self.load
32
35
  else
33
36
  self.__send__(:exec_queries)
34
37
  end
35
38
  @records.sort_by { |record| hits.index { |hit| hit['_id'].to_s == record.id.to_s } }
36
- end
39
+ end if self
37
40
  end
38
41
 
39
42
  sql_records
@@ -42,7 +45,7 @@ module Elasticsearch
42
45
  # Prevent clash with `ActiveSupport::Dependencies::Loadable`
43
46
  #
44
47
  def load
45
- records.load
48
+ records.__send__(:load)
46
49
  end
47
50
 
48
51
  # Intercept call to the `order` method, so we can ignore the order from Elasticsearch
@@ -34,7 +34,7 @@ module Elasticsearch
34
34
  if @index_name.respond_to?(:call)
35
35
  @index_name.call
36
36
  else
37
- @index_name || self.model_name.collection.gsub(/\//, '-')
37
+ @index_name || implicit(:index_name)
38
38
  end
39
39
  end
40
40
 
@@ -58,7 +58,7 @@ module Elasticsearch
58
58
  # Article.document_type "my-article"
59
59
  #
60
60
  def document_type name=nil
61
- @document_type = name || @document_type || self.model_name.element
61
+ @document_type = name || @document_type || implicit(:document_type)
62
62
  end
63
63
 
64
64
 
@@ -69,6 +69,30 @@ module Elasticsearch
69
69
  def document_type=(name)
70
70
  @document_type = name
71
71
  end
72
+
73
+ private
74
+
75
+ def implicit(prop)
76
+ value = nil
77
+
78
+ if Elasticsearch::Model.settings[:inheritance_enabled]
79
+ self.ancestors.each do |klass|
80
+ next if klass == self
81
+ break if value = klass.respond_to?(prop) && klass.send(prop)
82
+ end
83
+ end
84
+
85
+ value || self.send("default_#{prop}")
86
+ end
87
+
88
+ def default_index_name
89
+ self.model_name.collection.gsub(/\//, '-')
90
+ end
91
+
92
+ def default_document_type
93
+ self.model_name.element
94
+ end
95
+
72
96
  end
73
97
 
74
98
  module InstanceMethods