load_balanced_tire 0.1

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 (121) hide show
  1. data/.gitignore +14 -0
  2. data/.travis.yml +29 -0
  3. data/Gemfile +4 -0
  4. data/MIT-LICENSE +20 -0
  5. data/README.markdown +760 -0
  6. data/Rakefile +78 -0
  7. data/examples/rails-application-template.rb +249 -0
  8. data/examples/tire-dsl.rb +876 -0
  9. data/lib/tire.rb +55 -0
  10. data/lib/tire/alias.rb +296 -0
  11. data/lib/tire/configuration.rb +30 -0
  12. data/lib/tire/dsl.rb +43 -0
  13. data/lib/tire/http/client.rb +62 -0
  14. data/lib/tire/http/clients/curb.rb +61 -0
  15. data/lib/tire/http/clients/faraday.rb +71 -0
  16. data/lib/tire/http/response.rb +27 -0
  17. data/lib/tire/index.rb +361 -0
  18. data/lib/tire/logger.rb +60 -0
  19. data/lib/tire/model/callbacks.rb +40 -0
  20. data/lib/tire/model/import.rb +26 -0
  21. data/lib/tire/model/indexing.rb +128 -0
  22. data/lib/tire/model/naming.rb +100 -0
  23. data/lib/tire/model/percolate.rb +99 -0
  24. data/lib/tire/model/persistence.rb +71 -0
  25. data/lib/tire/model/persistence/attributes.rb +143 -0
  26. data/lib/tire/model/persistence/finders.rb +66 -0
  27. data/lib/tire/model/persistence/storage.rb +69 -0
  28. data/lib/tire/model/search.rb +307 -0
  29. data/lib/tire/results/collection.rb +114 -0
  30. data/lib/tire/results/item.rb +86 -0
  31. data/lib/tire/results/pagination.rb +54 -0
  32. data/lib/tire/rubyext/hash.rb +8 -0
  33. data/lib/tire/rubyext/ruby_1_8.rb +7 -0
  34. data/lib/tire/rubyext/symbol.rb +11 -0
  35. data/lib/tire/search.rb +188 -0
  36. data/lib/tire/search/facet.rb +74 -0
  37. data/lib/tire/search/filter.rb +28 -0
  38. data/lib/tire/search/highlight.rb +37 -0
  39. data/lib/tire/search/query.rb +186 -0
  40. data/lib/tire/search/scan.rb +114 -0
  41. data/lib/tire/search/script_field.rb +23 -0
  42. data/lib/tire/search/sort.rb +25 -0
  43. data/lib/tire/tasks.rb +135 -0
  44. data/lib/tire/utils.rb +17 -0
  45. data/lib/tire/version.rb +22 -0
  46. data/test/fixtures/articles/1.json +1 -0
  47. data/test/fixtures/articles/2.json +1 -0
  48. data/test/fixtures/articles/3.json +1 -0
  49. data/test/fixtures/articles/4.json +1 -0
  50. data/test/fixtures/articles/5.json +1 -0
  51. data/test/integration/active_model_indexing_test.rb +51 -0
  52. data/test/integration/active_model_searchable_test.rb +114 -0
  53. data/test/integration/active_record_searchable_test.rb +446 -0
  54. data/test/integration/boolean_queries_test.rb +43 -0
  55. data/test/integration/count_test.rb +34 -0
  56. data/test/integration/custom_score_queries_test.rb +88 -0
  57. data/test/integration/dis_max_queries_test.rb +68 -0
  58. data/test/integration/dsl_search_test.rb +22 -0
  59. data/test/integration/explanation_test.rb +44 -0
  60. data/test/integration/facets_test.rb +259 -0
  61. data/test/integration/filtered_queries_test.rb +66 -0
  62. data/test/integration/filters_test.rb +63 -0
  63. data/test/integration/fuzzy_queries_test.rb +20 -0
  64. data/test/integration/highlight_test.rb +64 -0
  65. data/test/integration/index_aliases_test.rb +122 -0
  66. data/test/integration/index_mapping_test.rb +43 -0
  67. data/test/integration/index_store_test.rb +96 -0
  68. data/test/integration/index_update_document_test.rb +111 -0
  69. data/test/integration/mongoid_searchable_test.rb +309 -0
  70. data/test/integration/percolator_test.rb +111 -0
  71. data/test/integration/persistent_model_test.rb +130 -0
  72. data/test/integration/prefix_query_test.rb +43 -0
  73. data/test/integration/query_return_version_test.rb +70 -0
  74. data/test/integration/query_string_test.rb +52 -0
  75. data/test/integration/range_queries_test.rb +36 -0
  76. data/test/integration/reindex_test.rb +46 -0
  77. data/test/integration/results_test.rb +39 -0
  78. data/test/integration/scan_test.rb +56 -0
  79. data/test/integration/script_fields_test.rb +38 -0
  80. data/test/integration/sort_test.rb +36 -0
  81. data/test/integration/text_query_test.rb +39 -0
  82. data/test/models/active_model_article.rb +31 -0
  83. data/test/models/active_model_article_with_callbacks.rb +49 -0
  84. data/test/models/active_model_article_with_custom_document_type.rb +7 -0
  85. data/test/models/active_model_article_with_custom_index_name.rb +7 -0
  86. data/test/models/active_record_models.rb +122 -0
  87. data/test/models/article.rb +15 -0
  88. data/test/models/mongoid_models.rb +97 -0
  89. data/test/models/persistent_article.rb +11 -0
  90. data/test/models/persistent_article_in_namespace.rb +12 -0
  91. data/test/models/persistent_article_with_casting.rb +28 -0
  92. data/test/models/persistent_article_with_defaults.rb +11 -0
  93. data/test/models/persistent_articles_with_custom_index_name.rb +10 -0
  94. data/test/models/supermodel_article.rb +17 -0
  95. data/test/models/validated_model.rb +11 -0
  96. data/test/test_helper.rb +93 -0
  97. data/test/unit/active_model_lint_test.rb +17 -0
  98. data/test/unit/configuration_test.rb +74 -0
  99. data/test/unit/http_client_test.rb +76 -0
  100. data/test/unit/http_response_test.rb +49 -0
  101. data/test/unit/index_alias_test.rb +275 -0
  102. data/test/unit/index_test.rb +894 -0
  103. data/test/unit/logger_test.rb +125 -0
  104. data/test/unit/model_callbacks_test.rb +116 -0
  105. data/test/unit/model_import_test.rb +71 -0
  106. data/test/unit/model_persistence_test.rb +528 -0
  107. data/test/unit/model_search_test.rb +913 -0
  108. data/test/unit/results_collection_test.rb +281 -0
  109. data/test/unit/results_item_test.rb +162 -0
  110. data/test/unit/rubyext_test.rb +66 -0
  111. data/test/unit/search_facet_test.rb +153 -0
  112. data/test/unit/search_filter_test.rb +42 -0
  113. data/test/unit/search_highlight_test.rb +46 -0
  114. data/test/unit/search_query_test.rb +301 -0
  115. data/test/unit/search_scan_test.rb +113 -0
  116. data/test/unit/search_script_field_test.rb +26 -0
  117. data/test/unit/search_sort_test.rb +50 -0
  118. data/test/unit/search_test.rb +499 -0
  119. data/test/unit/tire_test.rb +126 -0
  120. data/tire.gemspec +90 -0
  121. metadata +549 -0
