elasticsearch-model-queryable 0.1.5

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.
Files changed (70) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/CHANGELOG.md +26 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +13 -0
  6. data/README.md +695 -0
  7. data/Rakefile +59 -0
  8. data/elasticsearch-model.gemspec +57 -0
  9. data/examples/activerecord_article.rb +77 -0
  10. data/examples/activerecord_associations.rb +162 -0
  11. data/examples/couchbase_article.rb +66 -0
  12. data/examples/datamapper_article.rb +71 -0
  13. data/examples/mongoid_article.rb +68 -0
  14. data/examples/ohm_article.rb +70 -0
  15. data/examples/riak_article.rb +52 -0
  16. data/gemfiles/3.0.gemfile +12 -0
  17. data/gemfiles/4.0.gemfile +11 -0
  18. data/lib/elasticsearch/model/adapter.rb +145 -0
  19. data/lib/elasticsearch/model/adapters/active_record.rb +104 -0
  20. data/lib/elasticsearch/model/adapters/default.rb +50 -0
  21. data/lib/elasticsearch/model/adapters/mongoid.rb +92 -0
  22. data/lib/elasticsearch/model/callbacks.rb +35 -0
  23. data/lib/elasticsearch/model/client.rb +61 -0
  24. data/lib/elasticsearch/model/ext/active_record.rb +14 -0
  25. data/lib/elasticsearch/model/hash_wrapper.rb +15 -0
  26. data/lib/elasticsearch/model/importing.rb +144 -0
  27. data/lib/elasticsearch/model/indexing.rb +472 -0
  28. data/lib/elasticsearch/model/naming.rb +101 -0
  29. data/lib/elasticsearch/model/proxy.rb +127 -0
  30. data/lib/elasticsearch/model/response/base.rb +44 -0
  31. data/lib/elasticsearch/model/response/pagination.rb +173 -0
  32. data/lib/elasticsearch/model/response/records.rb +69 -0
  33. data/lib/elasticsearch/model/response/result.rb +63 -0
  34. data/lib/elasticsearch/model/response/results.rb +31 -0
  35. data/lib/elasticsearch/model/response.rb +71 -0
  36. data/lib/elasticsearch/model/searching.rb +107 -0
  37. data/lib/elasticsearch/model/serializing.rb +35 -0
  38. data/lib/elasticsearch/model/version.rb +5 -0
  39. data/lib/elasticsearch/model.rb +157 -0
  40. data/test/integration/active_record_associations_parent_child.rb +139 -0
  41. data/test/integration/active_record_associations_test.rb +307 -0
  42. data/test/integration/active_record_basic_test.rb +179 -0
  43. data/test/integration/active_record_custom_serialization_test.rb +62 -0
  44. data/test/integration/active_record_import_test.rb +100 -0
  45. data/test/integration/active_record_namespaced_model_test.rb +49 -0
  46. data/test/integration/active_record_pagination_test.rb +132 -0
  47. data/test/integration/mongoid_basic_test.rb +193 -0
  48. data/test/test_helper.rb +63 -0
  49. data/test/unit/adapter_active_record_test.rb +140 -0
  50. data/test/unit/adapter_default_test.rb +41 -0
  51. data/test/unit/adapter_mongoid_test.rb +102 -0
  52. data/test/unit/adapter_test.rb +69 -0
  53. data/test/unit/callbacks_test.rb +31 -0
  54. data/test/unit/client_test.rb +27 -0
  55. data/test/unit/importing_test.rb +176 -0
  56. data/test/unit/indexing_test.rb +478 -0
  57. data/test/unit/module_test.rb +57 -0
  58. data/test/unit/naming_test.rb +76 -0
  59. data/test/unit/proxy_test.rb +89 -0
  60. data/test/unit/response_base_test.rb +40 -0
  61. data/test/unit/response_pagination_kaminari_test.rb +189 -0
  62. data/test/unit/response_pagination_will_paginate_test.rb +208 -0
  63. data/test/unit/response_records_test.rb +91 -0
  64. data/test/unit/response_result_test.rb +90 -0
  65. data/test/unit/response_results_test.rb +31 -0
  66. data/test/unit/response_test.rb +67 -0
  67. data/test/unit/searching_search_request_test.rb +78 -0
  68. data/test/unit/searching_test.rb +41 -0
  69. data/test/unit/serializing_test.rb +17 -0
  70. metadata +466 -0
