elasticsearch-model-queryable 0.1.5

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