@@ -0,0 +1,11 @@
1
+ # Example class with ElasticSearch persistence
2
+
3
+ class PersistentArticle
4
+
5
+ include Tire::Model::Persistence
6
+
7
+ property :title
8
+ property :published_on
9
+ property :tags
10
+
11
+ end
@@ -0,0 +1,12 @@
1
+ # Example namespaced class with ElasticSearch persistence
2
+ #
3
+ # The `document_type` is `my_namespace/persistent_article_in_namespace`
4
+ #
5
+
6
+ module MyNamespace
7
+ class PersistentArticleInNamespace
8
+ include Tire::Model::Persistence
9
+
10
+ property :title
11
+ end
12
+ end
@@ -0,0 +1,28 @@
1
+ class Author
2
+ attr_accessor :first_name, :last_name
3
+ def initialize(attributes)
4
+ @first_name = HashWithIndifferentAccess.new(attributes)[:first_name]
5
+ @last_name = HashWithIndifferentAccess.new(attributes)[:last_name]
6
+ end
7
+ end
8
+
9
+ class Comment
10
+ def initialize(params); @attributes = HashWithIndifferentAccess.new(params); end
11
+ def method_missing(method_name, *arguments); @attributes[method_name]; end
12
+ def as_json(*); @attributes; end
13
+ end
14
+
15
+ class PersistentArticleWithCastedItem
16
+ include Tire::Model::Persistence
17
+
18
+ property :title
19
+ property :author, :class => Author
20
+ property :stats
21
+ end
22
+
23
+ class PersistentArticleWithCastedCollection
24
+ include Tire::Model::Persistence
25
+
26
+ property :title
27
+ property :comments, :class => [Comment]
28
+ end
@@ -0,0 +1,11 @@
1
+ class PersistentArticleWithDefaults
2
+
3
+ include Tire::Model::Persistence
4
+
5
+ property :title
6
+ property :published_on
7
+ property :tags, :default => []
8
+ property :hidden, :default => false
9
+ property :options, :default => {:switches => []}
10
+
11
+ end
@@ -0,0 +1,10 @@
1
+ # Example class with ElasticSearch persistence and custom index name
2
+
3
+ class PersistentArticleWithCustomIndexName
4
+
5
+ include Tire::Model::Persistence
6
+
7
+ property :title
8
+
9
+ index_name 'custom-index-name'
10
+ end
@@ -0,0 +1,17 @@
1
+ # Example ActiveModel class for testing :searchable mode
2
+
3
+ require 'rubygems'
4
+ require 'redis/persistence'
5
+
6
+ class SupermodelArticle
7
+ include Redis::Persistence
8
+
9
+ include Tire::Model::Search
10
+ include Tire::Model::Callbacks
11
+
12
+ property :title
13
+
14
+ mapping do
15
+ indexes :title, :type => 'string', :boost => 15, :analyzer => 'czech'
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ # Example ActiveModel with validations
2
+
3
+ class ValidatedModel
4
+
5
+ include Tire::Model::Persistence
6
+
7
+ property :name
8
+
9
+ validates_presence_of :name
10
+
11
+ end
@@ -0,0 +1,93 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'pathname'
5
+ require 'test/unit'
6
+
7
+ require 'yajl/json_gem'
8
+ require 'sqlite3'
9
+
10
+ require 'shoulda'
11
+ require 'turn/autorun' unless ENV["TM_FILEPATH"] || defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
12
+ require 'mocha'
13
+
14
+ require 'active_support/core_ext/hash/indifferent_access'
15
+
16
+ require 'tire'
17
+
18
+ # Require basic model files
19
+ #
20
+ require File.dirname(__FILE__) + '/models/active_model_article'
21
+ require File.dirname(__FILE__) + '/models/active_model_article_with_callbacks'
22
+ require File.dirname(__FILE__) + '/models/active_model_article_with_custom_document_type'
23
+ require File.dirname(__FILE__) + '/models/active_model_article_with_custom_index_name'
24
+ require File.dirname(__FILE__) + '/models/active_record_models'
25
+ require File.dirname(__FILE__) + '/models/article'
26
+ require File.dirname(__FILE__) + '/models/persistent_article'
27
+ require File.dirname(__FILE__) + '/models/persistent_article_in_namespace'
28
+ require File.dirname(__FILE__) + '/models/persistent_article_with_casting'
29
+ require File.dirname(__FILE__) + '/models/persistent_article_with_defaults'
30
+ require File.dirname(__FILE__) + '/models/persistent_articles_with_custom_index_name'
31
+ require File.dirname(__FILE__) + '/models/validated_model'
32
+
33
+ class Test::Unit::TestCase
34
+
35
+ def assert_block(message=nil)
36
+ raise Test::Unit::AssertionFailedError.new(message.to_s) if (! yield)
37
+ return true
38
+ end if defined?(RUBY_VERSION) && RUBY_VERSION < '1.9'
39
+
40
+ def mock_response(body, code=200, headers={})
41
+ Tire::HTTP::Response.new(body, code, headers)
42
+ end
43
+
44
+ def fixtures_path
45
+ Pathname( File.expand_path( 'fixtures', File.dirname(__FILE__) ) )
46
+ end
47
+
48
+ def fixture_file(path)
49
+ File.read File.expand_path( path, fixtures_path )
50
+ end
51
+
52
+ end
53
+
54
+ module Test::Integration
55
+ URL = "http://localhost:9200"
56
+
57
+ def setup
58
+ begin; Object.send(:remove_const, :Rails); rescue; end
59
+
60
+ begin
61
+ ::RestClient.get URL
62
+ rescue Errno::ECONNREFUSED
63
+ abort "\n\n#{'-'*87}\n[ABORTED] You have to run ElasticSearch on #{URL} for integration tests\n#{'-'*87}\n\n"
64
+ end
65
+
66
+ ::RestClient.delete "#{URL}/articles-test" rescue nil
67
+ ::RestClient.post "#{URL}/articles-test", ''
68
+ fixtures_path.join('articles').entries.each do |f|
69
+ filename = f.to_s
70
+ next if filename =~ /^\./
71
+ ::RestClient.put "#{URL}/articles-test/article/#{File.basename(filename, '.*')}",
72
+ fixtures_path.join('articles').join(f).read
73
+ end
74
+ ::RestClient.post "#{URL}/articles-test/_refresh", ''
75
+
76
+ Dir[File.dirname(__FILE__) + '/models/**/*.rb'].each { |m| load m }
77
+ end
78
+
79
+ def teardown
80
+ %w[
81
+ articles-test
82
+ active_record_articles
83
+ active_model_article_with_custom_as_serializations
84
+ active_record_class_with_tire_methods
85
+ mongoid_articles
86
+ mongoid_class_with_tire_methods
87
+ supermodel_articles
88
+ dynamic_index
89
+ model_with_nested_documents ].each do |index|
90
+ ::RestClient.delete "#{URL}/#{index}" rescue nil
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,17 @@
1
+ require 'test_helper'
2
+
3
+ module Tire
4
+ module Model
5
+
6
+ class ActiveModelLintTest < Test::Unit::TestCase
7
+
8
+ include ActiveModel::Lint::Tests
9
+
10
+ def setup
11
+ @model = PersistentArticle.new :title => 'Test'
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,74 @@
1
+ require 'test_helper'
2
+
3
+ module Tire
4
+
5
+ class ConfigurationTest < Test::Unit::TestCase
6
+
7
+ def teardown
8
+ Tire::Configuration.reset
9
+ ENV['ELASTICSEARCH_URL'] = nil
10
+ end
11
+
12
+ context "Configuration" do
13
+ setup do
14
+ Configuration.instance_variable_set(:@url, nil)
15
+ Configuration.instance_variable_set(:@client, nil)
16
+ end
17
+
18
+ teardown do
19
+ Configuration.reset
20
+ end
21
+
22
+ should "return default URL" do
23
+ assert_equal 'http://localhost:9200', Configuration.url
24
+ end
25
+
26
+ should "use environment variable, if present" do
27
+ ENV['ELASTICSEARCH_URL'] = 'http://es.example.com'
28
+ assert_equal 'http://es.example.com', Configuration.url
29
+ end
30
+
31
+ should "allow setting and retrieving the URL" do
32
+ assert_nothing_raised { Configuration.url 'http://example.com' }
33
+ assert_equal 'http://example.com', Configuration.url
34
+ end
35
+
36
+ should "strip trailing slash from the URL" do
37
+ assert_nothing_raised { Configuration.url 'http://slash.com:9200/' }
38
+ assert_equal 'http://slash.com:9200', Configuration.url
39
+ end
40
+
41
+ should "return default client" do
42
+ assert_equal HTTP::Client::RestClient, Configuration.client
43
+ end
44
+
45
+ should "return nil as logger by default" do
46
+ assert_nil Configuration.logger
47
+ end
48
+
49
+ should "return set and return logger" do
50
+ Configuration.logger STDERR
51
+ assert_not_nil Configuration.logger
52
+ assert_instance_of Tire::Logger, Configuration.logger
53
+ end
54
+
55
+ should "allow to reset the configuration for specific property" do
56
+ Configuration.url 'http://example.com'
57
+ assert_equal 'http://example.com', Configuration.url
58
+ Configuration.reset :url
59
+ assert_equal 'http://localhost:9200', Configuration.url
60
+ end
61
+
62
+ should "allow to reset the configuration for all properties" do
63
+ Configuration.url 'http://example.com'
64
+ Configuration.wrapper Hash
65
+ assert_equal 'http://example.com', Configuration.url
66
+ Configuration.reset
67
+ assert_equal 'http://localhost:9200', Configuration.url
68
+ assert_equal HTTP::Client::RestClient, Configuration.client
69
+ end
70
+ end
71
+
72
+ end
73
+
74
+ end
@@ -0,0 +1,76 @@
1
+ require 'test_helper'
2
+ require 'tire/http/clients/curb'
3
+
4
+ module Tire
5
+ module HTTP
6
+
7
+ class ClientTest < Test::Unit::TestCase
8
+
9
+ context "RestClient" do
10
+
11
+ should "be default" do
12
+ assert_equal Client::RestClient, Configuration.client
13
+ end
14
+
15
+ should "respond to HTTP methods" do
16
+ assert_respond_to Client::RestClient, :get
17
+ assert_respond_to Client::RestClient, :post
18
+ assert_respond_to Client::RestClient, :put
19
+ assert_respond_to Client::RestClient, :delete
20
+ assert_respond_to Client::RestClient, :head
21
+ end
22
+
23
+ should "not rescue generic exceptions" do
24
+ Client::RestClient.expects(:get).raises(RuntimeError, "Something bad happened in YOUR code")
25
+
26
+ assert_raise(RuntimeError) do
27
+ Client::RestClient.get 'http://example.com'
28
+ end
29
+ end
30
+
31
+ should "not rescue ServerBrokeConnection errors" do
32
+ Client::RestClient.expects(:get).raises(RestClient::ServerBrokeConnection)
33
+
34
+ assert_raise(RestClient::ServerBrokeConnection) do
35
+ Client::RestClient.get 'http://example.com'
36
+ end
37
+ end
38
+
39
+ should "not rescue RequestTimeout errors" do
40
+ Client::RestClient.expects(:get).raises(RestClient::RequestTimeout)
41
+
42
+ assert_raise(RestClient::RequestTimeout) do
43
+ Client::RestClient.get 'http://example.com'
44
+ end
45
+ end
46
+
47
+ end
48
+
49
+ context "Curb" do
50
+ setup do
51
+ Configuration.client Client::Curb
52
+ end
53
+
54
+ teardown do
55
+ Configuration.client Client::RestClient
56
+ end
57
+
58
+ should "use POST method if request body passed" do
59
+ ::Curl::Easy.any_instance.expects(:http_post)
60
+
61
+ response = Configuration.client.get "http://localhost:3000", '{ "query_string" : { "query" : "apple" }}'
62
+ end
63
+
64
+ should "use GET method if request body is nil" do
65
+ ::Curl::Easy.any_instance.expects(:http_get)
66
+
67
+ response = Configuration.client.get "http://localhost:9200/articles/article/1"
68
+ end
69
+
70
+ end
71
+
72
+
73
+ end
74
+ end
75
+
76
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+
3
+ module Tire
4
+ module HTTP
5
+
6
+ class ResponseTest < Test::Unit::TestCase
7
+
8
+ context "Response" do
9
+
10
+ should "take response body, code and headers on initialization" do
11
+ response = Response.new "http response body",
12
+ 200,
13
+ :content_length => 20,
14
+ :content_encoding => 'gzip'
15
+
16
+ assert_equal "http response body", response.body
17
+ assert_equal 200, response.code
18
+ end
19
+
20
+ should "not require headers" do
21
+ assert_nothing_raised do
22
+ Response.new "Forbidden", 403
23
+ end
24
+ end
25
+
26
+ should "return success" do
27
+ responses = []
28
+ responses << Response.new('OK', 200)
29
+ responses << Response.new('Redirect', 302)
30
+
31
+ responses.each { |response| assert response.success? }
32
+
33
+ assert ! Response.new('NotFound', 404).success?
34
+ end
35
+
36
+ should "return failure" do
37
+ assert Response.new('NotFound', 404).failure?
38
+ end
39
+
40
+ should "return string representation" do
41
+ assert_equal "200 : Hello", Response.new('Hello', 200).to_s
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,275 @@
1
+ require 'test_helper'
2
+
3
+ module Tire
4
+
5
+ class IndexAliasTest < Test::Unit::TestCase
6
+
7
+ context "Index Alias" do
8
+ teardown { Configuration.reset }
9
+
10
+ context "initialization" do
11
+
12
+ should "have a name and defaults" do
13
+ @alias = Alias.new :name => 'dummy'
14
+ assert_equal 'dummy', @alias.name
15
+ assert @alias.indices.empty?
16
+ end
17
+
18
+ should "have indices" do
19
+ @alias = Alias.new :indices => ['index_A', 'index_B']
20
+ assert_equal ['index_A', 'index_B'], @alias.indices.to_a
21
+ end
22
+
23
+ should "have single index" do
24
+ @alias = Alias.new :index => 'index_A'
25
+ assert_equal ['index_A'], @alias.indices.to_a
26
+ assert_equal ['index_A'], @alias.index.to_a
27
+ end
28
+
29
+ should "have properties" do
30
+ @alias = Alias.new :routing => '1'
31
+ assert_equal '1', @alias.routing
32
+ end
33
+
34
+ should "allow to add indices in a block" do
35
+ @alias = Alias.new do
36
+ index 'index_A'
37
+ index 'index_B'
38
+ end
39
+ assert_equal ['index_A', 'index_B'], @alias.indices.to_a
40
+
41
+ @alias = Alias.new do |a|
42
+ a.index 'index_A'
43
+ a.index 'index_B'
44
+ end
45
+ assert_equal ['index_A', 'index_B'], @alias.indices.to_a
46
+ end
47
+
48
+ should "allow to define filter with DSL" do
49
+ @alias = Alias.new do
50
+ filter :terms, :username => 'mary'
51
+ end
52
+
53
+ assert_equal( { :terms => { :username => 'mary' } }, @alias.filter )
54
+ end
55
+
56
+ should "allow chaining" do
57
+ @alias = Alias.new.name('my_alias').index('index_1').index('index_2').routing('1')
58
+
59
+ assert_equal 'my_alias', @alias.name
60
+ assert_equal ['index_1', 'index_2'], @alias.indices.to_a
61
+ assert_equal '1', @alias.routing
62
+ end
63
+
64
+ should "be converted to JSON" do
65
+ @alias = Alias.new :name => 'index_anne',
66
+ :indices => ['index_2012_04', 'index_2012_03', 'index_2012_02'],
67
+ :routing => 1,
68
+ :filter => { :terms => { :user => 'anne' } }
69
+ # p @alias.to_json
70
+ result = MultiJson.decode @alias.to_json
71
+
72
+ assert_equal 3, result['actions'].size
73
+ assert_equal 'index_2012_04', result['actions'][0]['add']['index']
74
+ end
75
+
76
+ should "be converted to string" do
77
+ @alias = Alias.new :name => 'my_alias'
78
+ assert_equal 'my_alias', @alias.to_s
79
+ end
80
+
81
+ end
82
+
83
+ context "updating" do
84
+ setup do
85
+ Configuration.client.expects(:get).
86
+ returns( mock_response( %q|{"index_A":{"aliases":{}},"index_B":{"aliases":{"alias_john":{"filter":{"term":{"user":"john"}}},"alias_martha":{"filter":{"term":{"user":"martha"}}}}},"mongoid_articles":{"aliases":{}},"index_C":{"aliases":{"alias_martha":{"filter":{"term":{"user":"martha"}}}}}}|), 200 ).at_least_once
87
+ end
88
+
89
+ should "add indices to alias" do
90
+ Configuration.client.expects(:post).with do |url, json|
91
+ # puts json
92
+ MultiJson.decode(json)['actions'].any? do |a|
93
+ a['add']['index'] == 'index_A' &&
94
+ a['add']['alias'] == 'alias_martha'
95
+ end
96
+ end.returns(mock_response('{}'), 200)
97
+
98
+ a = Alias.find('alias_martha')
99
+ a.indices.push 'index_A'
100
+ a.save
101
+ end
102
+
103
+ should "remove indices from alias" do
104
+ Configuration.client.expects(:post).with do |url, json|
105
+ # puts json
106
+ MultiJson.decode(json)['actions'].any? do |a|
107
+ a['remove'] &&
108
+ a['remove']['index'] == 'index_A' &&
109
+ a['remove']['alias'] == 'alias_martha'
110
+ end
111
+ end.returns(mock_response('{}'), 200)
112
+
113
+ a = Alias.find('alias_martha')
114
+ a.indices.delete 'index_A'
115
+ a.save
116
+ end
117
+
118
+ should "change alias configuration" do
119
+ Configuration.client.expects(:post).with do |url, json|
120
+ # puts json
121
+ MultiJson.decode(json)['actions'].all? { |a| a['add']['routing'] == 'martha' }
122
+ end.returns(mock_response('{}'), 200)
123
+
124
+ a = Alias.find('alias_martha')
125
+ a.routing('martha')
126
+ a.save
127
+ end
128
+
129
+ end
130
+
131
+ context "saving" do
132
+
133
+ should "send data to ElasticSearch" do
134
+ Configuration.client.expects(:post).with do |url, json|
135
+ url == "#{Configuration.url}/_aliases" &&
136
+ json =~ /"index":"index_2012_05"/ &&
137
+ json =~ /"alias":"index_current"/
138
+ end.returns(mock_response('{}'), 200)
139
+
140
+ @alias = Alias.new :name => 'index_current', :index => 'index_2012_05'
141
+ @alias.save
142
+ end
143
+
144
+ should "log request" do
145
+ Tire.configure { logger '/dev/null' }
146
+
147
+ Configuration.client.expects(:post)
148
+ Configuration.logger.expects(:log_request)
149
+ Alias.new( :name => 'index_current', :index => 'index_2012_05' ).save
150
+ end
151
+
152
+ end
153
+
154
+ context "finding" do
155
+ setup do
156
+ Configuration.client.expects(:get).with do |url, json|
157
+ url == "#{Configuration.url}/_aliases"
158
+ end.returns( mock_response( %q|{"index_A":{"aliases":{}},"index_B":{"aliases":{"alias_john":{"filter":{"term":{"user":"john"}}},"alias_martha":{"filter":{"term":{"user":"martha"}}}}},"index_C":{"aliases":{"alias_martha":{"filter":{"term":{"user":"martha"}}}}}}|), 200 )
159
+ end
160
+
161
+ should "find all aliases" do
162
+ aliases = Alias.all
163
+ # p aliases
164
+ assert_equal 2, aliases.size
165
+ assert_equal ['index_B', 'index_C'], aliases.select { |a| a.name == 'alias_martha'}.first.indices.to_a.sort
166
+ end
167
+
168
+ should "find aliases for a specific index" do
169
+ Configuration.client.unstub(:get)
170
+ Configuration.client.expects(:get).with do |url, json|
171
+ url == "#{Configuration.url}/index_C/_aliases"
172
+ end.returns( mock_response( %q|{"index_C":{"aliases":{"alias_martha":{"filter":{"term":{"user":"martha"}}}}}}|), 200 )
173
+
174
+ aliases = Alias.all('index_C')
175
+ # p aliases
176
+ assert_equal 1, aliases.size
177
+ assert_equal ['index_C'], aliases.last.indices.to_a
178
+ end
179
+
180
+ should "find an alias" do
181
+ a = Alias.find('alias_martha')
182
+ assert_instance_of Alias, a
183
+ assert_equal ['index_B', 'index_C'], a.indices.to_a.sort
184
+ end
185
+
186
+ should "find an alias and configure it with a block" do
187
+ a = Alias.find('alias_martha') do |a|
188
+ a.indices.delete 'index_A'
189
+ a.indices.add 'index_D'
190
+ end
191
+
192
+ assert_equal ['index_B', 'index_C', 'index_D'], a.indices.to_a.sort
193
+ end
194
+
195
+ end
196
+
197
+ context "creating" do
198
+ setup do
199
+ Configuration.client.expects(:post).with do |url, json|
200
+ url == "#{Configuration.url}/_aliases" &&
201
+ json =~ /"index":"index_2012_05"/ &&
202
+ json =~ /"alias":"index_current"/
203
+ end.returns(mock_response('{}'), 200)
204
+ end
205
+
206
+ should "create the alias" do
207
+ Alias.create :name => 'index_current', :index => 'index_2012_05'
208
+ end
209
+
210
+ should "create the alias with a block" do
211
+ Alias.create :name => 'index_current' do
212
+ index 'index_2012_05'
213
+ end
214
+ end
215
+
216
+ end
217
+
218
+ end
219
+
220
+ context "IndexCollection" do
221
+
222
+ should "be intialized with an array or arguments list" do
223
+ c1 = Alias::IndexCollection.new ['1', '2', '3']
224
+ c2 = Alias::IndexCollection.new '1', '2', '3'
225
+ assert_equal c1.to_a, c2.to_a
226
+ end
227
+
228
+ should "be iterable" do
229
+ c = Alias::IndexCollection.new '1', '2', '3'
230
+ assert_respond_to c, :each
231
+ assert_respond_to c, :size
232
+ assert_equal [1, 2, 3], c.map(&:to_i)
233
+ end
234
+
235
+ should "allow adding values" do
236
+ c = Alias::IndexCollection.new '1', '2'
237
+ c.add '3'
238
+ assert_equal 3, c.size
239
+ assert_equal ['1', '2', '3'], c.add_indices
240
+ assert_equal [], c.remove_indices
241
+ end
242
+
243
+ should "allow removing values" do
244
+ c = Alias::IndexCollection.new '1', '2'
245
+ c.remove '1'
246
+ assert_equal 1, c.size
247
+ assert_equal ['2'], c.add_indices
248
+ assert_equal ['1'], c.remove_indices
249
+ end
250
+
251
+ should "clear everything" do
252
+ c = Alias::IndexCollection.new '1', '2'
253
+ c.clear
254
+ assert_equal 0, c.size
255
+ assert_equal [], c.add_indices
256
+ assert_equal ['1', '2'], c.remove_indices
257
+ end
258
+
259
+ should "respond to empty" do
260
+ c = Alias::IndexCollection.new
261
+ assert c.empty?, "#{c.inspect} should be empty"
262
+ end
263
+
264
+ should "remove values with a block" do
265
+ c = Alias::IndexCollection.new '1', '2', '3'
266
+
267
+ c.delete_if { |a| a.to_i > 1 }
268
+ assert_equal 1, c.size
269
+ assert_equal ['1'], c.add_indices
270
+ assert_equal ['2', '3'], c.remove_indices
271
+ end
272
+
273
+ end
274
+ end
275
+ end