syphon 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG +10 -0
- data/Gemfile +1 -0
- data/README.markdown +62 -1
- data/lib/syphon/index.rb +15 -7
- data/lib/syphon/railtie.rb +38 -14
- data/lib/syphon/schema.rb +8 -7
- data/lib/syphon/version.rb +1 -1
- data/lib/syphon.rb +32 -5
- data/test/syphon/test_index.rb +25 -6
- data/test/syphon/test_railtie.rb +98 -0
- data/test/syphon/test_schema.rb +32 -9
- data/test/test_helper.rb +6 -4
- data/test/test_syphon.rb +55 -5
- metadata +6 -4
data/CHANGELOG
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
== 0.0.2 2013-12-12
|
2
|
+
|
3
|
+
* Add index_settings attribute to control sharding, replication, etc.
|
4
|
+
* Allow dynamic SQL (blocks) for attributes.
|
5
|
+
* Make index_base_name overridable instead of index_name. The former is
|
6
|
+
prefixed with the configured index_namespace.
|
7
|
+
* Restructure configuration under Rails. Single file (syphon.yml) with log
|
8
|
+
settings at top-level, and database and elasticsearch settings under their
|
9
|
+
respective keys. Log file may now be relative to rails root.
|
10
|
+
|
1
11
|
== 0.0.1 2013-11-18
|
2
12
|
|
3
13
|
* Hi.
|
data/Gemfile
CHANGED
data/README.markdown
CHANGED
@@ -2,4 +2,65 @@
|
|
2
2
|
|
3
3
|
Syphon data from an Arel source into ElasticSearch.
|
4
4
|
|
5
|
-
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
gem install syphon
|
8
|
+
|
9
|
+
## Usage
|
10
|
+
|
11
|
+
class UsersIndex
|
12
|
+
include Syphon::Index
|
13
|
+
|
14
|
+
define_source do
|
15
|
+
# Define some attributes. Options like "index: :not_analyzed" are passed
|
16
|
+
# to elasticsearch.
|
17
|
+
|
18
|
+
string :login, index: :not_analyzed
|
19
|
+
string :name
|
20
|
+
integer :age
|
21
|
+
geo_point :location
|
22
|
+
string :bio
|
23
|
+
nested_documents do
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
## Why?
|
30
|
+
|
31
|
+
In 2 words: fast indexing.
|
32
|
+
|
33
|
+
There is no shortage of ElasticSearch adapters for ruby. The issue is that they
|
34
|
+
typically work by defining fields as attributes (methods) on your model
|
35
|
+
instances, which means to index a lot of data, you need to roundtrip your data
|
36
|
+
through heavy ruby models, which can be quite slow, particularly if your models
|
37
|
+
are made of ActiveRecord.
|
38
|
+
|
39
|
+
Syphon makes no such assumption. You define your fields to index using SQL
|
40
|
+
expressions. These are assembled into a single SQL query, and the resulting rows
|
41
|
+
are used to build ElasticSearch documents in an intuitive way using minimal ruby
|
42
|
+
data structures. Those coming from ThinkingSphinx might find this notion -- and
|
43
|
+
syntax -- familiar.
|
44
|
+
|
45
|
+
Syphon is similar in concept to an ElasticSearch river, except it's completely
|
46
|
+
handled off the server. In fact it was originally implemented using the
|
47
|
+
[JDBC river][jdbc-river], but the current incarnation was found to be a little
|
48
|
+
lacking in functionality for a smooth integration (such as documents with
|
49
|
+
multiple nested fields, and synchronous updates for testing).
|
50
|
+
|
51
|
+
Syphon focuses on the indexing aspect only - you are free to choose another gem
|
52
|
+
for the query DSL.
|
53
|
+
|
54
|
+
[jdbc-river]: https://github.com/jprante/elasticsearch-river-jdbc
|
55
|
+
|
56
|
+
## Contributing
|
57
|
+
|
58
|
+
* [Bug reports](https://github.com/howaboutwe/syphon/issues)
|
59
|
+
* [Source](https://github.com/howaboutwe/syphon)
|
60
|
+
* Patches: Fork on Github, send pull request.
|
61
|
+
* Include tests where practical.
|
62
|
+
* Leave the version alone, or bump it in a separate commit.
|
63
|
+
|
64
|
+
## Copyright
|
65
|
+
|
66
|
+
Copyright (c) George Ogata. See LICENSE for details.
|
data/lib/syphon/index.rb
CHANGED
@@ -3,14 +3,16 @@ module Syphon
|
|
3
3
|
def self.included(base)
|
4
4
|
base.extend ClassMethods
|
5
5
|
base.pre_sql ||= []
|
6
|
+
base.index_settings ||= {}
|
6
7
|
super
|
7
8
|
end
|
8
9
|
|
9
10
|
module ClassMethods
|
10
|
-
attr_accessor :pre_sql
|
11
|
+
attr_accessor :pre_sql, :index_settings
|
11
12
|
|
12
13
|
def inherited(subclass)
|
13
14
|
subclass.pre_sql = pre_sql.dup
|
15
|
+
subclass.index_settings = index_settings.dup
|
14
16
|
super
|
15
17
|
end
|
16
18
|
|
@@ -25,11 +27,19 @@ module Syphon
|
|
25
27
|
def index_name
|
26
28
|
@index_name ||=
|
27
29
|
begin
|
28
|
-
|
29
|
-
|
30
|
+
namespace = Syphon.index_namespace
|
31
|
+
if namespace.to_s.empty?
|
32
|
+
index_base_name
|
33
|
+
else
|
34
|
+
"#{namespace}_#{index_base_name}"
|
35
|
+
end
|
30
36
|
end
|
31
37
|
end
|
32
38
|
|
39
|
+
def index_base_name
|
40
|
+
@index_base_name ||= name.sub(/Index\z/, '').underscore.pluralize
|
41
|
+
end
|
42
|
+
|
33
43
|
def sources
|
34
44
|
@sources ||= {}
|
35
45
|
end
|
@@ -38,7 +48,7 @@ module Syphon
|
|
38
48
|
old_internal_name = internal_index_name
|
39
49
|
new_internal_name = new_internal_index_name(index_name)
|
40
50
|
|
41
|
-
client.indices.create(index: new_internal_name)
|
51
|
+
client.indices.create(index: new_internal_name, body: {settings: index_settings})
|
42
52
|
sources.each do |name, source|
|
43
53
|
body = source.mapping
|
44
54
|
client.indices.put_mapping(index: new_internal_name, type: source.type, body: body)
|
@@ -82,9 +92,7 @@ module Syphon
|
|
82
92
|
@warmups ||= []
|
83
93
|
end
|
84
94
|
|
85
|
-
|
86
|
-
|
87
|
-
attr_writer :index_name
|
95
|
+
attr_writer :index_base_name
|
88
96
|
|
89
97
|
private
|
90
98
|
|
data/lib/syphon/railtie.rb
CHANGED
@@ -1,27 +1,51 @@
|
|
1
|
+
require 'erb'
|
2
|
+
require 'yaml'
|
3
|
+
|
1
4
|
module Syphon
|
2
5
|
class Railtie < Rails::Railtie
|
6
|
+
this = self
|
7
|
+
|
3
8
|
rake_tasks do
|
4
9
|
require 'syphon/tasks'
|
5
10
|
end
|
6
11
|
|
7
12
|
initializer "syphon.initialize" do
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
+
this.set_configuration(
|
14
|
+
env: Rails.env,
|
15
|
+
root: Rails.root,
|
16
|
+
app_name: Rails.application.class.parent_name,
|
17
|
+
dbconfig: ActiveRecord::Base.configurations,
|
18
|
+
)
|
19
|
+
end
|
13
20
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
21
|
+
class << self
|
22
|
+
def set_configuration(params = {})
|
23
|
+
env, root, app_name, dbconfig =
|
24
|
+
params.values_at(:env, :root, :app_name, :dbconfig)
|
25
|
+
|
26
|
+
path = "#{root}/config/syphon.yml"
|
27
|
+
if File.exist?(path)
|
28
|
+
erb = File.read(path)
|
29
|
+
yaml = ERB.new(erb).result
|
30
|
+
config = YAML.load(yaml)[env]
|
31
|
+
end
|
32
|
+
|
33
|
+
config ||= {}
|
34
|
+
config.symbolize_keys!
|
35
|
+
config[:log] = normalize_log(env, root, config[:log])
|
36
|
+
config[:database] ||= dbconfig[env].dup
|
37
|
+
config[:index_namespace] ||= "#{app_name.underscore}_#{env}"
|
38
|
+
config[:database].try(:symbolize_keys!)
|
39
|
+
config[:elasticsearch].try(:symbolize_keys!)
|
40
|
+
Syphon.configuration = config
|
20
41
|
end
|
21
42
|
|
22
|
-
|
23
|
-
|
24
|
-
|
43
|
+
private
|
44
|
+
|
45
|
+
def normalize_log(env, root, log)
|
46
|
+
return nil if log == false
|
47
|
+
log ||= "#{root}/log/syphon.#{env}.log"
|
48
|
+
log.start_with?('/') ? log : "#{root}/#{log}"
|
25
49
|
end
|
26
50
|
end
|
27
51
|
end
|
data/lib/syphon/schema.rb
CHANGED
@@ -84,24 +84,25 @@ module Syphon
|
|
84
84
|
end
|
85
85
|
|
86
86
|
class Field
|
87
|
-
def initialize(name, type, expression, options = {})
|
87
|
+
def initialize(schema, name, type, expression, options = {})
|
88
|
+
@schema = schema
|
88
89
|
@name = name.to_sym
|
89
90
|
@type = type
|
90
91
|
@expression = expression
|
91
92
|
@properties = options.merge(type: type)
|
92
93
|
end
|
93
94
|
|
94
|
-
attr_reader :name, :type, :expression, :properties
|
95
|
+
attr_reader :schema, :name, :type, :expression, :properties
|
95
96
|
|
96
97
|
def select(outer = nil)
|
97
98
|
name = outer ? "#{outer}[#{self.name}]" : self.name
|
98
|
-
"#{expression} AS `#{name}`"
|
99
|
+
"#{schema.send(:query_fragment, expression)} AS `#{name}`"
|
99
100
|
end
|
100
101
|
end
|
101
102
|
|
102
103
|
class NestedField < Field
|
103
|
-
def initialize(name, options = {}, &block)
|
104
|
-
super(name, :nested, nil, options)
|
104
|
+
def initialize(schema, name, options = {}, &block)
|
105
|
+
super(schema, name, :nested, nil, options)
|
105
106
|
@nested_schema = Schema.new(&block)
|
106
107
|
end
|
107
108
|
|
@@ -127,7 +128,7 @@ module Syphon
|
|
127
128
|
end
|
128
129
|
|
129
130
|
def field(name, type, expression, options = {})
|
130
|
-
schema.fields[name.to_sym] = Field.new(name, type, expression, options)
|
131
|
+
schema.fields[name.to_sym] = Field.new(schema, name, type, expression, options)
|
131
132
|
end
|
132
133
|
|
133
134
|
%w[string short byte integer long float double date boolean binary geo_point].each do |type|
|
@@ -139,7 +140,7 @@ module Syphon
|
|
139
140
|
end
|
140
141
|
|
141
142
|
def nested(name, options = {}, &block)
|
142
|
-
schema.fields[name.to_sym] = NestedField.new(name, options, &block)
|
143
|
+
schema.fields[name.to_sym] = NestedField.new(schema, name, options, &block)
|
143
144
|
end
|
144
145
|
|
145
146
|
{
|
data/lib/syphon/version.rb
CHANGED
data/lib/syphon.rb
CHANGED
@@ -10,31 +10,58 @@ module Syphon
|
|
10
10
|
autoload :VERSION, 'syphon/version'
|
11
11
|
|
12
12
|
class << self
|
13
|
-
attr_writer :configuration
|
13
|
+
attr_writer :configuration
|
14
14
|
|
15
15
|
def configuration
|
16
16
|
@configuration ||= {}
|
17
17
|
end
|
18
18
|
|
19
19
|
def database_configuration
|
20
|
-
|
20
|
+
configuration[:database] || {}
|
21
|
+
end
|
22
|
+
|
23
|
+
def elasticsearch_configuration
|
24
|
+
configuration = Syphon.configuration[:elasticsearch].try(:dup) || {}
|
25
|
+
configuration[:logger] = logger
|
26
|
+
configuration
|
21
27
|
end
|
22
28
|
|
23
29
|
def index_namespace
|
24
|
-
|
30
|
+
configuration[:index_namespace]
|
25
31
|
end
|
26
32
|
|
27
33
|
def database_connection
|
28
|
-
|
34
|
+
Thread.current[:syphon_database_connection] ||= Mysql2::Client.new(database_configuration)
|
29
35
|
end
|
30
36
|
|
31
37
|
def client
|
32
|
-
Thread.current[:syphon_client] ||= Elasticsearch::Client.new(
|
38
|
+
Thread.current[:syphon_client] ||= Elasticsearch::Client.new(elasticsearch_configuration)
|
33
39
|
end
|
34
40
|
|
35
41
|
def index_classes
|
36
42
|
Syphon.configuration['index_classes'].map(&:constantize)
|
37
43
|
end
|
44
|
+
|
45
|
+
def logger
|
46
|
+
Thread.current[:syphon_logger] ||= make_logger
|
47
|
+
end
|
48
|
+
|
49
|
+
def logger=(logger)
|
50
|
+
Thread.current[:syphon_logger] = logger
|
51
|
+
end
|
52
|
+
|
53
|
+
private
|
54
|
+
|
55
|
+
def make_logger
|
56
|
+
log = Syphon.configuration[:log] || STDOUT
|
57
|
+
Logger.new(log).tap do |logger|
|
58
|
+
logger.formatter = lambda do |level, time, progname, message|
|
59
|
+
"#{time.strftime('%Y-%m-%d: %H:%M:%S')}: #{level}: #{message}\n"
|
60
|
+
end
|
61
|
+
level = configuration[:log_level] and
|
62
|
+
logger.level = Logger.const_get(level.upcase)
|
63
|
+
end
|
64
|
+
end
|
38
65
|
end
|
39
66
|
end
|
40
67
|
|
data/test/syphon/test_index.rb
CHANGED
@@ -12,15 +12,15 @@ describe Syphon::Index do
|
|
12
12
|
|
13
13
|
describe ".index_name" do
|
14
14
|
describe "when no index namespace is set" do
|
15
|
-
use_attribute_value Syphon, :
|
15
|
+
use_attribute_value Syphon, :configuration, {index_namespace: nil}
|
16
16
|
|
17
|
-
it "it
|
17
|
+
it "it is the index base name" do
|
18
18
|
TestIndex.index_name.must_equal 'tests'
|
19
19
|
end
|
20
20
|
end
|
21
21
|
|
22
22
|
describe "when the index namespace is empty" do
|
23
|
-
use_attribute_value Syphon, :
|
23
|
+
use_attribute_value Syphon, :configuration, {index_namespace: ''}
|
24
24
|
|
25
25
|
it "it is treated the same as nil" do
|
26
26
|
TestIndex.index_name.must_equal 'tests'
|
@@ -32,10 +32,21 @@ describe Syphon::Index do
|
|
32
32
|
TestIndex.index_name.must_equal 'syphon_tests'
|
33
33
|
end
|
34
34
|
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".index_base_name" do
|
38
|
+
it "is based on the class name" do
|
39
|
+
TestIndex.index_base_name.must_equal 'tests'
|
40
|
+
end
|
41
|
+
|
42
|
+
it "can be overridden" do
|
43
|
+
TestIndex.index_base_name = 'wibble'
|
44
|
+
TestIndex.index_base_name.must_equal 'wibble'
|
45
|
+
end
|
35
46
|
|
36
|
-
it "
|
37
|
-
TestIndex.
|
38
|
-
TestIndex.index_name.must_equal '
|
47
|
+
it "contributes to the index name" do
|
48
|
+
TestIndex.index_base_name = 'wibble'
|
49
|
+
TestIndex.index_name.must_equal 'syphon_wibble'
|
39
50
|
end
|
40
51
|
end
|
41
52
|
|
@@ -95,6 +106,14 @@ describe Syphon::Index do
|
|
95
106
|
hits.map { |doc| doc['_source']['login'] }.must_equal ['bob']
|
96
107
|
end
|
97
108
|
|
109
|
+
it "passes configured index settings" do
|
110
|
+
TestIndex.index_settings = {number_of_shards: 23}
|
111
|
+
TestIndex.build
|
112
|
+
index = TestIndex.client.indices.get_alias(name: TestIndex.index_name).keys.first
|
113
|
+
num_shards = client.indices.get_settings[index]['settings']['index.number_of_shards']
|
114
|
+
num_shards.must_equal '23'
|
115
|
+
end
|
116
|
+
|
98
117
|
it "runs all warmups between building the new index and rotating it in" do
|
99
118
|
this = self
|
100
119
|
runs = []
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require_relative '../test_helper'
|
2
|
+
|
3
|
+
describe Syphon::Railtie do
|
4
|
+
use_attribute_value Syphon, :configuration, {}
|
5
|
+
|
6
|
+
describe ".set_configuration" do
|
7
|
+
use_temporary_directory "#{ROOT}/test/tmp"
|
8
|
+
|
9
|
+
let(:params) do
|
10
|
+
{
|
11
|
+
env: 'test',
|
12
|
+
root: tmp,
|
13
|
+
app_name: 'MyApp',
|
14
|
+
dbconfig: {'test' => {'database' => 'ardb'}},
|
15
|
+
}
|
16
|
+
end
|
17
|
+
|
18
|
+
def write_config(data)
|
19
|
+
FileUtils.mkdir_p "#{tmp}/config"
|
20
|
+
open("#{tmp}/config/syphon.yml", 'w') { |f| f.print data.to_yaml }
|
21
|
+
end
|
22
|
+
|
23
|
+
describe "when no configuration file is present" do
|
24
|
+
it "sets all the defaults" do
|
25
|
+
Syphon::Railtie.set_configuration(params)
|
26
|
+
Syphon.configuration[:log].must_equal "#{tmp}/log/syphon.test.log"
|
27
|
+
Syphon.configuration[:database].must_equal({database: 'ardb'})
|
28
|
+
Syphon.configuration[:index_namespace].must_equal('my_app_test')
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "when a configuration file is present, but no key for the environment" do
|
33
|
+
it "sets all the defaults" do
|
34
|
+
write_config('other_env' => 'blah')
|
35
|
+
Syphon::Railtie.set_configuration(params)
|
36
|
+
Syphon.configuration[:log].must_equal "#{tmp}/log/syphon.test.log"
|
37
|
+
Syphon.configuration[:database].must_equal({database: 'ardb'})
|
38
|
+
Syphon.configuration[:index_namespace].must_equal('my_app_test')
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "when a valid configuration is present" do
|
43
|
+
it "sets the configuration" do
|
44
|
+
write_config('test' => {'reload_on_failure' => true})
|
45
|
+
Syphon::Railtie.set_configuration(params)
|
46
|
+
Syphon.configuration[:reload_on_failure].must_equal true
|
47
|
+
end
|
48
|
+
|
49
|
+
it "defaults the index namespace to one based on the app name and Rails env" do
|
50
|
+
Syphon::Railtie.set_configuration(params)
|
51
|
+
Syphon.index_namespace.must_equal 'my_app_test'
|
52
|
+
end
|
53
|
+
|
54
|
+
it "sets a custom index namespace if configured" do
|
55
|
+
write_config('test' => {'index_namespace' => 'my_namespace'})
|
56
|
+
Syphon::Railtie.set_configuration(params)
|
57
|
+
Syphon.index_namespace.must_equal 'my_namespace'
|
58
|
+
end
|
59
|
+
|
60
|
+
it "sets a good default log path" do
|
61
|
+
write_config('test' => {})
|
62
|
+
Syphon::Railtie.set_configuration(params)
|
63
|
+
Syphon.configuration[:log].must_equal "#{tmp}/log/syphon.test.log"
|
64
|
+
end
|
65
|
+
|
66
|
+
it "expands a given log path relative to the rails root" do
|
67
|
+
write_config('test' => {'log' => 'path/to/my.log'})
|
68
|
+
Syphon::Railtie.set_configuration(params)
|
69
|
+
Syphon.configuration[:log].must_equal "#{tmp}/path/to/my.log"
|
70
|
+
end
|
71
|
+
|
72
|
+
it "sets no log if the log option is false" do
|
73
|
+
write_config('test' => {'log' => false})
|
74
|
+
Syphon::Railtie.set_configuration(params)
|
75
|
+
Syphon.configuration[:log].must_be_nil
|
76
|
+
end
|
77
|
+
|
78
|
+
it "sets the given database configuration" do
|
79
|
+
write_config('test' => {'database' => {'database' => 'mydb'}})
|
80
|
+
Syphon::Railtie.set_configuration(params)
|
81
|
+
Syphon.database_configuration.must_equal({database: 'mydb'})
|
82
|
+
end
|
83
|
+
|
84
|
+
it "defaults to the primary ActiveRecord configuration" do
|
85
|
+
write_config('test' => {})
|
86
|
+
Syphon::Railtie.set_configuration(params)
|
87
|
+
Syphon.database_configuration.must_equal({database: 'ardb'})
|
88
|
+
end
|
89
|
+
|
90
|
+
it "sets the given elasticsearch configuration" do
|
91
|
+
FileUtils.mkdir_p "#{tmp}/log"
|
92
|
+
write_config('test' => {'elasticsearch' => {'reload_on_failure' => true}})
|
93
|
+
Syphon::Railtie.set_configuration(params)
|
94
|
+
Syphon.elasticsearch_configuration[:reload_on_failure].must_equal true
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
data/test/syphon/test_schema.rb
CHANGED
@@ -180,14 +180,38 @@ describe Syphon::Schema do
|
|
180
180
|
having 'count(*) = 1'
|
181
181
|
end
|
182
182
|
schema.query.must_equal <<-EOS.strip.gsub(/\s+/, ' ')
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
183
|
+
SELECT S AS `s`, T AS `inner[t]`
|
184
|
+
FROM things
|
185
|
+
INNER JOIN a ON 1
|
186
|
+
INNER JOIN b ON 2
|
187
|
+
WHERE a = 1
|
188
|
+
GROUP BY x
|
189
|
+
HAVING count(*) = 1
|
190
|
+
EOS
|
191
|
+
end
|
192
|
+
|
193
|
+
it "calls blocks for dynamic queries" do
|
194
|
+
schema = Syphon::Schema.new do
|
195
|
+
string :s, -> { 'S' }
|
196
|
+
nested :inner do
|
197
|
+
string :t, -> { 'T' }
|
198
|
+
end
|
199
|
+
from -> { 'things' }
|
200
|
+
join -> { 'INNER JOIN a ON 1' }
|
201
|
+
join -> { 'INNER JOIN b ON 2' }
|
202
|
+
where -> { 'a = 1' }
|
203
|
+
group_by -> { 'x' }
|
204
|
+
having -> { 'count(*) = 1' }
|
205
|
+
end
|
206
|
+
schema.query.must_equal <<-EOS.strip.gsub(/\s+/, ' ')
|
207
|
+
SELECT S AS `s`, T AS `inner[t]`
|
208
|
+
FROM things
|
209
|
+
INNER JOIN a ON 1
|
210
|
+
INNER JOIN b ON 2
|
211
|
+
WHERE a = 1
|
212
|
+
GROUP BY x
|
213
|
+
HAVING count(*) = 1
|
214
|
+
EOS
|
191
215
|
end
|
192
216
|
|
193
217
|
it "omits optional clauses when in the minimal case" do
|
@@ -268,4 +292,3 @@ describe Syphon::Schema do
|
|
268
292
|
end
|
269
293
|
end
|
270
294
|
end
|
271
|
-
|
data/test/test_helper.rb
CHANGED
@@ -3,16 +3,18 @@ ROOT = File.expand_path('..', File.dirname(__FILE__))
|
|
3
3
|
$:.unshift "#{ROOT}/lib"
|
4
4
|
require 'minitest/spec'
|
5
5
|
require 'yaml'
|
6
|
+
require 'fileutils'
|
6
7
|
require 'temporaries'
|
7
8
|
require 'debugger' if RUBY_VERSION < '2.0'
|
8
9
|
require 'looksee'
|
10
|
+
require 'rails'
|
9
11
|
|
10
12
|
require 'syphon'
|
11
13
|
|
12
|
-
config = YAML.load_file("#{ROOT}/test/config.yml")
|
13
|
-
|
14
|
-
Syphon.configuration = config
|
15
|
-
Syphon.
|
14
|
+
config = YAML.load_file("#{ROOT}/test/config.yml").symbolize_keys
|
15
|
+
config[:database].symbolize_keys!
|
16
|
+
Syphon.configuration = config.merge(index_namespace: 'syphon')
|
17
|
+
Syphon.logger = Logger.new('/dev/null')
|
16
18
|
|
17
19
|
MiniTest::Spec.class_eval do
|
18
20
|
def self.uses_users_table
|
data/test/test_syphon.rb
CHANGED
@@ -10,7 +10,7 @@ describe Syphon do
|
|
10
10
|
end
|
11
11
|
|
12
12
|
describe ".database_configuration" do
|
13
|
-
use_instance_variable_value Syphon, :
|
13
|
+
use_instance_variable_value Syphon, :configuration, nil
|
14
14
|
|
15
15
|
it "defaults to an empty hash" do
|
16
16
|
Syphon.database_configuration.must_equal({})
|
@@ -18,11 +18,61 @@ describe Syphon do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
describe ".index_namespace" do
|
21
|
-
|
22
|
-
|
21
|
+
describe "when a namespace is configured" do
|
22
|
+
use_instance_variable_value Syphon, :configuration, {index_namespace: 'NAMESPACE'}
|
23
23
|
|
24
|
-
|
25
|
-
|
24
|
+
it "is the configured index namespace" do
|
25
|
+
Syphon.index_namespace.must_equal('NAMESPACE')
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when no namespace is configured" do
|
30
|
+
use_instance_variable_value Syphon, :configuration, {}
|
31
|
+
|
32
|
+
it "is nil" do
|
33
|
+
Syphon.index_namespace.must_be_nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe ".database_configuration" do
|
39
|
+
use_attribute_value Syphon, :configuration, nil
|
40
|
+
|
41
|
+
it "uses the configured database configuration" do
|
42
|
+
Syphon.configuration = {database: {database: 'mydb'}}
|
43
|
+
Syphon.database_configuration.must_equal({database: 'mydb'})
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe ".elasticsearch_configuration" do
|
48
|
+
use_attribute_value Syphon, :configuration, nil
|
49
|
+
use_attribute_value Syphon, :logger, nil
|
50
|
+
use_temporary_directory "#{ROOT}/test/tmp"
|
51
|
+
|
52
|
+
it "includes all configured elasticserach settings" do
|
53
|
+
Syphon.configuration = {elasticsearch: {reload_on_failure: true}}
|
54
|
+
Syphon.elasticsearch_configuration[:reload_on_failure].must_equal true
|
55
|
+
end
|
56
|
+
|
57
|
+
it "adds the Syphon logger" do
|
58
|
+
logger = Logger.new(logger)
|
59
|
+
Syphon.logger = logger
|
60
|
+
Syphon.elasticsearch_configuration[:logger].must_equal logger
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
describe ".logger" do
|
65
|
+
use_attribute_value Syphon, :configuration, nil
|
66
|
+
use_attribute_value Syphon, :logger, nil
|
67
|
+
use_temporary_directory "#{ROOT}/test/tmp"
|
68
|
+
|
69
|
+
it "uses the configured log path and log level" do
|
70
|
+
Syphon.configuration[:log] = "#{tmp}/syphon.log"
|
71
|
+
Syphon.configuration[:log_level] = 'info'
|
72
|
+
Syphon.logger.debug 'DEBUG LEVEL'
|
73
|
+
Syphon.logger.info 'INFO LEVEL'
|
74
|
+
File.read("#{ROOT}/test/tmp/syphon.log").wont_include 'DEBUG LEVEL'
|
75
|
+
File.read("#{ROOT}/test/tmp/syphon.log").must_include 'INFO LEVEL'
|
26
76
|
end
|
27
77
|
end
|
28
78
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: syphon
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-12-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: elasticsearch
|
@@ -100,6 +100,7 @@ files:
|
|
100
100
|
- test/config.yml.sample
|
101
101
|
- test/syphon/test_builder.rb
|
102
102
|
- test/syphon/test_index.rb
|
103
|
+
- test/syphon/test_railtie.rb
|
103
104
|
- test/syphon/test_schema.rb
|
104
105
|
- test/syphon/test_source.rb
|
105
106
|
- test/test_helper.rb
|
@@ -118,7 +119,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
118
119
|
version: '0'
|
119
120
|
segments:
|
120
121
|
- 0
|
121
|
-
hash: -
|
122
|
+
hash: -2157484304572429612
|
122
123
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
123
124
|
none: false
|
124
125
|
requirements:
|
@@ -127,7 +128,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
127
128
|
version: '0'
|
128
129
|
segments:
|
129
130
|
- 0
|
130
|
-
hash: -
|
131
|
+
hash: -2157484304572429612
|
131
132
|
requirements: []
|
132
133
|
rubyforge_project:
|
133
134
|
rubygems_version: 1.8.25
|
@@ -138,6 +139,7 @@ test_files:
|
|
138
139
|
- test/config.yml.sample
|
139
140
|
- test/syphon/test_builder.rb
|
140
141
|
- test/syphon/test_index.rb
|
142
|
+
- test/syphon/test_railtie.rb
|
141
143
|
- test/syphon/test_schema.rb
|
142
144
|
- test/syphon/test_source.rb
|
143
145
|
- test/test_helper.rb
|