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,73 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
#
|
4
|
+
# QueryFacets encapsulate requests for Sunspot's query faceting capability.
|
5
|
+
# They are created by the FieldQuery#add_query_facet method.
|
6
|
+
#
|
7
|
+
#--
|
8
|
+
#
|
9
|
+
# The actual concept of a QueryFacet is somewhat artificial - it provides a
|
10
|
+
# grouping for the facet at the Sunspot level, which provides a nicer and
|
11
|
+
# more consistent API in Sunspot; Solr does not provide any grouping for
|
12
|
+
# query facet rows, instead returning each requested row individually, keyed
|
13
|
+
# by the boolean phrase used in the facet query.
|
14
|
+
#
|
15
|
+
class QueryFacet
|
16
|
+
attr_reader :name #:nodoc:
|
17
|
+
attr_reader :field #:nodoc:
|
18
|
+
|
19
|
+
def initialize(name, setup = nil) #:nodoc:
|
20
|
+
@name = name
|
21
|
+
@setup = setup
|
22
|
+
@components = []
|
23
|
+
end
|
24
|
+
|
25
|
+
#
|
26
|
+
# Add a QueryFacetRow to this facet. The label argument becomes the value
|
27
|
+
# of the Sunspot::QueryFacetRow object corresponding to this query facet
|
28
|
+
# row.
|
29
|
+
#
|
30
|
+
# ==== Parameters
|
31
|
+
#
|
32
|
+
# label<Object>::
|
33
|
+
# An object that will become the value of the result row. Use whatever
|
34
|
+
# type is most intuitive.
|
35
|
+
#
|
36
|
+
# ==== Returns
|
37
|
+
#
|
38
|
+
# QueryFacetRow:: QueryFacetRow object containing scope for this row
|
39
|
+
#
|
40
|
+
def add_row(label)
|
41
|
+
@components << row = QueryFacetRow.new(label, @setup)
|
42
|
+
row
|
43
|
+
end
|
44
|
+
|
45
|
+
#
|
46
|
+
# Express this query facet as Solr parameters
|
47
|
+
#
|
48
|
+
# ==== Returns
|
49
|
+
#
|
50
|
+
# Hash:: Solr params hash
|
51
|
+
#
|
52
|
+
def to_params #:nodoc:
|
53
|
+
components = @components.map { |component| component.to_boolean_phrase }
|
54
|
+
components = components.first if components.length == 1
|
55
|
+
{
|
56
|
+
:facet => 'true',
|
57
|
+
:"facet.query" => components
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
#
|
62
|
+
# Get query facet rows (used when constructing results)
|
63
|
+
#
|
64
|
+
# ==== Returns
|
65
|
+
#
|
66
|
+
# Array:: Array of QueryFacetRow objects.
|
67
|
+
#
|
68
|
+
def rows #:nodoc:
|
69
|
+
@components
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
#
|
4
|
+
# QueryFacetRow objects encapsulate restrictions for a particular
|
5
|
+
# QueryFacet. They also contain a label attribute, which is used as the
|
6
|
+
# value for the search result's corresponding facet row object.
|
7
|
+
#
|
8
|
+
# See Query::Scope for the API provided.
|
9
|
+
#
|
10
|
+
class QueryFacetRow < Connective::Conjunction
|
11
|
+
attr_reader :label #:nodoc:
|
12
|
+
|
13
|
+
def initialize(label, setup) #:nodoc:
|
14
|
+
super(setup)
|
15
|
+
@label = label
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
class QueryFieldFacet < QueryFacet
|
4
|
+
def initialize(field, values)
|
5
|
+
super(field.name)
|
6
|
+
@field = field
|
7
|
+
values.each do |value|
|
8
|
+
add_row(value).add_component(Restriction::EqualTo.new(field, value))
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,233 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
module Restriction #:nodoc:
|
4
|
+
class <<self
|
5
|
+
#
|
6
|
+
# Return the names of all of the restriction classes that should be made
|
7
|
+
# available to the DSL.
|
8
|
+
#
|
9
|
+
# ==== Returns
|
10
|
+
#
|
11
|
+
# Array:: Collection of restriction class names
|
12
|
+
#
|
13
|
+
def names
|
14
|
+
constants - %w(Base SameAs) #XXX this seems ugly
|
15
|
+
end
|
16
|
+
|
17
|
+
def [](restriction_name)
|
18
|
+
@types ||= {}
|
19
|
+
@types[restriction_name.to_sym] ||= const_get(Sunspot::Util.camel_case(restriction_name.to_s))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
#
|
24
|
+
# Subclasses of this class represent restrictions that can be applied to
|
25
|
+
# a Sunspot query. The Sunspot::DSL::Restriction class presents a builder
|
26
|
+
# API for instances of this class.
|
27
|
+
#
|
28
|
+
# Implementations of this class must respond to #to_params and
|
29
|
+
# #to_negated_params. Instead of implementing those methods, they may
|
30
|
+
# choose to implement any of:
|
31
|
+
#
|
32
|
+
# * #to_positive_boolean_phrase, and optionally #to_negated_boolean_phrase
|
33
|
+
# * #to_solr_conditional
|
34
|
+
#
|
35
|
+
class Base #:nodoc:
|
36
|
+
include RSolr::Char
|
37
|
+
|
38
|
+
def initialize(field, value, negated = false)
|
39
|
+
@field, @value, @negated = field, value, negated
|
40
|
+
end
|
41
|
+
|
42
|
+
#
|
43
|
+
# A hash representing this restriction in solr-ruby's parameter format.
|
44
|
+
# All restriction implementations must respond to this method; however,
|
45
|
+
# the base implementation delegates to the #to_positive_boolean_phrase method, so
|
46
|
+
# subclasses may (and probably should) choose to implement that method
|
47
|
+
# instead.
|
48
|
+
#
|
49
|
+
# ==== Returns
|
50
|
+
#
|
51
|
+
# Hash:: Representation of this restriction as solr-ruby parameters
|
52
|
+
#
|
53
|
+
def to_params
|
54
|
+
{ :fq => [to_boolean_phrase] }
|
55
|
+
end
|
56
|
+
|
57
|
+
#
|
58
|
+
# Return the boolean phrase associated with this restriction object.
|
59
|
+
# Differentiates between positive and negated boolean phrases depending
|
60
|
+
# on whether this restriction is negated.
|
61
|
+
#
|
62
|
+
def to_boolean_phrase
|
63
|
+
unless negated?
|
64
|
+
to_positive_boolean_phrase
|
65
|
+
else
|
66
|
+
to_negated_boolean_phrase
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
#
|
71
|
+
# Boolean phrase representing this restriction in the positive. Subclasses
|
72
|
+
# may choose to implement this method rather than #to_params; however,
|
73
|
+
# this method delegates to the abstract #to_solr_conditional method, which
|
74
|
+
# in most cases will be what subclasses will want to implement.
|
75
|
+
# #to_solr_conditional contains the boolean phrase representing the
|
76
|
+
# condition but leaves out the field name (see built-in implementations
|
77
|
+
# for examples)
|
78
|
+
#
|
79
|
+
# ==== Returns
|
80
|
+
#
|
81
|
+
# String:: Boolean phrase for restriction in the positive
|
82
|
+
#
|
83
|
+
def to_positive_boolean_phrase
|
84
|
+
"#{escape(@field.indexed_name)}:#{to_solr_conditional}"
|
85
|
+
end
|
86
|
+
|
87
|
+
#
|
88
|
+
# Boolean phrase representing this restriction in the negated. Subclasses
|
89
|
+
# may choose to implement this method, but it is not necessary, as the
|
90
|
+
# base implementation delegates to #to_positive_boolean_phrase.
|
91
|
+
#
|
92
|
+
# ==== Returns
|
93
|
+
#
|
94
|
+
# String:: Boolean phrase for restriction in the negated
|
95
|
+
#
|
96
|
+
def to_negated_boolean_phrase
|
97
|
+
"-#{to_positive_boolean_phrase}"
|
98
|
+
end
|
99
|
+
|
100
|
+
#
|
101
|
+
# Whether this restriction should be negated from its original meaning
|
102
|
+
#
|
103
|
+
def negated? #:nodoc:
|
104
|
+
!!@negated
|
105
|
+
end
|
106
|
+
|
107
|
+
def negate
|
108
|
+
self.class.new(@field, @value, !@negated)
|
109
|
+
end
|
110
|
+
|
111
|
+
protected
|
112
|
+
|
113
|
+
#
|
114
|
+
# Return escaped Solr API representation of given value
|
115
|
+
#
|
116
|
+
# ==== Parameters
|
117
|
+
#
|
118
|
+
# value<Object>::
|
119
|
+
# value to convert to Solr representation (default: @value)
|
120
|
+
#
|
121
|
+
# ==== Returns
|
122
|
+
#
|
123
|
+
# String:: Solr API representation of given value
|
124
|
+
#
|
125
|
+
def solr_value(value = @value)
|
126
|
+
escape(@field.to_indexed(value))
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
#
|
131
|
+
# Results must have field with value equal to given value. If the value
|
132
|
+
# is nil, results must have no value for the given field.
|
133
|
+
#
|
134
|
+
class EqualTo < Base
|
135
|
+
def to_positive_boolean_phrase
|
136
|
+
unless @value.nil?
|
137
|
+
super
|
138
|
+
else
|
139
|
+
"#{escape(@field.indexed_name)}:[* TO *]"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
def negated?
|
144
|
+
if @value.nil?
|
145
|
+
!super
|
146
|
+
else
|
147
|
+
super
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
private
|
152
|
+
|
153
|
+
def to_solr_conditional
|
154
|
+
"#{solr_value}"
|
155
|
+
end
|
156
|
+
end
|
157
|
+
|
158
|
+
#
|
159
|
+
# Results must have field with value less than given value
|
160
|
+
#
|
161
|
+
class LessThan < Base
|
162
|
+
private
|
163
|
+
|
164
|
+
def to_solr_conditional
|
165
|
+
"[* TO #{solr_value}]"
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
#
|
170
|
+
# Results must have field with value greater than given value
|
171
|
+
#
|
172
|
+
class GreaterThan < Base
|
173
|
+
private
|
174
|
+
|
175
|
+
def to_solr_conditional
|
176
|
+
"[#{solr_value} TO *]"
|
177
|
+
end
|
178
|
+
end
|
179
|
+
|
180
|
+
#
|
181
|
+
# Results must have field with value in given range
|
182
|
+
#
|
183
|
+
class Between < Base
|
184
|
+
private
|
185
|
+
|
186
|
+
def to_solr_conditional
|
187
|
+
"[#{solr_value(@value.first)} TO #{solr_value(@value.last)}]"
|
188
|
+
end
|
189
|
+
end
|
190
|
+
|
191
|
+
#
|
192
|
+
# Results must have field with value included in given collection
|
193
|
+
#
|
194
|
+
class AnyOf < Base
|
195
|
+
private
|
196
|
+
|
197
|
+
def to_solr_conditional
|
198
|
+
"(#{@value.map { |v| solr_value v } * ' OR '})"
|
199
|
+
end
|
200
|
+
end
|
201
|
+
|
202
|
+
#
|
203
|
+
# Results must have field with values matching all values in given
|
204
|
+
# collection (only makes sense for fields with multiple values)
|
205
|
+
#
|
206
|
+
class AllOf < Base
|
207
|
+
private
|
208
|
+
|
209
|
+
def to_solr_conditional
|
210
|
+
"(#{@value.map { |v| solr_value v } * ' AND '})"
|
211
|
+
end
|
212
|
+
end
|
213
|
+
|
214
|
+
#
|
215
|
+
# Result must be the exact instance given (only useful when negated).
|
216
|
+
#
|
217
|
+
class SameAs < Base
|
218
|
+
def initialize(object, negated = false)
|
219
|
+
@object, @negated = object, negated
|
220
|
+
end
|
221
|
+
|
222
|
+
def to_positive_boolean_phrase
|
223
|
+
adapter = Adapters::InstanceAdapter.adapt(@object)
|
224
|
+
"id:#{escape(adapter.index_id)}"
|
225
|
+
end
|
226
|
+
|
227
|
+
def negate
|
228
|
+
SameAs.new(@object, !negated?)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Sunspot
|
2
|
+
module Query
|
3
|
+
#
|
4
|
+
# The Scope class encapsulates a set of restrictions that scope search
|
5
|
+
# results (as well as query facets rows). This class's API is exposed by
|
6
|
+
# Query::Query and Query::QueryFacetRow.
|
7
|
+
#
|
8
|
+
class Scope
|
9
|
+
#
|
10
|
+
# Add a restriction to the query.
|
11
|
+
#
|
12
|
+
# ==== Parameters
|
13
|
+
#
|
14
|
+
# field_name<Symbol>:: Name of the field to which the restriction applies
|
15
|
+
# restriction_type<Class,Symbol>::
|
16
|
+
# Subclass of Sunspot::Query::Restriction::Base, or snake_cased name as symbol
|
17
|
+
# (e.g., +:equal_to+)
|
18
|
+
# value<Object>::
|
19
|
+
# Value against which the restriction applies (e.g. less_than(2) has a
|
20
|
+
# value of 2)
|
21
|
+
# negated::
|
22
|
+
# Whether this restriction should be negated (use add_negated_restriction)
|
23
|
+
#
|
24
|
+
def add_restriction(field_name, restriction_type, value, negated = false)
|
25
|
+
if restriction_type.is_a?(Symbol)
|
26
|
+
restriction_type = Restriction[restriction_type]
|
27
|
+
end
|
28
|
+
add_component(
|
29
|
+
restriction = restriction_type.new(
|
30
|
+
build_field(field_name), value, negated
|
31
|
+
)
|
32
|
+
)
|
33
|
+
restriction
|
34
|
+
end
|
35
|
+
|
36
|
+
#
|
37
|
+
# Add a negated restriction to the query. The restriction will be taken as
|
38
|
+
# the opposite of its usual meaning (e.g., an :equal_to restriction will
|
39
|
+
# be "not equal to".
|
40
|
+
#
|
41
|
+
# ==== Parameters
|
42
|
+
#
|
43
|
+
# field_name<Symbol>:: Name of the field to which the restriction applies
|
44
|
+
# restriction_type<Class>::
|
45
|
+
# Subclass of Sunspot::Query::Restriction::Base to instantiate
|
46
|
+
# value<Object>::
|
47
|
+
# Value against which the restriction applies (e.g. less_than(2) has a
|
48
|
+
# value of 2)
|
49
|
+
#
|
50
|
+
def add_negated_restriction(field_name, restriction_type, value)
|
51
|
+
add_restriction(field_name, restriction_type, value, true)
|
52
|
+
end
|
53
|
+
|
54
|
+
#
|
55
|
+
# Add a disjunction to the scope. The disjunction can then take a set of
|
56
|
+
# restrictions, which are combined with OR semantics.
|
57
|
+
#
|
58
|
+
# ==== Returns
|
59
|
+
#
|
60
|
+
# Connective::Disjunction:: New disjunction
|
61
|
+
#
|
62
|
+
def add_disjunction
|
63
|
+
add_component(disjunction = Connective::Disjunction.new(setup))
|
64
|
+
disjunction
|
65
|
+
end
|
66
|
+
|
67
|
+
#
|
68
|
+
# Add a conjunction to the scope. In most cases, this will simply return
|
69
|
+
# the Scope object itself, since scopes by default combine their
|
70
|
+
# restrictions with OR semantics. The Connective::Disjunction class
|
71
|
+
# overrides this method to return a Connective::Conjunction.
|
72
|
+
#
|
73
|
+
# ==== Returns
|
74
|
+
#
|
75
|
+
# Scope:: Self or another scope with conjunctive semantics.
|
76
|
+
#
|
77
|
+
def add_conjunction
|
78
|
+
self
|
79
|
+
end
|
80
|
+
|
81
|
+
#
|
82
|
+
# Exclude a particular instance from the search results
|
83
|
+
#
|
84
|
+
# ==== Parameters
|
85
|
+
#
|
86
|
+
# instance<Object>:: instance to exclude from results
|
87
|
+
#
|
88
|
+
def exclude_instance(instance)
|
89
|
+
add_component(Restriction::SameAs.new(instance, true))
|
90
|
+
end
|
91
|
+
|
92
|
+
#
|
93
|
+
# Generate a DynamicQuery instance for the given base name.
|
94
|
+
# This gives you access to a subset of the Query API but the operations
|
95
|
+
# apply to dynamic fields inside the dynamic field definition specified
|
96
|
+
# by +base_name+.
|
97
|
+
#
|
98
|
+
# ==== Parameters
|
99
|
+
#
|
100
|
+
# base_name<Symbol>::
|
101
|
+
# Base name of the dynamic field definition to use in the dynamic query
|
102
|
+
# operations
|
103
|
+
#
|
104
|
+
# ==== Returns
|
105
|
+
#
|
106
|
+
# DynamicQuery::
|
107
|
+
# Instance providing dynamic query functionality for the given field
|
108
|
+
# definitions.
|
109
|
+
#
|
110
|
+
def dynamic_query(base_name)
|
111
|
+
DynamicQuery.new(setup.dynamic_field_factory(base_name), self)
|
112
|
+
end
|
113
|
+
|
114
|
+
#
|
115
|
+
# Determine which restriction type to add based on the type of the value.
|
116
|
+
# Used to interpret query conditions passed as a hash, as well as the
|
117
|
+
# short-form DSL::Scope#with method.
|
118
|
+
#
|
119
|
+
# ==== Parameters
|
120
|
+
#
|
121
|
+
# field_name<Symbol>:: Name of the field on which to apply the restriction
|
122
|
+
# value<Object,Array,Range>:: Value to which to apply to the restriction
|
123
|
+
#--
|
124
|
+
# negated<Boolean>:: Whether to negate the restriction.
|
125
|
+
#
|
126
|
+
def add_shorthand_restriction(field_name, value, negated = false) #:nodoc:
|
127
|
+
restriction_type =
|
128
|
+
case value
|
129
|
+
when Range
|
130
|
+
Restriction::Between
|
131
|
+
when Array
|
132
|
+
Restriction::AnyOf
|
133
|
+
else
|
134
|
+
Restriction::EqualTo
|
135
|
+
end
|
136
|
+
add_restriction(field_name, restriction_type, value, negated)
|
137
|
+
end
|
138
|
+
|
139
|
+
#
|
140
|
+
# Add a negated shorthand restriction. See #add_shorthand_restriction
|
141
|
+
#
|
142
|
+
def add_negated_shorthand_restriction(field_name, value)
|
143
|
+
add_shorthand_restriction(field_name, value, true)
|
144
|
+
end
|
145
|
+
|
146
|
+
private
|
147
|
+
|
148
|
+
#
|
149
|
+
# Build a field with the given field name. Subclasses may override this
|
150
|
+
# method.
|
151
|
+
#
|
152
|
+
def build_field(field_name)
|
153
|
+
setup.field(field_name)
|
154
|
+
end
|
155
|
+
|
156
|
+
#
|
157
|
+
# Return a setup object which can return a field object given a name.
|
158
|
+
# Subclasses may override this method.
|
159
|
+
#
|
160
|
+
def setup
|
161
|
+
@setup
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|