elasticsearch-model 0.1.9 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
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