bigindex 0.1.0
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/MIT-LICENSE +20 -0
- data/README.rdoc +58 -0
- data/Rakefile +14 -0
- data/VERSION +1 -0
- data/examples/bigindex.yml +9 -0
- data/generators/bigindex/bigindex_generator.rb +17 -0
- data/generators/bigindex/templates/bigindex.rake +3 -0
- data/init.rb +27 -0
- data/install.rb +15 -0
- data/lib/big_index/adapters/abstract_adapter.rb +70 -0
- data/lib/big_index/adapters/solr_adapter.rb +180 -0
- data/lib/big_index/adapters.rb +11 -0
- data/lib/big_index/index_field.rb +41 -0
- data/lib/big_index/repository.rb +77 -0
- data/lib/big_index/resource.rb +462 -0
- data/lib/big_index/support/assertions.rb +8 -0
- data/lib/big_index/support.rb +3 -0
- data/lib/big_index.rb +108 -0
- data/lib/bigindex.rb +1 -0
- data/rails/init.rb +27 -0
- data/spec/connections/activerecord/activerecord.yml +7 -0
- data/spec/connections/activerecord/connection.rb +19 -0
- data/spec/connections/bigindex.yml +7 -0
- data/spec/connections/bigrecord/bigrecord.yml +13 -0
- data/spec/connections/bigrecord/connection.rb +29 -0
- data/spec/connections/bigrecord/migrations/20090706182535_add_animals_table.rb +13 -0
- data/spec/connections/bigrecord/migrations/20090706190623_add_books_table.rb +15 -0
- data/spec/connections/bigrecord/migrations/20090706193019_add_companies_table.rb +14 -0
- data/spec/connections/bigrecord/migrations/20090706194512_add_employees_table.rb +13 -0
- data/spec/connections/bigrecord/migrations/20090706195741_add_zoos_table.rb +13 -0
- data/spec/lib/activerecord/animal.rb +14 -0
- data/spec/lib/activerecord/book.rb +26 -0
- data/spec/lib/activerecord/novel.rb +10 -0
- data/spec/lib/bigrecord/animal.rb +11 -0
- data/spec/lib/bigrecord/book.rb +27 -0
- data/spec/lib/bigrecord/novel.rb +7 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +28 -0
- data/spec/unit/adapters/abstract_adapter_spec.rb +48 -0
- data/spec/unit/adapters/adapter_shared_spec.rb +10 -0
- data/spec/unit/adapters/solr_adapter_spec.rb +16 -0
- data/spec/unit/bigindex_setup_spec.rb +70 -0
- data/spec/unit/index_shared_spec.rb +59 -0
- data/spec/unit/index_spec.rb +225 -0
- data/spec/unit/inherited_class_spec.rb +42 -0
- data/tasks/gem.rb +20 -0
- data/tasks/rdoc.rb +8 -0
- data/tasks/spec.rb +38 -0
- data/vendor/solr/adapter_methods/search_results.rb +53 -0
- data/vendor/solr/adapter_methods/solr_result.rb +137 -0
- data/vendor/solr/adapter_methods.rb +360 -0
- data/vendor/solr/base.rb +159 -0
- data/vendor/solr.rb +20 -0
- metadata +147 -0
data/MIT-LICENSE
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
Copyright (c) 2009 openplaces.org
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
|
4
|
+
a copy of this software and associated documentation files (the
|
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
|
9
|
+
the following conditions:
|
|
10
|
+
|
|
11
|
+
The above copyright notice and this permission notice shall be
|
|
12
|
+
included in all copies or substantial portions of the Software.
|
|
13
|
+
|
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
= BigIndex
|
|
2
|
+
|
|
3
|
+
A Rails plugin that drops into models and provides indexing functionality. Uses an adapter/repository pattern inspired by Datamapper to abstract the actual indexer used in the background, and exposes the model to a simple indexing API.
|
|
4
|
+
|
|
5
|
+
This should be used in conjunction with BigRecord in order to provide a more complete ORM.
|
|
6
|
+
|
|
7
|
+
== Supported search servers
|
|
8
|
+
|
|
9
|
+
* Solr
|
|
10
|
+
* Sphinx (planned)
|
|
11
|
+
|
|
12
|
+
== Installation
|
|
13
|
+
|
|
14
|
+
(1) Download and install Solr. Take a note of the url that solr is running on.
|
|
15
|
+
|
|
16
|
+
(2) In your Rails application, add Bigindex as a gem to your config/environment.rb file:
|
|
17
|
+
|
|
18
|
+
config.gem "bigindex", :source => "http://gemcutter.org"
|
|
19
|
+
|
|
20
|
+
and run the following rake task to install all the gems listed for your Rails app:
|
|
21
|
+
|
|
22
|
+
[sudo] rake gems:install
|
|
23
|
+
|
|
24
|
+
(3) Bootstrap Bigindex into your Rails application:
|
|
25
|
+
|
|
26
|
+
script/generate bigindex
|
|
27
|
+
|
|
28
|
+
(4) Modify the config file config/bigindex.yml[.sample] to correspond to your Solr server.
|
|
29
|
+
|
|
30
|
+
== Getting Started
|
|
31
|
+
|
|
32
|
+
Modify your Ruby class/model similarly to the following:
|
|
33
|
+
|
|
34
|
+
class Model < BigRecord::Base
|
|
35
|
+
include BigIndex::Resource # 1. Include the BigIndex::Resource module into your model.
|
|
36
|
+
|
|
37
|
+
column :name, :string
|
|
38
|
+
column :description, :text
|
|
39
|
+
|
|
40
|
+
index :name, :string # 2. Define each attribute you want to index along with its type.
|
|
41
|
+
index :description # Defaults to type :text
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
BigIndex will then override the default Model.find() method to pass through the indexer first. Model.find() will also accept the option {:bypass_index => true}, which bypasses the indexed #find method and dispatches it to the original Model.find() method, e.g. Model.find(:all, :bypass_index => true). Alternatively, you can use Model.find_without_index(:all) for the same functionality.
|
|
45
|
+
|
|
46
|
+
== License
|
|
47
|
+
|
|
48
|
+
Bigindex is released under the MIT license.
|
|
49
|
+
|
|
50
|
+
== Contributions
|
|
51
|
+
|
|
52
|
+
Bigindex was derived from the work of Data Mapper and parts of acts_as_solr.
|
|
53
|
+
|
|
54
|
+
== Links
|
|
55
|
+
|
|
56
|
+
* Contact Us
|
|
57
|
+
* Website - http://www.bigrecord.org
|
|
58
|
+
* IRC Channel - <tt>#bigrecord</tt> on irc.freenode.net
|
data/Rakefile
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
require 'rubygems'
|
|
2
|
+
require 'rake'
|
|
3
|
+
require 'rake/rdoctask'
|
|
4
|
+
require 'rake/gempackagetask'
|
|
5
|
+
require 'pathname'
|
|
6
|
+
require 'spec/rake/spectask'
|
|
7
|
+
|
|
8
|
+
DATA_STORES = ["bigrecord", "activerecord"]
|
|
9
|
+
|
|
10
|
+
ROOT = Pathname(__FILE__).dirname.expand_path
|
|
11
|
+
|
|
12
|
+
require ROOT + 'tasks/gem'
|
|
13
|
+
require ROOT + 'tasks/rdoc'
|
|
14
|
+
require ROOT + 'tasks/spec'
|
data/VERSION
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
0.1.0
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# This generator bootstraps a Rails project for use with Bigindex
|
|
2
|
+
class BigindexGenerator < Rails::Generator::Base
|
|
3
|
+
|
|
4
|
+
def initialize(runtime_args, runtime_options = {})
|
|
5
|
+
require File.join(File.dirname(__FILE__), "..", "..", "install.rb")
|
|
6
|
+
Dir.mkdir('lib/tasks') unless File.directory?('lib/tasks')
|
|
7
|
+
super
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def manifest
|
|
11
|
+
record do |m|
|
|
12
|
+
m.directory 'lib/tasks'
|
|
13
|
+
m.file 'bigindex.rake', 'lib/tasks/bigindex.rake'
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
end
|
data/init.rb
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
require 'big_index'
|
|
2
|
+
|
|
3
|
+
def config_file
|
|
4
|
+
"#{RAILS_ROOT}/config/bigindex.yml"
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def full_config
|
|
8
|
+
begin
|
|
9
|
+
YAML::load(File.open(config_file))
|
|
10
|
+
rescue
|
|
11
|
+
puts "Missing environment '#{RAILS_ENV}' in config file #{config_file}"
|
|
12
|
+
return {}
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def get_config_for_environment
|
|
17
|
+
if hash = full_config[RAILS_ENV]
|
|
18
|
+
BigIndex.symbolize_keys(hash)
|
|
19
|
+
elsif hash = full_config[RAILS_ENV.to_sym]
|
|
20
|
+
hash
|
|
21
|
+
else
|
|
22
|
+
{}
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
BigIndex.setup(:default, get_config_for_environment) unless get_config_for_environment.empty?
|
data/install.rb
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
require 'fileutils'
|
|
2
|
+
|
|
3
|
+
puts "[Bigindex] Copying example config file to your RAILS_ROOT...\n"
|
|
4
|
+
|
|
5
|
+
config_dir = File.join(RAILS_ROOT, "config")
|
|
6
|
+
source = File.join(File.dirname(__FILE__), "examples", "bigindex.yml")
|
|
7
|
+
target = File.join(config_dir, "bigindex.yml")
|
|
8
|
+
alternate_target = File.join(config_dir, "bigindex.yml.sample")
|
|
9
|
+
|
|
10
|
+
if !File.exist?(target)
|
|
11
|
+
FileUtils.cp(source, target)
|
|
12
|
+
else
|
|
13
|
+
puts "[Bigindex] RAILS_ROOT/config/bigindex.yml file already exists. Copying it as bigindex.yml.sample for reference."
|
|
14
|
+
FileUtils.cp(source, alternate_target)
|
|
15
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
module BigIndex
|
|
2
|
+
module Adapters
|
|
3
|
+
|
|
4
|
+
class AbstractAdapter
|
|
5
|
+
|
|
6
|
+
attr_reader :name, :options, :connection
|
|
7
|
+
|
|
8
|
+
def adapter_name
|
|
9
|
+
'abstract'
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def default_type_field
|
|
13
|
+
raise NotImplementedError
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def default_primary_key_field
|
|
17
|
+
raise NotImplementedError
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def process_index_batch(items, loop, options={})
|
|
21
|
+
raise NotImplementedError
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def drop_index(model)
|
|
25
|
+
raise NotImplementedError
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def get_field_type(field_type)
|
|
29
|
+
field_type
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def execute(request)
|
|
33
|
+
raise NotImplementedError
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def index_save(model)
|
|
37
|
+
raise NotImplementedError
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def index_destroy(model)
|
|
41
|
+
raise NotImplementedError
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def find_by_index(model, query, options={})
|
|
45
|
+
raise NotImplementedError
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def find_values_by_index(model, query, options={})
|
|
49
|
+
raise NotImplementedError
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def find_ids_by_index(model, query, options={})
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def optimize_index
|
|
57
|
+
raise NotImplementedError
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
private
|
|
61
|
+
|
|
62
|
+
def initialize(name, options)
|
|
63
|
+
@name = name
|
|
64
|
+
@options = options
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
end # class AbstractAdapter
|
|
68
|
+
|
|
69
|
+
end # module Adapters
|
|
70
|
+
end # module BigIndex
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
module BigIndex
|
|
2
|
+
module Adapters
|
|
3
|
+
|
|
4
|
+
class SolrAdapter < AbstractAdapter
|
|
5
|
+
|
|
6
|
+
include ::Solr::AdapterMethods
|
|
7
|
+
|
|
8
|
+
# BigIndex Adapter API methods ====================================
|
|
9
|
+
|
|
10
|
+
def adapter_name
|
|
11
|
+
'solr'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def default_type_field
|
|
15
|
+
"type_s_mv"
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def default_primary_key_field
|
|
19
|
+
"pk_s"
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def process_index_batch(items, loop, options = {})
|
|
23
|
+
unless items.empty?
|
|
24
|
+
# This checks that if the item has a method indexable? defined, then it will determine
|
|
25
|
+
# whether or not to index the item based on that method's returned boolean value.
|
|
26
|
+
items_to_index = items.select { |item| item.respond_to?(:indexable?) ? item.indexable? : true }
|
|
27
|
+
|
|
28
|
+
unless items_to_index.empty?
|
|
29
|
+
docs = items_to_index.collect{|content| to_solr_doc(content)}
|
|
30
|
+
if options[:only_generate]
|
|
31
|
+
# Collect the documents. This is to be used within a mapred job.
|
|
32
|
+
docs.each do |doc|
|
|
33
|
+
key = doc['id']
|
|
34
|
+
|
|
35
|
+
# Cannot have \n and \t in the value since they are
|
|
36
|
+
# document and field separators respectively
|
|
37
|
+
value = doc.to_xml.to_s
|
|
38
|
+
value = value.gsub("\n", "__ENDLINE__")
|
|
39
|
+
value = value.gsub("\t", "__TAB__")
|
|
40
|
+
|
|
41
|
+
puts "#{key}\t#{value}"
|
|
42
|
+
end
|
|
43
|
+
else
|
|
44
|
+
solr_add(docs)
|
|
45
|
+
solr_commit if options[:commit]
|
|
46
|
+
end
|
|
47
|
+
else
|
|
48
|
+
break
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def drop_index(model)
|
|
54
|
+
@connection.logger = model.logger if model.respond_to?(:logger)
|
|
55
|
+
result = @connection.solr_execute(Solr::Request::Delete.new(:query => "type_s_mv:\"#{model.name}\""))
|
|
56
|
+
|
|
57
|
+
result.status_message == "0"
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def get_field_type(field_type)
|
|
61
|
+
if field_type.is_a?(Symbol)
|
|
62
|
+
case field_type
|
|
63
|
+
when :float then return "f"
|
|
64
|
+
when :integer then return "i"
|
|
65
|
+
when :boolean then return "b"
|
|
66
|
+
when :string then return "s"
|
|
67
|
+
when :date then return "d"
|
|
68
|
+
when :range_float then return "rf"
|
|
69
|
+
when :range_integer then return "ri"
|
|
70
|
+
when :ngrams then return "ngrams"
|
|
71
|
+
when :autocomplete then return "auto"
|
|
72
|
+
when :lowercase then return "lc"
|
|
73
|
+
when :exact_match then return "em"
|
|
74
|
+
when :geo then return "geo"
|
|
75
|
+
when :text then return "t"
|
|
76
|
+
when :text_not_stored then return "t_ns"
|
|
77
|
+
when :text_not_indexed then return "t_ni"
|
|
78
|
+
when :integer_array then return "i_mv"
|
|
79
|
+
when :integer_array_not_stored then return "i_mv_ns"
|
|
80
|
+
when :text_array then return "t_mv"
|
|
81
|
+
when :text_array_not_stored then return "t_mv_ns"
|
|
82
|
+
when :float_array then return "f_mv"
|
|
83
|
+
when :boolean_array then return "b_mv"
|
|
84
|
+
when :date_array then return "d_mv"
|
|
85
|
+
when :string_array then return "s_mv"
|
|
86
|
+
when :range_integer_array then return "ri_mv"
|
|
87
|
+
when :range_float_array then return "rf_mv"
|
|
88
|
+
when :ngrams_array then return "ngrams_mv"
|
|
89
|
+
when :autocomplete_array then return "auto_mv"
|
|
90
|
+
when :lowercase_array then return "lc_mv"
|
|
91
|
+
when :exact_match_array then return "em_mv"
|
|
92
|
+
else
|
|
93
|
+
raise "Unknown field_type symbol: #{field_type}"
|
|
94
|
+
end
|
|
95
|
+
elsif field_type.is_a?(String)
|
|
96
|
+
return field_type
|
|
97
|
+
else
|
|
98
|
+
raise "Unknown field_type class: #{field_type.class}: #{field_type}"
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def execute(request)
|
|
103
|
+
@connection.solr_execute(request)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def index_save(model)
|
|
107
|
+
configuration = model.index_configuration
|
|
108
|
+
|
|
109
|
+
results = []
|
|
110
|
+
if configuration[:if] && evaluate_condition(configuration[:if], model)
|
|
111
|
+
results << solr_add(to_solr_doc(model))
|
|
112
|
+
results << solr_commit if configuration[:auto_commit]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
!results.map{|result| result.status_code == "0"}.include?(false)
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
def index_destroy(model)
|
|
119
|
+
configuration = model.index_configuration
|
|
120
|
+
|
|
121
|
+
results = []
|
|
122
|
+
|
|
123
|
+
results << solr_delete(model.index_id)
|
|
124
|
+
results << solr_delete(":#{model.record_id}")
|
|
125
|
+
results << solr_commit if configuration[:auto_commit]
|
|
126
|
+
|
|
127
|
+
!results.map{|result| result.status_code == "0"}.include?(false)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def find_by_index(model, query, options={})
|
|
131
|
+
raw_result = options.delete(:raw_result)
|
|
132
|
+
data = parse_query(model, query, options)
|
|
133
|
+
|
|
134
|
+
if data
|
|
135
|
+
parsed = parse_results(model, data, options)
|
|
136
|
+
|
|
137
|
+
return raw_result ? parsed : parsed.results
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def find_values_by_index(model, query, options={})
|
|
142
|
+
raw_result = options.delete(:raw_result)
|
|
143
|
+
data = parse_query(model, query, options)
|
|
144
|
+
|
|
145
|
+
if data
|
|
146
|
+
parsed = parse_results(model, data, {:format => :values})
|
|
147
|
+
|
|
148
|
+
return raw_result ? parsed : parsed.results
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def find_ids_by_index(model, query, options={})
|
|
153
|
+
raw_result = options.delete(:raw_result)
|
|
154
|
+
data = parse_query(model, query, options)
|
|
155
|
+
|
|
156
|
+
if data
|
|
157
|
+
parsed = parse_results(model, data, {:format => :ids})
|
|
158
|
+
|
|
159
|
+
return raw_result ? parsed : parsed.results
|
|
160
|
+
end
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
def optimize_index
|
|
164
|
+
solr_optimize
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
# End of BigIndex Adapter API ====================================
|
|
168
|
+
|
|
169
|
+
private
|
|
170
|
+
|
|
171
|
+
def initialize(name, options)
|
|
172
|
+
@connection = Solr::Base.new(options)
|
|
173
|
+
|
|
174
|
+
super(name, options)
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
end # class SolrAdapter
|
|
178
|
+
|
|
179
|
+
end # module Adapters
|
|
180
|
+
end # module BigIndex
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
require File.join(File.dirname(__FILE__), 'support')
|
|
2
|
+
|
|
3
|
+
module BigIndex
|
|
4
|
+
|
|
5
|
+
class IndexField
|
|
6
|
+
include Assertions
|
|
7
|
+
|
|
8
|
+
attr_reader :field, :field_name, :field_type, :options, :block
|
|
9
|
+
|
|
10
|
+
def initialize(params, block = nil)
|
|
11
|
+
raise "IndexField requires at least a field name" unless params.size > 0
|
|
12
|
+
|
|
13
|
+
@params = params.dup
|
|
14
|
+
@block = block
|
|
15
|
+
|
|
16
|
+
@field_name = params.shift
|
|
17
|
+
assert_kind_of 'field_name', @field_name, Symbol, String
|
|
18
|
+
|
|
19
|
+
unless params.empty? || ![Symbol, String].include?(params.first.class)
|
|
20
|
+
@field_type = params.shift
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
@options = params.shift || {}
|
|
24
|
+
assert_kind_of 'options', @options, Hash
|
|
25
|
+
|
|
26
|
+
# Setting the default values
|
|
27
|
+
@options[:finder_name] ||= field_name
|
|
28
|
+
@field_type ||= :text
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def [](name)
|
|
32
|
+
@options[name]
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def method_missing(name)
|
|
36
|
+
@options[name.to_sym] || super
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end # class IndexField
|
|
40
|
+
|
|
41
|
+
end # module BigIndex
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
module BigIndex
|
|
2
|
+
class Repository
|
|
3
|
+
include Assertions
|
|
4
|
+
|
|
5
|
+
@adapters = {}
|
|
6
|
+
@default_name = :default
|
|
7
|
+
|
|
8
|
+
##
|
|
9
|
+
#
|
|
10
|
+
# @return <Adapter> the adapters registered for this repository
|
|
11
|
+
def self.adapters
|
|
12
|
+
@adapters
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.context
|
|
16
|
+
Thread.current[:bigindex_repository_contexts] ||= []
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def self.default_name
|
|
20
|
+
@default_name ||= :default
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def self.default_name=(name)
|
|
24
|
+
@default_name = name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# TODO: Make sure this isn't dangerous
|
|
28
|
+
def self.clear_adapters
|
|
29
|
+
@adapters = {}
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
attr_reader :name
|
|
33
|
+
|
|
34
|
+
def adapter
|
|
35
|
+
# Make adapter instantiation lazy so we can defer repository setup until it's actually
|
|
36
|
+
# needed. Do not remove this code.
|
|
37
|
+
@adapter ||= begin
|
|
38
|
+
raise ArgumentError, "Adapter not set: #{@name}. Did you forget to setup?" \
|
|
39
|
+
unless self.class.adapters.has_key?(@name)
|
|
40
|
+
|
|
41
|
+
self.class.adapters[@name]
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# TODO: spec this
|
|
46
|
+
def scope
|
|
47
|
+
Repository.context << self
|
|
48
|
+
|
|
49
|
+
begin
|
|
50
|
+
return yield(self)
|
|
51
|
+
ensure
|
|
52
|
+
Repository.context.pop
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def eql?(other)
|
|
57
|
+
return true if super
|
|
58
|
+
name == other.name
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
alias == eql?
|
|
62
|
+
|
|
63
|
+
def to_s
|
|
64
|
+
"#<BigIndex::Repository:#{@name}>"
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
def initialize(name)
|
|
71
|
+
assert_kind_of 'name', name, Symbol
|
|
72
|
+
|
|
73
|
+
@name = name
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
end # class Repository
|
|
77
|
+
end # module BigIndex
|