runes 0.1.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.
- data/Gemfile +8 -0
- data/Gemfile.lock +18 -0
- data/LICENSE +24 -0
- data/README.markdown +39 -0
- data/Rakefile +43 -0
- data/VERSION +1 -0
- data/lib/runes.rb +22 -0
- data/lib/runes/base.rb +18 -0
- data/lib/runes/janitor.rb +36 -0
- data/lib/runes/orm/active_record.rb +38 -0
- data/lib/runes/railtie.rb +33 -0
- data/lib/runes/rubberband_extension.rb +12 -0
- data/test/runes_test.rb +17 -0
- data/test/test_helper.rb +21 -0
- data/test/test_unit_extension.rb +21 -0
- metadata +110 -0
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
elasticsearch (0.0.0)
|
5
|
+
git (1.2.5)
|
6
|
+
jeweler (1.5.2)
|
7
|
+
bundler (~> 1.0.0)
|
8
|
+
git (>= 1.2.5)
|
9
|
+
rake
|
10
|
+
rake (0.8.7)
|
11
|
+
|
12
|
+
PLATFORMS
|
13
|
+
ruby
|
14
|
+
|
15
|
+
DEPENDENCIES
|
16
|
+
bundler (~> 1.0.0)
|
17
|
+
elasticsearch
|
18
|
+
jeweler (~> 1.5.2)
|
data/LICENSE
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
Copyright (c) 2011, Stephano Zanzin
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are met:
|
6
|
+
1. Redistributions of source code must retain the above copyright
|
7
|
+
notice, this list of conditions and the following disclaimer.
|
8
|
+
2. Redistributions in binary form must reproduce the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer in the
|
10
|
+
documentation and/or other materials provided with the distribution.
|
11
|
+
3. Neither the name of the Stephano Zanzin nor the
|
12
|
+
names of its contributors may be used to endorse or promote products
|
13
|
+
derived from this software without specific prior written permission.
|
14
|
+
|
15
|
+
THIS SOFTWARE IS PROVIDED BY STEPHANO ZANZIN ''AS IS'' AND ANY
|
16
|
+
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
17
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL STEPHANO ZANZIN BE LIABLE FOR ANY
|
19
|
+
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
20
|
+
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
21
|
+
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
22
|
+
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
23
|
+
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
24
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/README.markdown
ADDED
@@ -0,0 +1,39 @@
|
|
1
|
+
Runes
|
2
|
+
======
|
3
|
+
|
4
|
+
Runes is a Railtie to index your models using the modern Elasticsearch as backend, which have possibilities ranging from a simple single-node index manipulation to a highly populated cluster.
|
5
|
+
|
6
|
+
Elasticsearch
|
7
|
+
-------------
|
8
|
+
|
9
|
+
Elasticsearch is a powerful easy-to-use search engine built on top of Apache Lucene. It aims to solve many problems found when search is needed providing an amazing RESTful interface and complete ability to scale using a innovative distributed architecture. For more information check their [website](http://www.elasticsearch.org/).
|
10
|
+
|
11
|
+
Getting started
|
12
|
+
-------------
|
13
|
+
|
14
|
+
First of all, this plugin was designed using the new Railtie architecture, so it's only supported by Rails 3. If you are new to elasticsearch I encourage you to install it using their [installation guide](http://www.elasticsearch.org/guide/reference/setup/installation.html).
|
15
|
+
|
16
|
+
Install the latest gem in the conventional manner:
|
17
|
+
|
18
|
+
gem install runes
|
19
|
+
|
20
|
+
Specify the models you want to index:
|
21
|
+
|
22
|
+
class Cake < ActiveRecord::Base
|
23
|
+
acts_as_indexable
|
24
|
+
end
|
25
|
+
|
26
|
+
After you have installed Runes and specified the models just fire your Rails app. Voila! You are able to index and search.
|
27
|
+
|
28
|
+
Cake.create!(:name => "chocolate", :category => "fatty")
|
29
|
+
Cake.search("chocolate")
|
30
|
+
|
31
|
+
Author
|
32
|
+
------
|
33
|
+
|
34
|
+
Stephano Zanzin :: me@zan.st :: zanst @ Freenode
|
35
|
+
|
36
|
+
NOTICE
|
37
|
+
------
|
38
|
+
|
39
|
+
Work in progress, if you are not a code diver I recommend wait for a tag.
|
data/Rakefile
ADDED
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/testtask'
|
3
|
+
require 'rake/rdoctask'
|
4
|
+
require 'psych' unless RUBY_VERSION < '1.9.2'
|
5
|
+
|
6
|
+
desc 'Default: run unit tests.'
|
7
|
+
task :default => :test
|
8
|
+
|
9
|
+
desc 'Test the runes plugin.'
|
10
|
+
Rake::TestTask.new(:test) do |t|
|
11
|
+
t.libs << 'lib'
|
12
|
+
t.libs << 'test'
|
13
|
+
t.pattern = 'test/**/*_test.rb'
|
14
|
+
t.verbose = true
|
15
|
+
end
|
16
|
+
|
17
|
+
desc 'Generate documentation for the runes plugin.'
|
18
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
19
|
+
rdoc.rdoc_dir = 'rdoc'
|
20
|
+
rdoc.title = 'Runes'
|
21
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
22
|
+
rdoc.rdoc_files.include('README')
|
23
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'Build gem for the runes railtie.'
|
27
|
+
begin
|
28
|
+
require 'jeweler'
|
29
|
+
Jeweler::Tasks.new do |gem|
|
30
|
+
gem.name = 'runes'
|
31
|
+
gem.summary = 'Elasticsearch Railtie'
|
32
|
+
gem.description = 'Implements search to your models easily using elasticsearch as engine.'
|
33
|
+
gem.email = 'me@zan.st'
|
34
|
+
gem.homepage = 'http://github.com/zanst/runes'
|
35
|
+
gem.authors = ['Stephano Zanzin']
|
36
|
+
gem.files = Dir['*', '{lib}/**/*']
|
37
|
+
gem.add_dependency('rubberband')
|
38
|
+
end
|
39
|
+
|
40
|
+
Jeweler::GemcutterTasks.new
|
41
|
+
rescue LoadError
|
42
|
+
puts 'Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler'
|
43
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/lib/runes.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'rails'
|
2
|
+
require 'rubberband'
|
3
|
+
|
4
|
+
module Runes
|
5
|
+
require 'runes/base'
|
6
|
+
require 'runes/janitor'
|
7
|
+
require 'runes/orm/active_record'
|
8
|
+
require 'runes/railtie' if defined?(Rails)
|
9
|
+
require 'runes/rubberband_ext'
|
10
|
+
|
11
|
+
begin
|
12
|
+
config_path = Rails.root.to_s + '/config/runes.yml'
|
13
|
+
@config = YAML.load_file(config_path)
|
14
|
+
rescue
|
15
|
+
@config = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
if Runes::Janitor.es_is_running?
|
19
|
+
@server_host = @config.nil? ? '127.0.0.1:9200' : @config['host'] + ':' + @config['port']
|
20
|
+
$es_client = ElasticSearch.new(@server_host)
|
21
|
+
end
|
22
|
+
end
|
data/lib/runes/base.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Runes
|
2
|
+
module Janitor
|
3
|
+
class << self
|
4
|
+
def setup!
|
5
|
+
if Runes::Janitor.es_is_running?
|
6
|
+
begin
|
7
|
+
Runes::Base.actors.each do |actor|
|
8
|
+
$es_client.create_index(actor)
|
9
|
+
end
|
10
|
+
rescue ElasticSearch::RequestError
|
11
|
+
return true
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# This function was created because rubberband
|
17
|
+
# behaves strangely and doesn't inform properly
|
18
|
+
# when elasticsearch isn't running.
|
19
|
+
def es_is_running?
|
20
|
+
require 'socket'
|
21
|
+
if @config.nil?
|
22
|
+
# getting the longer line possible to avoid problems in different operating systems.
|
23
|
+
process_status = system("ps auxwwww | grep org.elasticsearch.bootstrap | grep -v grep >> /dev/null")
|
24
|
+
return process_status
|
25
|
+
else
|
26
|
+
net_status = TCPSocket.open(@config['host'], @config['port'].to_i)
|
27
|
+
if net_status.nil?
|
28
|
+
return false
|
29
|
+
else
|
30
|
+
return true
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Runes
|
2
|
+
module Orm
|
3
|
+
module ActiveRecord
|
4
|
+
attr_accessor :index_name
|
5
|
+
attr_accessor :type_name
|
6
|
+
|
7
|
+
def acts_as_indexable(options={})
|
8
|
+
send :include, InstanceMethods
|
9
|
+
@index_name = self.name.underscore.gsub(/\//, '-').pluralize
|
10
|
+
@type_name = self.name.underscore.gsub(/\//, '-').singularize
|
11
|
+
Runes::Base.set_actor(@index_name)
|
12
|
+
after_destroy :destroy_object_from_index
|
13
|
+
after_save :add_object_to_index
|
14
|
+
end
|
15
|
+
|
16
|
+
def search(query)
|
17
|
+
search = Runes::Base.search(query, @index_name)
|
18
|
+
results = search.map{|result| result.ar_equivalence}
|
19
|
+
return results.sort_by(&:created_at)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
module InstanceMethods
|
24
|
+
def destroy_object_from_index
|
25
|
+
$es_client.delete(self.id.to_s, :index => self.class.index_name, :type => self.class.type_name)
|
26
|
+
end
|
27
|
+
|
28
|
+
def add_object_to_index
|
29
|
+
begin
|
30
|
+
destroy_object_from_index
|
31
|
+
$es_client.index(self.to_json, :id => self.id, :index => self.class.index_name, :type => self.class.type_name)
|
32
|
+
rescue
|
33
|
+
$es_client.index(self.to_json, :id => self.id, :index => self.class.index_name, :type => self.class.type_name)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'runes'
|
2
|
+
require 'rails'
|
3
|
+
|
4
|
+
module Runes
|
5
|
+
class Railtie < Rails::Railtie
|
6
|
+
# Check if elasticsearch is running.
|
7
|
+
initializer 'runes.check_es_status', :before => 'i18n.callbacks' do
|
8
|
+
if Runes::Janitor.es_is_running? == false
|
9
|
+
raise "Elasticsearch server is not running."
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
# Include module into Rubberband's ElasticSearch::Api::Hit
|
14
|
+
initializer 'runes.include.rubberband', :before => 'active_record.initialize_timezone' do
|
15
|
+
ElasticSearch::Api::Hit.send :include, Runes::RubberbandExtension
|
16
|
+
end
|
17
|
+
|
18
|
+
# Extends module into active_record.
|
19
|
+
initializer 'runes.extend.active_record', :after => 'runes.include.rubberband' do
|
20
|
+
ActiveRecord::Base.send :extend, Runes::Orm::ActiveRecord
|
21
|
+
end
|
22
|
+
|
23
|
+
# Initialize models in order to perform the Runes function.
|
24
|
+
initializer 'runes.req_models', :after => :engines_blank_point do
|
25
|
+
Dir.glob(Rails.root.to_s + '/app/models/*.rb').each { |file| require file }
|
26
|
+
end
|
27
|
+
|
28
|
+
# Verify and setup the actors defined by the user.
|
29
|
+
initializer 'runes.create_indexes', :after => 'runes.req_models' do
|
30
|
+
Runes::Janitor.setup!
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
data/test/runes_test.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class RunesTest < ActiveSupport::TestCase
|
4
|
+
setup do
|
5
|
+
setup_db
|
6
|
+
ActiveRecord::Base.send :extend, Runes::Orm::ActiveRecord
|
7
|
+
end
|
8
|
+
|
9
|
+
must "execute method and add object to index" do
|
10
|
+
class Nut < ActiveRecord::Base
|
11
|
+
acts_as_indexable
|
12
|
+
end
|
13
|
+
Nut.create!(:name => "nutixious", :content => "nuts do crackle")
|
14
|
+
assert_equal 1, Nut.all.count
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'test/unit'
|
3
|
+
require 'active_support'
|
4
|
+
require 'active_record'
|
5
|
+
require 'test_unit_extension'
|
6
|
+
|
7
|
+
def setup_db
|
8
|
+
ActiveRecord::Base.establish_connection(:adapter => 'sqlite3', :database => ':memory:')
|
9
|
+
|
10
|
+
ActiveRecord::Schema.define(:version => 0) do
|
11
|
+
create_table :nuts, :force => true do |t|
|
12
|
+
t.string :name
|
13
|
+
t.text :content
|
14
|
+
t.datetime :created_at
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
require File.dirname(__FILE__) + '/../lib/runes'
|
19
|
+
end
|
20
|
+
|
21
|
+
ActiveSupport::TestCase.send :extend, Test::Unit
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Test::Unit
|
2
|
+
# Used to fix a minor minitest/unit incompatibility in flexmock
|
3
|
+
AssertionFailedError = Class.new(StandardError)
|
4
|
+
|
5
|
+
class TestCase
|
6
|
+
|
7
|
+
def self.must(name, &block)
|
8
|
+
test_name = "test_#{name.gsub(/\s+/,'_')}".to_sym
|
9
|
+
defined = instance_method(test_name) rescue false
|
10
|
+
raise "#{test_name} is already defined in #{self}" if defined
|
11
|
+
if block_given?
|
12
|
+
define_method(test_name, &block)
|
13
|
+
else
|
14
|
+
define_method(test_name) do
|
15
|
+
flunk "No implementation provided for #{name}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,110 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: runes
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Stephano Zanzin
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-05-15 00:00:00.000000000 -03:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: rubberband
|
17
|
+
requirement: &7573140 !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - ! '>='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: '0'
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: *7573140
|
26
|
+
- !ruby/object:Gem::Dependency
|
27
|
+
name: bundler
|
28
|
+
requirement: &7564440 !ruby/object:Gem::Requirement
|
29
|
+
none: false
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.0.0
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: *7564440
|
37
|
+
- !ruby/object:Gem::Dependency
|
38
|
+
name: jeweler
|
39
|
+
requirement: &7563100 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ~>
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: 1.5.2
|
45
|
+
type: :development
|
46
|
+
prerelease: false
|
47
|
+
version_requirements: *7563100
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: rubberband
|
50
|
+
requirement: &7561660 !ruby/object:Gem::Requirement
|
51
|
+
none: false
|
52
|
+
requirements:
|
53
|
+
- - ! '>='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: '0'
|
56
|
+
type: :runtime
|
57
|
+
prerelease: false
|
58
|
+
version_requirements: *7561660
|
59
|
+
description: Implements search to your models easily using elasticsearch as engine.
|
60
|
+
email: me@zan.st
|
61
|
+
executables: []
|
62
|
+
extensions: []
|
63
|
+
extra_rdoc_files:
|
64
|
+
- LICENSE
|
65
|
+
- README.markdown
|
66
|
+
files:
|
67
|
+
- Gemfile
|
68
|
+
- Gemfile.lock
|
69
|
+
- LICENSE
|
70
|
+
- README.markdown
|
71
|
+
- Rakefile
|
72
|
+
- VERSION
|
73
|
+
- lib/runes.rb
|
74
|
+
- lib/runes/base.rb
|
75
|
+
- lib/runes/janitor.rb
|
76
|
+
- lib/runes/orm/active_record.rb
|
77
|
+
- lib/runes/railtie.rb
|
78
|
+
- lib/runes/rubberband_extension.rb
|
79
|
+
- test/runes_test.rb
|
80
|
+
- test/test_helper.rb
|
81
|
+
- test/test_unit_extension.rb
|
82
|
+
has_rdoc: true
|
83
|
+
homepage: http://github.com/zanst/runes
|
84
|
+
licenses: []
|
85
|
+
post_install_message:
|
86
|
+
rdoc_options: []
|
87
|
+
require_paths:
|
88
|
+
- lib
|
89
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
90
|
+
none: false
|
91
|
+
requirements:
|
92
|
+
- - ! '>='
|
93
|
+
- !ruby/object:Gem::Version
|
94
|
+
version: '0'
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
96
|
+
none: false
|
97
|
+
requirements:
|
98
|
+
- - ! '>='
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
version: '0'
|
101
|
+
requirements: []
|
102
|
+
rubyforge_project:
|
103
|
+
rubygems_version: 1.6.2
|
104
|
+
signing_key:
|
105
|
+
specification_version: 3
|
106
|
+
summary: Elasticsearch Railtie
|
107
|
+
test_files:
|
108
|
+
- test/runes_test.rb
|
109
|
+
- test/test_helper.rb
|
110
|
+
- test/test_unit_extension.rb
|