elasticsearch-persistence-queryable 0.1.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/CHANGELOG.md +16 -0
  4. data/Gemfile +4 -0
  5. data/LICENSE.txt +13 -0
  6. data/README.md +678 -0
  7. data/Rakefile +57 -0
  8. data/elasticsearch-persistence.gemspec +57 -0
  9. data/examples/music/album.rb +34 -0
  10. data/examples/music/artist.rb +50 -0
  11. data/examples/music/artists/_form.html.erb +8 -0
  12. data/examples/music/artists/artists_controller.rb +67 -0
  13. data/examples/music/artists/artists_controller_test.rb +53 -0
  14. data/examples/music/artists/index.html.erb +57 -0
  15. data/examples/music/artists/show.html.erb +51 -0
  16. data/examples/music/assets/application.css +226 -0
  17. data/examples/music/assets/autocomplete.css +48 -0
  18. data/examples/music/assets/blank_cover.png +0 -0
  19. data/examples/music/assets/form.css +113 -0
  20. data/examples/music/index_manager.rb +60 -0
  21. data/examples/music/search/index.html.erb +93 -0
  22. data/examples/music/search/search_controller.rb +41 -0
  23. data/examples/music/search/search_controller_test.rb +9 -0
  24. data/examples/music/search/search_helper.rb +15 -0
  25. data/examples/music/suggester.rb +45 -0
  26. data/examples/music/template.rb +392 -0
  27. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.css +7 -0
  28. data/examples/music/vendor/assets/jquery-ui-1.10.4.custom.min.js +6 -0
  29. data/examples/notes/.gitignore +7 -0
  30. data/examples/notes/Gemfile +28 -0
  31. data/examples/notes/README.markdown +36 -0
  32. data/examples/notes/application.rb +238 -0
  33. data/examples/notes/config.ru +7 -0
  34. data/examples/notes/test.rb +118 -0
  35. data/lib/elasticsearch/per_thread_registry.rb +53 -0
  36. data/lib/elasticsearch/persistence/client.rb +51 -0
  37. data/lib/elasticsearch/persistence/inheritence.rb +9 -0
  38. data/lib/elasticsearch/persistence/model/base.rb +95 -0
  39. data/lib/elasticsearch/persistence/model/callbacks.rb +37 -0
  40. data/lib/elasticsearch/persistence/model/errors.rb +9 -0
  41. data/lib/elasticsearch/persistence/model/find.rb +155 -0
  42. data/lib/elasticsearch/persistence/model/gateway_delegation.rb +23 -0
  43. data/lib/elasticsearch/persistence/model/hash_wrapper.rb +17 -0
  44. data/lib/elasticsearch/persistence/model/rails.rb +39 -0
  45. data/lib/elasticsearch/persistence/model/store.rb +271 -0
  46. data/lib/elasticsearch/persistence/model.rb +148 -0
  47. data/lib/elasticsearch/persistence/null_relation.rb +56 -0
  48. data/lib/elasticsearch/persistence/query_cache.rb +68 -0
  49. data/lib/elasticsearch/persistence/querying.rb +21 -0
  50. data/lib/elasticsearch/persistence/relation/delegation.rb +130 -0
  51. data/lib/elasticsearch/persistence/relation/finder_methods.rb +39 -0
  52. data/lib/elasticsearch/persistence/relation/merger.rb +179 -0
  53. data/lib/elasticsearch/persistence/relation/query_builder.rb +279 -0
  54. data/lib/elasticsearch/persistence/relation/query_methods.rb +362 -0
  55. data/lib/elasticsearch/persistence/relation/search_option_methods.rb +44 -0
  56. data/lib/elasticsearch/persistence/relation/spawn_methods.rb +61 -0
  57. data/lib/elasticsearch/persistence/relation.rb +110 -0
  58. data/lib/elasticsearch/persistence/repository/class.rb +71 -0
  59. data/lib/elasticsearch/persistence/repository/find.rb +73 -0
  60. data/lib/elasticsearch/persistence/repository/naming.rb +115 -0
  61. data/lib/elasticsearch/persistence/repository/response/results.rb +105 -0
  62. data/lib/elasticsearch/persistence/repository/search.rb +156 -0
  63. data/lib/elasticsearch/persistence/repository/serialize.rb +31 -0
  64. data/lib/elasticsearch/persistence/repository/store.rb +94 -0
  65. data/lib/elasticsearch/persistence/repository.rb +77 -0
  66. data/lib/elasticsearch/persistence/scoping/default.rb +137 -0
  67. data/lib/elasticsearch/persistence/scoping/named.rb +70 -0
  68. data/lib/elasticsearch/persistence/scoping.rb +52 -0
  69. data/lib/elasticsearch/persistence/version.rb +5 -0
  70. data/lib/elasticsearch/persistence.rb +157 -0
  71. data/lib/elasticsearch/rails_compatibility.rb +17 -0
  72. data/lib/rails/generators/elasticsearch/model/model_generator.rb +21 -0
  73. data/lib/rails/generators/elasticsearch/model/templates/model.rb.tt +9 -0
  74. data/lib/rails/generators/elasticsearch_generator.rb +2 -0
  75. data/lib/rails/instrumentation/railtie.rb +31 -0
  76. data/lib/rails/instrumentation.rb +10 -0
  77. data/test/integration/model/model_basic_test.rb +157 -0
  78. data/test/integration/repository/custom_class_test.rb +85 -0
  79. data/test/integration/repository/customized_class_test.rb +82 -0
  80. data/test/integration/repository/default_class_test.rb +114 -0
  81. data/test/integration/repository/virtus_model_test.rb +114 -0
  82. data/test/test_helper.rb +53 -0
  83. data/test/unit/model_base_test.rb +48 -0
  84. data/test/unit/model_find_test.rb +148 -0
  85. data/test/unit/model_gateway_test.rb +99 -0
  86. data/test/unit/model_rails_test.rb +88 -0
  87. data/test/unit/model_store_test.rb +514 -0
  88. data/test/unit/persistence_test.rb +32 -0
  89. data/test/unit/repository_class_test.rb +51 -0
  90. data/test/unit/repository_client_test.rb +32 -0
  91. data/test/unit/repository_find_test.rb +388 -0
  92. data/test/unit/repository_indexing_test.rb +37 -0
  93. data/test/unit/repository_module_test.rb +146 -0
  94. data/test/unit/repository_naming_test.rb +146 -0
  95. data/test/unit/repository_response_results_test.rb +98 -0
  96. data/test/unit/repository_search_test.rb +117 -0
  97. data/test/unit/repository_serialize_test.rb +57 -0
  98. data/test/unit/repository_store_test.rb +303 -0
  99. metadata +487 -0
