sunspot 0.9.7
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/History.txt +83 -0
- data/LICENSE +18 -0
- data/README.rdoc +154 -0
- data/Rakefile +9 -0
- data/TODO +9 -0
- data/VERSION.yml +4 -0
- data/bin/sunspot-configure-solr +46 -0
- data/bin/sunspot-solr +62 -0
- data/lib/light_config.rb +40 -0
- data/lib/sunspot.rb +469 -0
- data/lib/sunspot/adapters.rb +265 -0
- data/lib/sunspot/composite_setup.rb +186 -0
- data/lib/sunspot/configuration.rb +38 -0
- data/lib/sunspot/data_extractor.rb +47 -0
- data/lib/sunspot/dsl.rb +3 -0
- data/lib/sunspot/dsl/field_query.rb +72 -0
- data/lib/sunspot/dsl/fields.rb +86 -0
- data/lib/sunspot/dsl/query.rb +59 -0
- data/lib/sunspot/dsl/query_facet.rb +31 -0
- data/lib/sunspot/dsl/restriction.rb +25 -0
- data/lib/sunspot/dsl/scope.rb +193 -0
- data/lib/sunspot/dsl/search.rb +30 -0
- data/lib/sunspot/facet.rb +16 -0
- data/lib/sunspot/facet_data.rb +120 -0
- data/lib/sunspot/facet_row.rb +10 -0
- data/lib/sunspot/field.rb +157 -0
- data/lib/sunspot/field_factory.rb +126 -0
- data/lib/sunspot/indexer.rb +123 -0
- data/lib/sunspot/instantiated_facet.rb +42 -0
- data/lib/sunspot/instantiated_facet_row.rb +22 -0
- data/lib/sunspot/query.rb +191 -0
- data/lib/sunspot/query/base_query.rb +90 -0
- data/lib/sunspot/query/connective.rb +126 -0
- data/lib/sunspot/query/dynamic_query.rb +69 -0
- data/lib/sunspot/query/field_facet.rb +151 -0
- data/lib/sunspot/query/field_query.rb +63 -0
- data/lib/sunspot/query/pagination.rb +39 -0
- data/lib/sunspot/query/query_facet.rb +73 -0
- data/lib/sunspot/query/query_facet_row.rb +19 -0
- data/lib/sunspot/query/query_field_facet.rb +13 -0
- data/lib/sunspot/query/restriction.rb +233 -0
- data/lib/sunspot/query/scope.rb +165 -0
- data/lib/sunspot/query/sort.rb +36 -0
- data/lib/sunspot/query/sort_composite.rb +33 -0
- data/lib/sunspot/schema.rb +165 -0
- data/lib/sunspot/search.rb +219 -0
- data/lib/sunspot/search/hit.rb +66 -0
- data/lib/sunspot/session.rb +201 -0
- data/lib/sunspot/setup.rb +271 -0
- data/lib/sunspot/type.rb +200 -0
- data/lib/sunspot/util.rb +164 -0
- data/solr/etc/jetty.xml +212 -0
- data/solr/etc/webdefault.xml +379 -0
- data/solr/lib/jetty-6.1.3.jar +0 -0
- data/solr/lib/jetty-util-6.1.3.jar +0 -0
- data/solr/lib/jsp-2.1/ant-1.6.5.jar +0 -0
- data/solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-2.1.jar +0 -0
- data/solr/lib/jsp-2.1/jsp-api-2.1.jar +0 -0
- data/solr/lib/servlet-api-2.5-6.1.3.jar +0 -0
- data/solr/solr/conf/elevate.xml +36 -0
- data/solr/solr/conf/protwords.txt +21 -0
- data/solr/solr/conf/schema.xml +50 -0
- data/solr/solr/conf/solrconfig.xml +696 -0
- data/solr/solr/conf/stopwords.txt +57 -0
- data/solr/solr/conf/synonyms.txt +31 -0
- data/solr/start.jar +0 -0
- data/solr/webapps/solr.war +0 -0
- data/spec/api/adapters_spec.rb +33 -0
- data/spec/api/build_search_spec.rb +1039 -0
- data/spec/api/indexer_spec.rb +311 -0
- data/spec/api/query_spec.rb +153 -0
- data/spec/api/search_retrieval_spec.rb +362 -0
- data/spec/api/session_spec.rb +157 -0
- data/spec/api/spec_helper.rb +1 -0
- data/spec/api/sunspot_spec.rb +18 -0
- data/spec/integration/dynamic_fields_spec.rb +55 -0
- data/spec/integration/faceting_spec.rb +169 -0
- data/spec/integration/keyword_search_spec.rb +83 -0
- data/spec/integration/scoped_search_spec.rb +289 -0
- data/spec/integration/spec_helper.rb +1 -0
- data/spec/integration/stored_fields_spec.rb +10 -0
- data/spec/integration/test_pagination.rb +32 -0
- data/spec/mocks/adapters.rb +32 -0
- data/spec/mocks/blog.rb +3 -0
- data/spec/mocks/comment.rb +19 -0
- data/spec/mocks/connection.rb +84 -0
- data/spec/mocks/mock_adapter.rb +30 -0
- data/spec/mocks/mock_record.rb +48 -0
- data/spec/mocks/photo.rb +8 -0
- data/spec/mocks/post.rb +73 -0
- data/spec/mocks/user.rb +8 -0
- data/spec/spec_helper.rb +47 -0
- data/tasks/gemspec.rake +25 -0
- data/tasks/rcov.rake +28 -0
- data/tasks/rdoc.rake +22 -0
- data/tasks/schema.rake +19 -0
- data/tasks/spec.rake +24 -0
- data/tasks/todo.rake +4 -0
- data/templates/schema.xml.haml +24 -0
- metadata +246 -0
@@ -0,0 +1,66 @@
|
|
1
|
+
module Sunspot
|
2
|
+
class Search
|
3
|
+
class Hit
|
4
|
+
SPECIAL_KEYS = Set.new(%w(id type score)) #:nodoc:
|
5
|
+
|
6
|
+
#
|
7
|
+
# Primary key of object associated with this hit, as string.
|
8
|
+
#
|
9
|
+
attr_reader :primary_key
|
10
|
+
#
|
11
|
+
# Class name of object associated with this hit, as string.
|
12
|
+
#
|
13
|
+
attr_reader :class_name
|
14
|
+
#
|
15
|
+
# Keyword relevance score associated with this result. Nil if this hit
|
16
|
+
# is not from a keyword search.
|
17
|
+
#
|
18
|
+
attr_reader :score
|
19
|
+
|
20
|
+
attr_writer :instance #:nodoc:
|
21
|
+
|
22
|
+
def initialize(raw_hit, search) #:nodoc:
|
23
|
+
@class_name, @primary_key = *raw_hit['id'].match(/([^ ]+) (.+)/)[1..2]
|
24
|
+
@score = raw_hit['score']
|
25
|
+
@search = search
|
26
|
+
@stored_values = raw_hit
|
27
|
+
@stored_cache = {}
|
28
|
+
end
|
29
|
+
|
30
|
+
#
|
31
|
+
# Retrieve stored field value. For any attribute field configured with
|
32
|
+
# :stored => true, the Hit object will contain the stored value for
|
33
|
+
# that field. The value of this field will be typecast according to the
|
34
|
+
# type of the field.
|
35
|
+
#
|
36
|
+
# ==== Parameters
|
37
|
+
#
|
38
|
+
# field_name<Symbol>::
|
39
|
+
# The name of the field for which to retrieve the stored value.
|
40
|
+
#
|
41
|
+
def stored(field_name)
|
42
|
+
@stored_cache[field_name.to_sym] ||=
|
43
|
+
begin
|
44
|
+
field = Sunspot::Setup.for(@class_name).field(field_name)
|
45
|
+
field.cast(@stored_values[field.indexed_name])
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
#
|
50
|
+
# Retrieve the instance associated with this hit. This is lazy-loaded, but
|
51
|
+
# the first time it is called on any hit, all the hits for the search will
|
52
|
+
# load their instances using the adapter's #load_all method.
|
53
|
+
#
|
54
|
+
def instance
|
55
|
+
if @instance.nil?
|
56
|
+
@search.populate_hits!
|
57
|
+
end
|
58
|
+
@instance
|
59
|
+
end
|
60
|
+
|
61
|
+
def inspect
|
62
|
+
"#<Sunspot::Search::Hit:#{@class_name} #{@primary_key}>"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,201 @@
|
|
1
|
+
module Sunspot
|
2
|
+
#
|
3
|
+
# A Sunspot session encapsulates a connection to Solr and a set of
|
4
|
+
# configuration choices. Though users of Sunspot may manually instantiate
|
5
|
+
# Session objects, in the general case it's easier to use the singleton
|
6
|
+
# stored in the Sunspot module. Since the Sunspot module provides all of
|
7
|
+
# the instance methods of Session as class methods, they are not documented
|
8
|
+
# again here.
|
9
|
+
#
|
10
|
+
class Session
|
11
|
+
class <<self
|
12
|
+
attr_writer :connection_class #:nodoc:
|
13
|
+
|
14
|
+
#
|
15
|
+
# For testing purposes
|
16
|
+
#
|
17
|
+
def connection_class #:nodoc:
|
18
|
+
@connection_class ||= RSolr::Connection
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
#
|
23
|
+
# Sunspot::Configuration object for this session
|
24
|
+
#
|
25
|
+
attr_reader :config
|
26
|
+
|
27
|
+
#
|
28
|
+
# Sessions are initialized with a Sunspot configuration and a Solr
|
29
|
+
# connection. Usually you will want to stick with the default arguments
|
30
|
+
# when instantiating your own sessions.
|
31
|
+
#
|
32
|
+
def initialize(config = Configuration.build, connection = nil)
|
33
|
+
@config = config
|
34
|
+
yield(@config) if block_given?
|
35
|
+
@connection = connection
|
36
|
+
@updates = 0
|
37
|
+
end
|
38
|
+
|
39
|
+
#
|
40
|
+
# See Sunspot.new_search
|
41
|
+
#
|
42
|
+
def new_search(*types)
|
43
|
+
types.flatten!
|
44
|
+
setup =
|
45
|
+
if types.length == 1
|
46
|
+
Setup.for(types.first)
|
47
|
+
else
|
48
|
+
CompositeSetup.for(types)
|
49
|
+
end
|
50
|
+
Search.new(connection, setup, Query::Query.new(types, setup, @config))
|
51
|
+
end
|
52
|
+
|
53
|
+
#
|
54
|
+
# See Sunspot.search
|
55
|
+
#
|
56
|
+
def search(*types, &block)
|
57
|
+
options = types.last.is_a?(Hash) ? types.pop : {}
|
58
|
+
search = new_search(*types)
|
59
|
+
search.build(&block) if block
|
60
|
+
search.query.options = options
|
61
|
+
search.execute!
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# See Sunspot.index
|
66
|
+
#
|
67
|
+
def index(*objects)
|
68
|
+
objects.flatten!
|
69
|
+
@updates += objects.length
|
70
|
+
indexer.add(objects)
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# See Sunspot.index!
|
75
|
+
#
|
76
|
+
def index!(*objects)
|
77
|
+
index(*objects)
|
78
|
+
commit
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# See Sunspot.commit
|
83
|
+
#
|
84
|
+
def commit
|
85
|
+
@updates = 0
|
86
|
+
connection.commit
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# See Sunspot.remove
|
91
|
+
#
|
92
|
+
def remove(*objects)
|
93
|
+
objects.flatten!
|
94
|
+
@updates += objects.length
|
95
|
+
for object in objects
|
96
|
+
indexer.remove(object)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# See Sunspot.remove!
|
102
|
+
#
|
103
|
+
def remove!(*objects)
|
104
|
+
remove(*objects)
|
105
|
+
commit
|
106
|
+
end
|
107
|
+
|
108
|
+
#
|
109
|
+
# See Sunspot.remove_by_id
|
110
|
+
#
|
111
|
+
def remove_by_id(clazz, id)
|
112
|
+
class_name =
|
113
|
+
if clazz.is_a?(Class)
|
114
|
+
clazz.name
|
115
|
+
else
|
116
|
+
clazz.to_s
|
117
|
+
end
|
118
|
+
indexer.remove_by_id(class_name, id)
|
119
|
+
end
|
120
|
+
|
121
|
+
#
|
122
|
+
# See Sunspot.remove_by_id!
|
123
|
+
#
|
124
|
+
def remove_by_id!(clazz, id)
|
125
|
+
remove_by_id(clazz, id)
|
126
|
+
commit
|
127
|
+
end
|
128
|
+
|
129
|
+
#
|
130
|
+
# See Sunspot.remove_all
|
131
|
+
#
|
132
|
+
def remove_all(*classes)
|
133
|
+
classes.flatten!
|
134
|
+
if classes.empty?
|
135
|
+
@updates += 1
|
136
|
+
Indexer.remove_all(connection)
|
137
|
+
else
|
138
|
+
@updates += classes.length
|
139
|
+
for clazz in classes
|
140
|
+
indexer.remove_all(clazz)
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
144
|
+
|
145
|
+
#
|
146
|
+
# See Sunspot.remove_all!
|
147
|
+
#
|
148
|
+
def remove_all!(*classes)
|
149
|
+
remove_all(*classes)
|
150
|
+
commit
|
151
|
+
end
|
152
|
+
|
153
|
+
#
|
154
|
+
# See Sunspot.dirty?
|
155
|
+
#
|
156
|
+
def dirty?
|
157
|
+
@updates > 0
|
158
|
+
end
|
159
|
+
|
160
|
+
#
|
161
|
+
# See Sunspot.commit_if_dirty
|
162
|
+
#
|
163
|
+
def commit_if_dirty
|
164
|
+
commit if dirty?
|
165
|
+
end
|
166
|
+
|
167
|
+
#
|
168
|
+
# See Sunspot.batch
|
169
|
+
#
|
170
|
+
def batch
|
171
|
+
indexer.start_batch
|
172
|
+
yield
|
173
|
+
indexer.flush_batch
|
174
|
+
end
|
175
|
+
|
176
|
+
private
|
177
|
+
|
178
|
+
#
|
179
|
+
# Retrieve the Solr connection for this session, creating one if it does not
|
180
|
+
# already exist.
|
181
|
+
#
|
182
|
+
# ==== Returns
|
183
|
+
#
|
184
|
+
# Solr::Connection:: The connection for this session
|
185
|
+
#
|
186
|
+
def connection
|
187
|
+
@connection ||=
|
188
|
+
begin
|
189
|
+
connection = self.class.connection_class.new(
|
190
|
+
RSolr::Adapter::HTTP.new(:url => config.solr.url)
|
191
|
+
)
|
192
|
+
connection.adapter.connector.adapter_name = config.http_client
|
193
|
+
connection
|
194
|
+
end
|
195
|
+
end
|
196
|
+
|
197
|
+
def indexer
|
198
|
+
@indexer ||= Indexer.new(connection)
|
199
|
+
end
|
200
|
+
end
|
201
|
+
end
|
@@ -0,0 +1,271 @@
|
|
1
|
+
module Sunspot
|
2
|
+
#
|
3
|
+
# This class encapsulates the search/indexing setup for a given class. Its
|
4
|
+
# contents are built using the Sunspot.setup method.
|
5
|
+
#
|
6
|
+
class Setup #:nodoc:
|
7
|
+
def initialize(clazz)
|
8
|
+
@clazz = clazz
|
9
|
+
@class_name = clazz.name
|
10
|
+
@field_factories, @text_field_factories, @dynamic_field_factories,
|
11
|
+
@field_factories_cache, @text_field_factories_cache,
|
12
|
+
@dynamic_field_factories_cache = *Array.new(6) { Hash.new }
|
13
|
+
@dsl = DSL::Fields.new(self)
|
14
|
+
add_field_factory(:class, Type::ClassType)
|
15
|
+
end
|
16
|
+
|
17
|
+
def type_names
|
18
|
+
[@class_name]
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Add field_factories for scope/ordering
|
23
|
+
#
|
24
|
+
# ==== Parameters
|
25
|
+
#
|
26
|
+
# field_factories<Array>:: Array of Sunspot::Field objects
|
27
|
+
#
|
28
|
+
def add_field_factory(name, type, options = {}, &block)
|
29
|
+
field_factory = FieldFactory::Static.new(name, type, options, &block)
|
30
|
+
@field_factories[field_factory.signature] = field_factory
|
31
|
+
@field_factories_cache[field_factory.name] = field_factory
|
32
|
+
end
|
33
|
+
|
34
|
+
#
|
35
|
+
# Add field_factories for fulltext search
|
36
|
+
#
|
37
|
+
# ==== Parameters
|
38
|
+
#
|
39
|
+
# field_factories<Array>:: Array of Sunspot::Field objects
|
40
|
+
#
|
41
|
+
def add_text_field_factory(name, options = {}, &block)
|
42
|
+
field_factory = FieldFactory::Static.new(name, Type::TextType, options, &block)
|
43
|
+
@text_field_factories[name] = field_factory
|
44
|
+
@text_field_factories_cache[field_factory.name] = field_factory
|
45
|
+
end
|
46
|
+
|
47
|
+
#
|
48
|
+
# Add dynamic field_factories
|
49
|
+
#
|
50
|
+
# ==== Parameters
|
51
|
+
#
|
52
|
+
# field_factories<Array>:: Array of dynamic field objects
|
53
|
+
#
|
54
|
+
def add_dynamic_field_factory(name, type, options = {}, &block)
|
55
|
+
field_factory = FieldFactory::Dynamic.new(name, type, options, &block)
|
56
|
+
@dynamic_field_factories[field_factory.signature] = field_factory
|
57
|
+
@dynamic_field_factories_cache[field_factory.name] = field_factory
|
58
|
+
end
|
59
|
+
|
60
|
+
def add_document_boost(attr_name, &block)
|
61
|
+
@document_boost_extractor =
|
62
|
+
if attr_name
|
63
|
+
if attr_name.respond_to?(:to_f)
|
64
|
+
DataExtractor::Constant.new(attr_name)
|
65
|
+
else
|
66
|
+
DataExtractor::AttributeExtractor.new(attr_name)
|
67
|
+
end
|
68
|
+
else
|
69
|
+
DataExtractor::BlockExtractor.new(&block)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
#
|
74
|
+
# Builder method for evaluating the setup DSL
|
75
|
+
#
|
76
|
+
def setup(&block)
|
77
|
+
@dsl.instance_eval(&block)
|
78
|
+
end
|
79
|
+
|
80
|
+
def field(field_name)
|
81
|
+
if field_factory = @field_factories_cache[field_name.to_sym]
|
82
|
+
field_factory.build
|
83
|
+
else
|
84
|
+
raise(
|
85
|
+
UnrecognizedFieldError,
|
86
|
+
"No field configured for #{@clazz.name} with name '#{field_name}'"
|
87
|
+
)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def text_field(field_name)
|
92
|
+
if field_factory = @text_field_factories_cache[field_name.to_sym]
|
93
|
+
field_factory.build
|
94
|
+
else
|
95
|
+
raise(
|
96
|
+
UnrecognizedFieldError,
|
97
|
+
"No text field configured for #{@clazz.name} with name '#{field_name}'"
|
98
|
+
)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def dynamic_field_factory(field_name)
|
103
|
+
@dynamic_field_factories_cache[field_name.to_sym] || raise(
|
104
|
+
UnrecognizedFieldError,
|
105
|
+
"No dynamic field configured for #{@clazz.name} with name '#{field_name}'"
|
106
|
+
)
|
107
|
+
end
|
108
|
+
|
109
|
+
def fields
|
110
|
+
field_factories.map { |field_factory| field_factory.build }
|
111
|
+
end
|
112
|
+
|
113
|
+
def text_fields
|
114
|
+
text_field_factories.map { |text_field_factory| text_field_factory.build }
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Get the field_factories associated with this setup as well as all inherited field_factories
|
119
|
+
#
|
120
|
+
# ==== Returns
|
121
|
+
#
|
122
|
+
# Array:: Collection of all field_factories associated with this setup
|
123
|
+
#
|
124
|
+
def field_factories
|
125
|
+
collection_from_inheritable_hash(:field_factories)
|
126
|
+
end
|
127
|
+
|
128
|
+
#
|
129
|
+
# Get the text field_factories associated with this setup as well as all inherited
|
130
|
+
# text field_factories
|
131
|
+
#
|
132
|
+
# ==== Returns
|
133
|
+
#
|
134
|
+
# Array:: Collection of all text field_factories associated with this setup
|
135
|
+
#
|
136
|
+
def text_field_factories
|
137
|
+
collection_from_inheritable_hash(:text_field_factories)
|
138
|
+
end
|
139
|
+
|
140
|
+
#
|
141
|
+
# Get all static, dynamic, and text field_factories associated with this setup as
|
142
|
+
# well as all inherited field_factories
|
143
|
+
#
|
144
|
+
# ==== Returns
|
145
|
+
#
|
146
|
+
# Array:: Collection of all text and scope field_factories associated with this setup
|
147
|
+
#
|
148
|
+
def all_field_factories
|
149
|
+
all_field_factories = []
|
150
|
+
all_field_factories.concat(field_factories).concat(text_field_factories).concat(dynamic_field_factories)
|
151
|
+
all_field_factories
|
152
|
+
end
|
153
|
+
|
154
|
+
#
|
155
|
+
# Get all dynamic field_factories for this and parent setups
|
156
|
+
#
|
157
|
+
# ==== Returns
|
158
|
+
#
|
159
|
+
# Array:: Dynamic field_factories
|
160
|
+
#
|
161
|
+
def dynamic_field_factories
|
162
|
+
collection_from_inheritable_hash(:dynamic_field_factories)
|
163
|
+
end
|
164
|
+
|
165
|
+
#
|
166
|
+
# Return the class associated with this setup.
|
167
|
+
#
|
168
|
+
# ==== Returns
|
169
|
+
#
|
170
|
+
# clazz<Class>:: Class setup is configured for
|
171
|
+
#
|
172
|
+
def clazz
|
173
|
+
Util.full_const_get(@class_name)
|
174
|
+
end
|
175
|
+
|
176
|
+
def document_boost_for(model)
|
177
|
+
if @document_boost_extractor
|
178
|
+
@document_boost_extractor.value_for(model)
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
protected
|
183
|
+
|
184
|
+
#
|
185
|
+
# Get the nearest inherited setup, if any
|
186
|
+
#
|
187
|
+
# ==== Returns
|
188
|
+
#
|
189
|
+
# Sunspot::Setup:: Setup for the nearest ancestor of this setup's class
|
190
|
+
#
|
191
|
+
def parent
|
192
|
+
Setup.for(clazz.superclass)
|
193
|
+
end
|
194
|
+
|
195
|
+
def get_inheritable_hash(name)
|
196
|
+
hash = instance_variable_get(:"@#{name}")
|
197
|
+
parent.get_inheritable_hash(name).each_pair do |key, value|
|
198
|
+
hash[key] = value unless hash.has_key?(key)
|
199
|
+
end if parent
|
200
|
+
hash
|
201
|
+
end
|
202
|
+
|
203
|
+
private
|
204
|
+
|
205
|
+
def collection_from_inheritable_hash(name)
|
206
|
+
get_inheritable_hash(name).values
|
207
|
+
end
|
208
|
+
|
209
|
+
class <<self
|
210
|
+
#
|
211
|
+
# Retrieve or create the Setup instance for the given class, evaluating
|
212
|
+
# the given block to add to the setup's configuration
|
213
|
+
#
|
214
|
+
def setup(clazz, &block) #:nodoc:
|
215
|
+
self.for!(clazz).setup(&block)
|
216
|
+
end
|
217
|
+
|
218
|
+
#
|
219
|
+
# Retrieve the setup instance for the given class, or for the nearest
|
220
|
+
# ancestor that has a setup, if any.
|
221
|
+
#
|
222
|
+
# ==== Parameters
|
223
|
+
#
|
224
|
+
# clazz<Class>:: Class for which to retrieve a setup
|
225
|
+
#
|
226
|
+
# ==== Returns
|
227
|
+
#
|
228
|
+
# Sunspot::Setup::
|
229
|
+
# Setup instance associated with the given class or its nearest ancestor
|
230
|
+
#
|
231
|
+
def for(clazz) #:nodoc:
|
232
|
+
class_name =
|
233
|
+
if clazz.respond_to?(:name)
|
234
|
+
clazz.name
|
235
|
+
else
|
236
|
+
clazz
|
237
|
+
end
|
238
|
+
setups[class_name.to_sym] || self.for(clazz.superclass) if clazz
|
239
|
+
end
|
240
|
+
|
241
|
+
protected
|
242
|
+
|
243
|
+
#
|
244
|
+
# Retrieve or create a Setup instance for this class
|
245
|
+
#
|
246
|
+
# ==== Parameters
|
247
|
+
#
|
248
|
+
# clazz<Class>:: Class for which to retrieve a setup
|
249
|
+
#
|
250
|
+
# ==== Returns
|
251
|
+
#
|
252
|
+
# Sunspot::Setup:: New or existing setup for this class
|
253
|
+
#
|
254
|
+
def for!(clazz) #:nodoc:
|
255
|
+
setups[clazz.name.to_sym] ||= new(clazz)
|
256
|
+
end
|
257
|
+
|
258
|
+
private
|
259
|
+
|
260
|
+
# Singleton hash of class names to Setup instances
|
261
|
+
#
|
262
|
+
# ==== Returns
|
263
|
+
#
|
264
|
+
# Hash:: Class names keyed to Setup instances
|
265
|
+
#
|
266
|
+
def setups
|
267
|
+
@setups ||= {}
|
268
|
+
end
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|