@@ -0,0 +1,91 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::RecordsTest < Test::Unit::TestCase
4
+ context "Response records" do
5
+ class DummyCollection
6
+ include Enumerable
7
+
8
+ def each(&block); ['FOO'].each(&block); end
9
+ def size; ['FOO'].size; end
10
+ def empty?; ['FOO'].empty?; end
11
+ def foo; 'BAR'; end
12
+ end
13
+
14
+ class DummyModel
15
+ def self.index_name; 'foo'; end
16
+ def self.document_type; 'bar'; end
17
+
18
+ def self.find(*args)
19
+ DummyCollection.new
20
+ end
21
+ end
22
+
23
+ RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'_id' => '1', 'foo' => 'bar'}] } }
24
+ RESULTS = Elasticsearch::Model::Response::Results.new DummyModel, RESPONSE
25
+
26
+ setup do
27
+ search = Elasticsearch::Model::Searching::SearchRequest.new DummyModel, '*'
28
+ search.stubs(:execute!).returns RESPONSE
29
+
30
+ response = Elasticsearch::Model::Response::Response.new DummyModel, search
31
+ @records = Elasticsearch::Model::Response::Records.new DummyModel, response
32
+ end
33
+
34
+ should "access the records" do
35
+ assert_respond_to @records, :records
36
+ assert_equal 1, @records.records.size
37
+ assert_equal 'FOO', @records.records.first
38
+ end
39
+
40
+ should "delegate Enumerable methods to records" do
41
+ assert ! @records.empty?
42
+ assert_equal 'FOO', @records.first
43
+ end
44
+
45
+ should "delegate methods to records" do
46
+ assert_respond_to @records, :foo
47
+ assert_equal 'BAR', @records.foo
48
+ end
49
+
50
+ should "have each_with_hit method" do
51
+ @records.each_with_hit do |record, hit|
52
+ assert_equal 'FOO', record
53
+ assert_equal 'bar', hit.foo
54
+ end
55
+ end
56
+
57
+ should "have map_with_hit method" do
58
+ assert_equal ['FOO---bar'], @records.map_with_hit { |record, hit| "#{record}---#{hit.foo}" }
59
+ end
60
+
61
+ should "return the IDs" do
62
+ assert_equal ['1'], @records.ids
63
+ end
64
+
65
+ context "with adapter" do
66
+ module DummyAdapter
67
+ module RecordsMixin
68
+ def records
69
+ ['FOOBAR']
70
+ end
71
+ end
72
+
73
+ def records_mixin
74
+ RecordsMixin
75
+ end; module_function :records_mixin
76
+ end
77
+
78
+ should "delegate the records method to the adapter" do
79
+ Elasticsearch::Model::Adapter.expects(:from_class)
80
+ .with(DummyModel)
81
+ .returns(DummyAdapter)
82
+
83
+ @records = Elasticsearch::Model::Response::Records.new DummyModel,
84
+ RESPONSE
85
+
86
+ assert_equal ['FOOBAR'], @records.records
87
+ end
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,90 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::ResultTest < Test::Unit::TestCase
4
+ context "Response result" do
5
+
6
+ should "have method access to properties" do
7
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', bar: { bam: 'baz' }
8
+
9
+ assert_respond_to result, :foo
10
+ assert_respond_to result, :bar
11
+
12
+ assert_equal 'bar', result.foo
13
+ assert_equal 'baz', result.bar.bam
14
+
15
+ assert_raise(NoMethodError) { result.xoxo }
16
+ end
17
+
18
+ should "return _id as #id" do
19
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _id: 42, _source: { id: 12 }
20
+
21
+ assert_equal 42, result.id
22
+ assert_equal 12, result._source.id
23
+ end
24
+
25
+ should "return _type as #type" do
26
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _type: 'baz', _source: { type: 'BAM' }
27
+
28
+ assert_equal 'baz', result.type
29
+ assert_equal 'BAM', result._source.type
30
+ end
31
+
32
+ should "delegate method calls to `_source` when available" do
33
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'baz' }
34
+
35
+ assert_respond_to result, :foo
36
+ assert_respond_to result, :_source
37
+ assert_respond_to result, :bar
38
+
39
+ assert_equal 'bar', result.foo
40
+ assert_equal 'baz', result._source.bar
41
+ assert_equal 'baz', result.bar
42
+ end
43
+
44
+ should "delegate existence method calls to `_source`" do
45
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: { bam: 'baz' } }
46
+
47
+ assert_respond_to result._source, :bar?
48
+ assert_respond_to result, :bar?
49
+
50
+ assert_equal true, result._source.bar?
51
+ assert_equal true, result.bar?
52
+ assert_equal false, result.boo?
53
+
54
+ assert_equal true, result.bar.bam?
55
+ assert_equal false, result.bar.boo?
56
+ end
57
+
58
+ should "delegate methods to @result" do
59
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar'
60
+
61
+ assert_equal 'bar', result.foo
62
+ assert_equal 'bar', result.fetch('foo')
63
+ assert_equal 'moo', result.fetch('NOT_EXIST', 'moo')
64
+ assert_equal ['foo'], result.keys
65
+
66
+ assert_respond_to result, :to_hash
67
+ assert_equal({'foo' => 'bar'}, result.to_hash)
68
+
69
+ assert_raise(NoMethodError) { result.does_not_exist }
70
+ end
71
+
72
+ should "delegate existence method calls to @result" do
73
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar', _source: { bar: 'bam' }
74
+ assert_respond_to result, :foo?
75
+
76
+ assert_equal true, result.foo?
77
+ assert_equal false, result.boo?
78
+ assert_equal false, result._source.foo?
79
+ assert_equal false, result._source.boo?
80
+ end
81
+
82
+ should "delegate as_json to @result even when ActiveSupport changed half of Ruby" do
83
+ require 'active_support/json/encoding'
84
+ result = Elasticsearch::Model::Response::Result.new foo: 'bar'
85
+
86
+ result.instance_variable_get(:@result).expects(:as_json)
87
+ result.as_json(except: 'foo')
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,31 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::ResultsTest < Test::Unit::TestCase
4
+ context "Response results" do
5
+ class OriginClass
6
+ def self.index_name; 'foo'; end
7
+ def self.document_type; 'bar'; end
8
+ end
9
+
10
+ RESPONSE = { 'hits' => { 'total' => 123, 'max_score' => 456, 'hits' => [{'foo' => 'bar'}] } }
11
+
12
+ setup do
13
+ @search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
14
+ @response = Elasticsearch::Model::Response::Response.new OriginClass, @search
15
+ @results = Elasticsearch::Model::Response::Results.new OriginClass, @response
16
+ @search.stubs(:execute!).returns(RESPONSE)
17
+ end
18
+
19
+ should "access the results" do
20
+ assert_respond_to @results, :results
21
+ assert_equal 1, @results.results.size
22
+ assert_equal 'bar', @results.results.first.foo
23
+ end
24
+
25
+ should "delegate Enumerable methods to results" do
26
+ assert ! @results.empty?
27
+ assert_equal 'bar', @results.first.foo
28
+ end
29
+
30
+ end
31
+ end
@@ -0,0 +1,67 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::ResponseTest < Test::Unit::TestCase
4
+ context "Response" do
5
+ class OriginClass
6
+ def self.index_name; 'foo'; end
7
+ def self.document_type; 'bar'; end
8
+ end
9
+
10
+ RESPONSE = { 'took' => '5', 'timed_out' => false, '_shards' => {'one' => 'OK'}, 'hits' => { 'hits' => [] } }
11
+
12
+ setup do
13
+ @search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
14
+ @search.stubs(:execute!).returns(RESPONSE)
15
+ end
16
+
17
+ should "access klass, response, took, timed_out, shards" do
18
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
19
+
20
+ assert_equal OriginClass, response.klass
21
+ assert_equal @search, response.search
22
+ assert_equal RESPONSE, response.response
23
+ assert_equal '5', response.took
24
+ assert_equal false, response.timed_out
25
+ assert_equal 'OK', response.shards.one
26
+ end
27
+
28
+ should "wrap the raw Hash response in Hashie::Mash" do
29
+ @search = Elasticsearch::Model::Searching::SearchRequest.new OriginClass, '*'
30
+ @search.stubs(:execute!).returns({'hits' => { 'hits' => [] }, 'aggregations' => { 'dates' => 'FOO' }})
31
+
32
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
33
+
34
+ assert_respond_to response.response, :aggregations
35
+ assert_equal 'FOO', response.response.aggregations.dates
36
+ end
37
+
38
+ should "load and access the results" do
39
+ @search.expects(:execute!).returns(RESPONSE)
40
+
41
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
42
+ assert_instance_of Elasticsearch::Model::Response::Results, response.results
43
+ assert_equal 0, response.size
44
+ end
45
+
46
+ should "load and access the records" do
47
+ @search.expects(:execute!).returns(RESPONSE)
48
+
49
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
50
+ assert_instance_of Elasticsearch::Model::Response::Records, response.records
51
+ assert_equal 0, response.size
52
+ end
53
+
54
+ should "delegate Enumerable methods to results" do
55
+ @search.expects(:execute!).returns(RESPONSE)
56
+
57
+ response = Elasticsearch::Model::Response::Response.new OriginClass, @search
58
+ assert response.empty?
59
+ end
60
+
61
+ should "be initialized lazily" do
62
+ @search.expects(:execute!).never
63
+
64
+ Elasticsearch::Model::Response::Response.new OriginClass, @search
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,78 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::SearchRequestTest < Test::Unit::TestCase
4
+ context "SearchRequest class" do
5
+ class ::DummySearchingModel
6
+ extend Elasticsearch::Model::Searching::ClassMethods
7
+
8
+ def self.index_name; 'foo'; end
9
+ def self.document_type; 'bar'; end
10
+
11
+ end
12
+
13
+ setup do
14
+ @client = mock('client')
15
+ DummySearchingModel.stubs(:client).returns(@client)
16
+ end
17
+
18
+ should "pass the search definition as a simple query" do
19
+ @client.expects(:search).with do |params|
20
+ assert_equal 'foo', params[:q]
21
+ true
22
+ end
23
+ .returns({})
24
+
25
+ s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, 'foo'
26
+ s.execute!
27
+ end
28
+
29
+ should "pass the search definition as a Hash" do
30
+ @client.expects(:search).with do |params|
31
+ assert_equal( {foo: 'bar'}, params[:body] )
32
+ true
33
+ end
34
+ .returns({})
35
+
36
+ s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, foo: 'bar'
37
+ s.execute!
38
+ end
39
+
40
+ should "pass the search definition as a JSON string" do
41
+ @client.expects(:search).with do |params|
42
+ assert_equal( '{"foo":"bar"}', params[:body] )
43
+ true
44
+ end
45
+ .returns({})
46
+
47
+ s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, '{"foo":"bar"}'
48
+ s.execute!
49
+ end
50
+
51
+ should "pass the search definition as an object which responds to to_hash" do
52
+ class MySpecialQueryBuilder
53
+ def to_hash; {foo: 'bar'}; end
54
+ end
55
+
56
+ @client.expects(:search).with do |params|
57
+ assert_equal( {foo: 'bar'}, params[:body] )
58
+ true
59
+ end
60
+ .returns({})
61
+
62
+ s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, MySpecialQueryBuilder.new
63
+ s.execute!
64
+ end
65
+
66
+ should "pass the options to the client" do
67
+ @client.expects(:search).with do |params|
68
+ assert_equal 'foo', params[:q]
69
+ assert_equal 15, params[:size]
70
+ true
71
+ end
72
+ .returns({})
73
+
74
+ s = Elasticsearch::Model::Searching::SearchRequest.new ::DummySearchingModel, 'foo', size: 15
75
+ s.execute!
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,41 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::SearchingTest < Test::Unit::TestCase
4
+ context "Searching module" do
5
+ class ::DummySearchingModel
6
+ extend Elasticsearch::Model::Searching::ClassMethods
7
+
8
+ def self.index_name; 'foo'; end
9
+ def self.document_type; 'bar'; end
10
+ end
11
+
12
+ setup do
13
+ @client = mock('client')
14
+ DummySearchingModel.stubs(:client).returns(@client)
15
+ end
16
+
17
+ should "have the search method" do
18
+ assert_respond_to DummySearchingModel, :search
19
+ end
20
+
21
+ should "initialize the search object" do
22
+ Elasticsearch::Model::Searching::SearchRequest
23
+ .expects(:new).with do |klass, query, options|
24
+ assert_equal DummySearchingModel, klass
25
+ assert_equal 'foo', query
26
+ assert_equal({default_operator: 'AND'}, options)
27
+ true
28
+ end
29
+ .returns( stub('search') )
30
+
31
+ DummySearchingModel.search 'foo', default_operator: 'AND'
32
+ end
33
+
34
+ should "not execute the search" do
35
+ Elasticsearch::Model::Searching::SearchRequest
36
+ .expects(:new).returns( mock('search').expects(:execute!).never )
37
+
38
+ DummySearchingModel.search 'foo'
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ class Elasticsearch::Model::SerializingTest < Test::Unit::TestCase
4
+ context "Serializing module" do
5
+ class DummyClass
6
+ include Elasticsearch::Model::Serializing::InstanceMethods
7
+
8
+ def as_json(options={})
9
+ 'HASH'
10
+ end
11
+ end
12
+
13
+ should "delegate to as_json by default" do
14
+ assert_equal 'HASH', DummyClass.new.as_indexed_json
15
+ end
16
+ end
17
+ end