@@ -0,0 +1,279 @@
1
+ module Elasticsearch
2
+ module Persistence
3
+ class QueryBuilder
4
+
5
+ attr_reader :structure, :values
6
+
7
+ def initialize(values)
8
+ @values = values
9
+ end
10
+
11
+ def aggregations
12
+ values[:aggregation]
13
+ end
14
+
15
+ def filters
16
+ values[:filter]
17
+ end
18
+
19
+ def or_filters
20
+ values[:or_filter]
21
+ end
22
+
23
+ def query
24
+ @query ||= compact_where(values[:where])
25
+ end
26
+
27
+ def query_strings
28
+ @query_string ||= compact_where(values[:query_string], bool: false)
29
+ end
30
+
31
+ def must_nots
32
+ @must_nots ||= compact_where(values[:must_not])
33
+ end
34
+
35
+ def shoulds
36
+ @shoulds ||= compact_where(values[:should])
37
+ end
38
+
39
+ def fields
40
+ values[:field]
41
+ end
42
+
43
+ def source
44
+ values[:source]
45
+ end
46
+
47
+ def highlights
48
+ values[:highlight]
49
+ end
50
+
51
+ def size
52
+ values[:size]
53
+ end
54
+
55
+ def sort
56
+ values[:order]
57
+ end
58
+
59
+ def query_filters
60
+ values[:filter]
61
+ end
62
+
63
+ def search_options
64
+ build_search_options
65
+ end
66
+
67
+ def query_string_options
68
+ @query_string_options || {}
69
+ end
70
+
71
+ def count?
72
+ values[:count]
73
+ end
74
+
75
+ def to_elastic
76
+ @structure = Jbuilder.new ignore_nil: true
77
+ build_query
78
+ build_sort unless sort.blank?
79
+ build_highlights unless highlights.blank?
80
+ build_fields unless fields.blank?
81
+ build_source unless source.blank?
82
+ build_aggregations unless aggregations.blank?
83
+ structure.attributes!
84
+ end
85
+
86
+ private
87
+
88
+ def missing_bool_query?
89
+ query.nil? && must_nots.nil? && shoulds.nil?
90
+ end
91
+
92
+ def missing_query_string?
93
+ query_strings.nil?
94
+ end
95
+
96
+ def missing_query_filter?
97
+ query_filters.nil? && or_filters.nil?
98
+ end
99
+
100
+ def build_query
101
+ return if missing_bool_query? && missing_query_string? && missing_query_filter?
102
+ structure.query do
103
+ structure.bool do
104
+ structure.must query unless missing_bool_query?
105
+ structure.must_not must_nots unless must_nots.nil?
106
+ structure.should shoulds unless shoulds.nil?
107
+
108
+ build_filtered_query if query_filters || or_filters
109
+
110
+ end unless missing_bool_query? && missing_query_filter?
111
+
112
+
113
+ structure.query_string do
114
+ structure.extract! query_string_options, *query_string_options.keys
115
+ structure.query query_strings
116
+ end unless query_strings.nil?
117
+ end
118
+ end
119
+
120
+ def build_filtered_query
121
+ structure.filter do
122
+ structure.or do
123
+ or_filters.each do |f|
124
+ structure.child! do
125
+ structure.set! f[:name], extract_filters(f[:name], f[:args])
126
+ end
127
+ end
128
+ end unless or_filters.blank?
129
+
130
+ structure.bool do
131
+ structure.must do
132
+ query_filters.each do |f|
133
+ structure.child! do
134
+ structure.set! f[:name], extract_filters(f[:name], f[:args])
135
+ end
136
+ end
137
+ end
138
+ end unless query_filters.blank?
139
+ end
140
+ end
141
+
142
+ def build_source
143
+ if [true,false].include? source.first
144
+ structure._source source.first
145
+ else
146
+ structure._source do
147
+ structure.include source.first.delete(:include) if source.first.has_key? :include
148
+ structure.exclude source.first.delete(:exclude) if source.first.has_key? :exclude
149
+ end
150
+ end
151
+ end
152
+
153
+ def build_sort
154
+ structure.sort sort.flatten.inject(Hash.new) { |h,v| h.merge(v) }
155
+ end
156
+
157
+ def build_highlights
158
+ structure.highlight do
159
+ structure.fields do
160
+ highlights.each do |highlight|
161
+ structure.set! highlight, extract_highlighter(highlight)
162
+ end
163
+ end
164
+ end
165
+ end
166
+
167
+ def build_filters
168
+ filters.each do |f|
169
+ structure.filter extract_filters(f[:name], f[:args])
170
+ end
171
+ end
172
+
173
+ def build_or_filters
174
+ or_filters.each do |f|
175
+ structure.filter extract_filters(f[:name], f[:args])
176
+ end
177
+ end
178
+
179
+ def build_aggregations
180
+ structure.aggregations do
181
+ aggregations.each do |agg|
182
+ structure.set! agg[:name], aggregation(agg[:name], agg[:args])
183
+ end
184
+ end
185
+ end
186
+
187
+ def build_fields
188
+ structure.fields do
189
+ structure.array! fields.flatten
190
+ end
191
+ end
192
+
193
+ def build_search_options
194
+ values[:search_option] ||= []
195
+
196
+ opts = extra_search_options
197
+ (values[:search_option] + [opts]).compact.inject(Hash.new) { |h,k,v| h.merge(k) }
198
+ end
199
+
200
+ def extra_search_options
201
+ [:size].inject(Hash.new) { |h,k| h[k] = self.send(k) unless self.send(k).nil?; h}
202
+ end
203
+
204
+ def compact_where(q, opts = {bool:true})
205
+ return if q.nil?
206
+ if opts.delete(:bool)
207
+ as_must(q)
208
+ else
209
+ as_query_string(q.flatten)
210
+ end
211
+ end
212
+
213
+ def as_must(q)
214
+ _must = []
215
+ q.each do |arg|
216
+ arg.each_pair { |k,v| _must << (v.is_a?(Array) ? {terms: Hash[k,v]} : {term: Hash[k,v]}) } if arg.class == Hash
217
+ _must << {term: Hash[[arg.split(/:/).collect(&:strip)]]} if arg.class == String
218
+ _must << arg.first if arg.class == Array
219
+ end
220
+ _must.length == 1 ? _must.first : _must
221
+ end
222
+
223
+ def as_query_string(q)
224
+ _and = []
225
+
226
+ @query_string_options = q.pop if q.length > 1
227
+
228
+ q.each do |arg|
229
+ arg.each_pair { |k,v| _and << "(#{k}:#{v})" } if arg.class == Hash
230
+ _and << "(#{arg})" if arg.class == String
231
+ end
232
+ _and.join(" AND ")
233
+ end
234
+
235
+
236
+
237
+ def extract_highlighter(highlighter)
238
+ Jbuilder.new do |highlight|
239
+ highlight.extract! highlighter
240
+ end
241
+ end
242
+
243
+ def extract_filters(name,opts = {})
244
+ Jbuilder.new do |filter|
245
+ case
246
+ when opts.is_a?(Hash)
247
+ filter.extract! opts, *opts.keys
248
+ when opts.is_a?(Array)
249
+ extract_filter_arguments_from_array(filter, opts)
250
+ else
251
+ raise "#filter only accepts Hash or Array"
252
+ end
253
+ end
254
+ end
255
+
256
+ def aggregation(name, opts = {})
257
+ Jbuilder.new do |agg|
258
+ case
259
+ when opts.is_a?(Hash)
260
+ agg.extract! opts, *opts.keys
261
+ when opts.is_a?(Array)
262
+ extract_filter_arguments_from_array(agg, opts)
263
+ else
264
+ raise "#aggregation only accepts Hash or Array"
265
+ end
266
+ end
267
+ end
268
+
269
+ def extract_filter_arguments_from_array(element, opts)
270
+ opts.each do |opt|
271
+ element.child! do
272
+ element.extract! opt , *opt.keys
273
+ end
274
+ end
275
+ end
276
+
277
+ end
278
+ end
279
+ end
@@ -0,0 +1,362 @@
1
+ require 'active_support/core_ext/array/wrap'
2
+
3
+ module Elasticsearch
4
+ module Persistence
5
+ module QueryMethods
6
+ extend ActiveSupport::Concern
7
+
8
+
9
+ MULTI_VALUE_METHODS = [:where, :order, :field, :highlight, :source,
10
+ :must_not, :should, :query_string,
11
+ :aggregation, :search_option,
12
+ :filter, :or_filter, :extending, :skip_callbacks]
13
+ SINGLE_VALUE_METHODS = [:size]
14
+
15
+ class WhereChain
16
+ def initialize(scope)
17
+ @scope = scope
18
+ end
19
+ end
20
+
21
+
22
+ MULTI_VALUE_METHODS.each do |name|
23
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
24
+ def #{name}_values # def select_values
25
+ @values[:#{name}] || [] # @values[:select] || []
26
+ end # end
27
+ #
28
+ def #{name}_values=(values) # def select_values=(values)
29
+ raise ImmutableRelation if @loaded # raise ImmutableRelation if @loaded
30
+ @values[:#{name}] = values # @values[:select] = values
31
+ end # end
32
+ CODE
33
+ end
34
+
35
+ SINGLE_VALUE_METHODS.each do |name|
36
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
37
+ def #{name}_value # def readonly_value
38
+ @values[:#{name}] # @values[:readonly]
39
+ end # end
40
+ CODE
41
+ end
42
+
43
+ SINGLE_VALUE_METHODS.each do |name|
44
+ class_eval <<-CODE, __FILE__, __LINE__ + 1
45
+ def #{name}_value=(value) # def readonly_value=(value)
46
+ raise ImmutableRelation if @loaded # raise ImmutableRelation if @loaded
47
+ @values[:#{name}] = value # @values[:readonly] = value
48
+ end # end
49
+ CODE
50
+ end
51
+
52
+
53
+
54
+ def order(*args)
55
+ check_if_method_has_arguments!(:order, args)
56
+ spawn.order!(*args)
57
+ end
58
+
59
+ def order!(*args)
60
+ self.order_values += [preprocess_order_args(args)]
61
+ self
62
+ end
63
+
64
+ alias :sort :order
65
+
66
+
67
+ def skip_callbacks(*args)
68
+ spawn.skip_callbacks!(*args)
69
+ end
70
+
71
+ def skip_callbacks!(*args)
72
+ self.skip_callbacks_values += args
73
+ self
74
+ end
75
+
76
+ alias :sort :order
77
+
78
+
79
+ def size(args)
80
+ spawn.size!(args)
81
+ end
82
+
83
+ def size!(args)
84
+ self.size_value = args
85
+ self
86
+ end
87
+
88
+ alias :limit :size
89
+
90
+
91
+
92
+
93
+ def where(opts = :chain, *rest)
94
+ if opts == :chain
95
+ WhereChain.new(spawn)
96
+ elsif opts.blank?
97
+ self
98
+ else
99
+ spawn.where!(opts, *rest)
100
+ end
101
+ end
102
+
103
+ alias :must :where
104
+
105
+ def where!(opts, *rest) # :nodoc:
106
+ if opts == :chain
107
+ WhereChain.new(self)
108
+ else
109
+ #if Hash === opts
110
+ #opts = sanitize_forbidden_attributes(opts)
111
+ #end
112
+
113
+ self.where_values += build_where(opts, rest)
114
+ self
115
+ end
116
+ end
117
+
118
+
119
+
120
+
121
+ def query_string(opts = :chain, *rest)
122
+ if opts == :chain
123
+ WhereChain.new(spawn)
124
+ elsif opts.blank?
125
+ self
126
+ else
127
+ spawn.query_string!(opts, *rest)
128
+ end
129
+ end
130
+
131
+ def query_string!(opts, *rest) # :nodoc:
132
+ if opts == :chain
133
+ WhereChain.new(self)
134
+ else
135
+ self.query_string_values += build_where(opts, rest)
136
+ self
137
+ end
138
+ end
139
+
140
+
141
+
142
+
143
+ def must_not(opts = :chain, *rest)
144
+ if opts == :chain
145
+ WhereChain.new(spawn)
146
+ elsif opts.blank?
147
+ self
148
+ else
149
+ spawn.must_not!(opts, *rest)
150
+ end
151
+ end
152
+
153
+ alias :where_not :must_not
154
+
155
+ def must_not!(opts, *rest)
156
+ if opts == :chain
157
+ WhereChain.new(self)
158
+ else
159
+ self.must_not_values += build_where(opts, rest)
160
+ self
161
+ end
162
+ end
163
+
164
+
165
+
166
+
167
+ def should(opts = :chain, *rest)
168
+ if opts == :chain
169
+ WhereChain.new(spawn)
170
+ elsif opts.blank?
171
+ self
172
+ else
173
+ spawn.should!(opts, *rest)
174
+ end
175
+ end
176
+
177
+ def should!(opts, *rest)
178
+ if opts == :chain
179
+ WhereChain.new(self)
180
+ else
181
+ self.should_values += build_where(opts, rest)
182
+ self
183
+ end
184
+ end
185
+
186
+
187
+ def or_filter(name, options = {}, &block)
188
+ spawn.or_filter!(name, options, &block)
189
+ end
190
+
191
+ def or_filter!(name, options = {}, &block)
192
+ self.or_filter_values += [{name: name, args: options}]
193
+ self
194
+ end
195
+
196
+
197
+
198
+ def filter(name, options = {}, &block)
199
+ spawn.filter!(name, options, &block)
200
+ end
201
+
202
+ def filter!(name, options = {}, &block)
203
+ self.filter_values += [{name: name, args: options}]
204
+ self
205
+ end
206
+
207
+
208
+
209
+
210
+ def aggregation(name, options = {}, &block)
211
+ spawn.aggregation!(name, options, &block)
212
+ end
213
+
214
+ def aggregation!(name, options = {}, &block)
215
+ self.aggregation_values += [{name: name, args: options}]
216
+ self
217
+ end
218
+
219
+
220
+
221
+
222
+ def field(*args)
223
+ spawn.field!(*args)
224
+ end
225
+ alias :fields :field
226
+
227
+ def field!(*args)
228
+ self.field_values += args
229
+ self
230
+ end
231
+
232
+
233
+
234
+
235
+ def source(*args)
236
+ spawn.source!(*args)
237
+ end
238
+
239
+ def source!(*args)
240
+ self.source_values += args
241
+ self
242
+ end
243
+
244
+
245
+
246
+
247
+ def has_field?(field)
248
+ spawn.filter(:exists, {field: field})
249
+ end
250
+
251
+
252
+
253
+
254
+ def bind(value)
255
+ spawn.bind!(value)
256
+ end
257
+
258
+ def bind!(value) # :nodoc:
259
+ self.bind_values += [value]
260
+ self
261
+ end
262
+
263
+ def build_where(opts, other = [])
264
+ case opts
265
+ when String, Array
266
+ #TODO: Remove duplication with: /activerecord/lib/active_record/sanitization.rb:113
267
+ values = Hash === other.first ? other.first.values : other
268
+
269
+ values.grep(Elasticsearch::Persistence::Relation) do |rel|
270
+ self.bind_values += rel.bind_values
271
+ end
272
+
273
+ [other.empty? ? opts : ([opts] + other)]
274
+ when Hash
275
+ [other.empty? ? opts : ([opts] + other)]
276
+ else
277
+ [opts]
278
+ end
279
+ end
280
+
281
+ def highlight(*args)
282
+ spawn.highlight!(*args)
283
+ end
284
+
285
+ def highlight!(*args)
286
+ self.highlight_values += args
287
+ self
288
+ end
289
+
290
+
291
+ # Returns a chainable relation with zero records.
292
+ #
293
+ #
294
+ def none
295
+ extending(NullRelation)
296
+ end
297
+
298
+ def none! # :nodoc:
299
+ extending!(NullRelation)
300
+ end
301
+
302
+
303
+ def extending(*modules, &block)
304
+ if modules.any? || block
305
+ spawn.extending!(*modules, &block)
306
+ else
307
+ self
308
+ end
309
+ end
310
+
311
+ def extending!(*modules, &block) # :nodoc:
312
+ modules << Module.new(&block) if block
313
+ modules.flatten!
314
+
315
+ self.extending_values += modules
316
+ extend(*extending_values) if extending_values.any?
317
+
318
+ self
319
+ end
320
+
321
+ private
322
+
323
+ def check_if_method_has_arguments!(method_name, args)
324
+ if args.blank?
325
+ raise ArgumentError, "The method .#{method_name}() must contain arguments."
326
+ end
327
+ end
328
+
329
+ VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC,
330
+ 'asc', 'desc', 'ASC', 'DESC'] # :nodoc:
331
+
332
+ def validate_order_args(args)
333
+ args.each do |arg|
334
+ next unless arg.is_a?(Hash)
335
+ arg.each do |_key, value|
336
+ raise ArgumentError, "Direction \"#{value}\" is invalid. Valid " \
337
+ "directions are: #{VALID_DIRECTIONS.inspect}" unless VALID_DIRECTIONS.include?(value)
338
+ end
339
+ end
340
+ end
341
+
342
+ def preprocess_order_args(order_args)
343
+ args = order_args.reject{ |arg| arg.is_a?(Hash) }.take(2)
344
+ return [Hash[[args]]] if args.length == 2
345
+ order_args.select { |arg| arg.is_a?(Hash)}.flatten
346
+ end
347
+
348
+ def add_relations_to_bind_values(attributes)
349
+ if attributes.is_a?(Hash)
350
+ attributes.each_value do |value|
351
+ if value.is_a?(ActiveRecord::Relation)
352
+ self.bind_values += value.bind_values
353
+ else
354
+ add_relations_to_bind_values(value)
355
+ end
356
+ end
357
+ end
358
+ end
359
+ end
360
+
361
+ end
362
+ end
@@ -0,0 +1,44 @@
1
+ module Elasticsearch
2
+ module Persistence
3
+
4
+ module SearchOptionMethods
5
+ extend ActiveSupport::Concern
6
+
7
+ def routing(args)
8
+ check_if_method_has_arguments!(:routing, args)
9
+ spawn.routing!(args)
10
+ end
11
+
12
+ def routing!(args)
13
+ merge_search_option_values(:routing, args)
14
+ self
15
+ end
16
+
17
+ def search_type(args)
18
+ check_if_method_has_arguments!(:search_type, args)
19
+ spawn.search_type!(args)
20
+ end
21
+
22
+ def search_type!(args)
23
+ merge_search_option_values(:search_type, args)
24
+ self
25
+ end
26
+
27
+ def search_options(*args)
28
+ spawn.search_options!(*args)
29
+ end
30
+
31
+ def search_options!(*args)
32
+ self.search_option_values += args
33
+ self
34
+ end
35
+
36
+ private
37
+
38
+ def merge_search_option_values(key, value)
39
+ self.search_option_values += [Hash[key,value]]
40
+ end
41
+
42
+ end
43
+ end
44
+ end