multi-solr 01.01.05

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.
Files changed (53) hide show
  1. data/.gitignore +6 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +4 -0
  4. data/Rakefile +1 -0
  5. data/lib/multi_solr/base_searcher.rb +393 -0
  6. data/lib/multi_solr/filter_value_composite.rb +33 -0
  7. data/lib/multi_solr/rails_form_render_helper.rb +84 -0
  8. data/lib/multi_solr/search_request.rb +209 -0
  9. data/lib/multi_solr/search_result.rb +127 -0
  10. data/lib/multi_solr/single_core_handler.rb +341 -0
  11. data/lib/multi_solr/solr_filter_collection.rb +97 -0
  12. data/lib/multi_solr/solr_filter_date.rb +46 -0
  13. data/lib/multi_solr/solr_filter_date_range.rb +62 -0
  14. data/lib/multi_solr/solr_filter_free_query.rb +11 -0
  15. data/lib/multi_solr/solr_filter_simple.rb +96 -0
  16. data/lib/multi_solr/timeline_core_handler.rb +131 -0
  17. data/lib/multi_solr/version.rb +3 -0
  18. data/lib/multi_solr.rb +43 -0
  19. data/multi-solr.gemspec +28 -0
  20. data/spec/fixtures/solr-testdata.yml +13 -0
  21. data/spec/multi_solr/base_searcher_spec.rb +212 -0
  22. data/spec/multi_solr/search_request_spec.rb +45 -0
  23. data/spec/multi_solr/search_result_spec.rb +113 -0
  24. data/spec/multi_solr/single_core_handler_spec.rb +169 -0
  25. data/spec/multi_solr/timeline_core_handler_spec.rb +107 -0
  26. data/spec/solr_test_helper.rb +15 -0
  27. data/spec/solr_testdata_provider.rb +89 -0
  28. data/spec/spec_helper.rb +27 -0
  29. data/test-solr/.gitignore +4 -0
  30. data/test-solr/articles.xml +6 -0
  31. data/test-solr/etc/jetty.xml +227 -0
  32. data/test-solr/etc/webdefault.xml +410 -0
  33. data/test-solr/lib/jetty-6.1.26-patched-JETTY-1340.jar +0 -0
  34. data/test-solr/lib/jetty-LICENSE.txt +202 -0
  35. data/test-solr/lib/jetty-NOTICE.txt +36 -0
  36. data/test-solr/lib/jetty-util-6.1.26-patched-JETTY-1340.jar +0 -0
  37. data/test-solr/lib/jsp-2.1/core-3.1.1.jar +0 -0
  38. data/test-solr/lib/jsp-2.1/jsp-2.1-glassfish-2.1.v20091210.jar +0 -0
  39. data/test-solr/lib/jsp-2.1/jsp-2.1-jetty-6.1.26.jar +0 -0
  40. data/test-solr/lib/jsp-2.1/jsp-api-2.1-glassfish-2.1.v20091210.jar +0 -0
  41. data/test-solr/lib/lukeall-3.4.0_1.jar +0 -0
  42. data/test-solr/lib/servlet-api-2.5-20081211.jar +0 -0
  43. data/test-solr/solr/lib/apache-solr-dataimporthandler-3.4.0.jar +0 -0
  44. data/test-solr/solr/solr.xml +20 -0
  45. data/test-solr/solr/testcore/conf/dataimport-test.xml +12 -0
  46. data/test-solr/solr/testcore/conf/schema.xml +42 -0
  47. data/test-solr/solr/testcore/conf/solr_schema.css +58 -0
  48. data/test-solr/solr/testcore/conf/solr_schema.xsl +72 -0
  49. data/test-solr/solr/testcore/conf/solrconfig.xml +72 -0
  50. data/test-solr/start-test-solr.sh +10 -0
  51. data/test-solr/start.jar +0 -0
  52. data/test-solr/webapps/solr.war +0 -0
  53. metadata +212 -0
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .idea
6
+ .rvmrc
data/.rspec ADDED
@@ -0,0 +1 @@
1
+ --color
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in multi-solr.gemspec
4
+ gemspec
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,393 @@
1
+ # Basis-Suchmodule für SOLR-Indizies
2
+
3
+ require 'rsolr'
4
+ require "active_support/core_ext/class/attribute_accessors"
5
+
6
+ module MultiSolr::BaseSearcher
7
+
8
+
9
+ # Erweitern einer Searcher-Class um Basis-Solr-Funktionen
10
+ #
11
+ def self.included(base)
12
+ base.class_eval do
13
+
14
+ cattr_accessor :solr_url # String mit der Base-Solr-Url (ohne Core-Anteil!)
15
+
16
+ cattr_accessor :result_class do # die zu nutzende Klasse für das Suchergebnis
17
+ MultiSolr::SearchResult
18
+ end
19
+
20
+ cattr_accessor :facet_enum_fields do # Array mit den Namen der Felder, die die Facet-Enum-Methode für Facets nutzen (Felder mit kleinen Wertebereichen)
21
+ []
22
+ end
23
+
24
+ # der zu verwendende SOLR-Core, wird per default aus dem Klassennamen gebildet
25
+ # Beispiel: ContainerSearcher => 'core-container'
26
+ cattr_accessor(:core_name, :instance_reader => false, :instance_writer => false) do
27
+ m = self.name.match(/(\w+::)*(\w+)Searcher/)
28
+ if m
29
+ c = m[2].downcase
30
+ name = "core-#{c}"
31
+ else
32
+ name = 'core-default'
33
+ end
34
+ name
35
+ end
36
+
37
+ attr_accessor :fieldlist # Field-List (siehe Solr-Doku fl-Parameter), default ist *
38
+ attr_accessor :facets_only # wenn true, dann nur Facets ermittlen
39
+ attr_accessor :without_facets # wenn true, dann auf Facets verzichten
40
+ attr_accessor :result_format # Rückgabe-Format (json, xml), wenn nicht gesetzt wird "ruby" geliefert; Ist es gesetzt wird das Ergebnis nicht geparst (also raw als String zurückgegeben)
41
+
42
+
43
+ end
44
+ base.extend ClassMethods
45
+ end
46
+
47
+
48
+ module ClassMethods
49
+
50
+ def set_solr_url url
51
+ self.solr_url = url
52
+ end
53
+
54
+ # Setzen des CORE-Namens
55
+ def set_core_name name
56
+ self.core_name = name
57
+ end
58
+
59
+ def set_result_class clasz
60
+ self.result_class = clasz
61
+ end
62
+
63
+
64
+ # Setzen der Feldnamen, die bei Facetierung die Facet-Enum-Methode des SOLR nutzen sollen
65
+ def set_facet_enum_fields *field_names
66
+ self.facet_enum_fields += field_names
67
+ end
68
+
69
+
70
+ # Ermittelt und cached die möglichen Werte der als pre_cache_value_fields definierten Felder
71
+ # Diese werden im Rails-Cache zwischengespeichert
72
+ # Ansonsten see BaseSearcher.list_possible_values
73
+ # zusätzlicher Parameter:
74
+ # expires_in: optional, Gültigkeit des Cache-Wertes in Sekunden, default ist 1 Stunde
75
+ #
76
+ def cached_list_possible_values fieldname, context=nil, searcher_options=nil, expires_in=1.hours
77
+ cache_key = "solr-#{self.core_name}-#{context}-#{fieldname}-values"
78
+ values = MultiSolr.cache.read(cache_key)
79
+ if values.nil?
80
+ # dann sind noch gar keine Werte gecached => diese holen
81
+ values = list_possible_values fieldname, context, searcher_options
82
+ # und nun im Cache ablegen
83
+ MultiSolr.logger.debug "#{name}.cached_list_possible_values: write in cache '#{cache_key}' => #{values.inspect}" if MultiSolr.logger.debug?
84
+ MultiSolr.cache.write(cache_key, values, :expires_in => expires_in)
85
+ end
86
+ values
87
+ end
88
+
89
+
90
+ # Liefert zu dem spezifizierten Kontext und Feld die möglichen Werte
91
+ # Parameter:
92
+ # fieldname: Name des Feldes (als Symbol)
93
+ # context: optionales Object mit weiteren Context-Informationen, dieser wird an den Force-Query-Builder übergeben
94
+ # searcher_options: optinale Hash mit Optionen für den hier intern erzeugten Searcher (see self.initialize)
95
+ # Beispiel:
96
+ # searcher.list_possible_values :lkz, :whs_id => 5
97
+ #
98
+ def list_possible_values fieldname, context=nil, searcher_options=nil
99
+ s_request = MultiSolr::SearchRequest.new :facets => [fieldname]
100
+ searcher_options ||= {}
101
+ searcher = self.new(searcher_options.merge(:facets_only => true))
102
+ result = searcher.execute(s_request, context)
103
+ facet_counts = result.facet_counts
104
+ values = []
105
+ if MultiSolr.logger.debug?
106
+ MultiSolr.logger.debug "#{name}.list_possible_values(#{fieldname}, #{context.inspect}): facet_counts=#{facet_counts.inspect}"
107
+ end
108
+ if facet_counts
109
+ value_pairs = facet_counts[fieldname.to_s]
110
+ if value_pairs && !value_pairs.empty?
111
+ # das value_pairs besteht Paar-weise aus Value und Anzahl
112
+ # Es werden hier nur die Values gebraucht, wo die Anzahl >0 ist
113
+ value_pairs.each do |value_count_pair|
114
+ val, count = value_count_pair
115
+ if val && count > 0
116
+ # wenn val nur aus Zahlen besteht, dann nach Integer konvertieren (wegen der Sortierung)
117
+ val = val.to_i if val =~ /\d+/
118
+ values << val
119
+ end
120
+ end
121
+ values.sort!
122
+ end
123
+ end
124
+ if MultiSolr.logger.debug?
125
+ MultiSolr.logger.debug "#{name}.list_possible_values(#{fieldname}, #{context.inspect}) => #{values.inspect}"
126
+ end
127
+ values
128
+ end
129
+
130
+
131
+ # Liefert RSolr-Connection (RSolr.connect) zum konfigurierten SOLR-Server(see solr_url)
132
+ # und konfiguriertem Core (see core_name)
133
+ def solr_connection
134
+ url = self.solr_url || raise("no solr-url configured!")
135
+ url = "#{url}/#{self.core_name}" if self.core_name
136
+ MultiSolr.logger.debug("solr_connection: url==#{url}")
137
+ RSolr.connect :url => url
138
+ end
139
+
140
+
141
+ # sendet Ping an SOLR-Instance
142
+ # returns true if ok
143
+ def ping
144
+ self.solr_connection.head("admin/ping").response[:status] == 200
145
+ end
146
+
147
+
148
+ # ermitteln Zeitstempel des letzten Datenimports
149
+ def import_status solr_core_import_handler_propfile_path
150
+ MultiSolr.cache.fetch("Solr.import_status.#{self.core_name}.#{solr_core_import_handler_propfile_path}", :expires_in => 900) do
151
+ result = 'unbekannt'
152
+ begin
153
+ raise("Solr-Import-Status-Propertiesfile not exist") unless File.exist?(solr_core_import_handler_propfile_path)
154
+ matcher = /^last_index_time=(.*)$/
155
+ data = File.read(solr_core_import_handler_propfile_path)
156
+ match = matcher.match(data)
157
+ if match
158
+ result = match[1]
159
+ result.gsub!('\\', '') # Zeit enthält \ vor :
160
+ result = result[0...-3] # Sekunden entfernen
161
+ end
162
+ rescue => ex
163
+ MultiSolr.logger.warn "SolrSearch.import_status: source=#{solr_core_import_handler_propfile_path}, error=#{ex.message}\n\t"+ex.backtrace.join("\n\t")
164
+ end
165
+ MultiSolr.logger.info "SolrSearch.import_status: #{solr_core_import_handler_propfile_path}, result=#{result}"
166
+ result
167
+ end
168
+ end
169
+
170
+
171
+ # liefert einzelnes Solr-Dokument an Hand der Id
172
+ # Parameter:
173
+ # id: die gewünschte Id (Integer oder String)
174
+ # id_field_name : optional, der Name des ID-Fields, default ist 'id'
175
+ def get_doc_by_id(id, id_field_name=:id)
176
+ solr_result = solr_connection.get 'select', :params => {:q => "#{id_field_name}:#{id}", :rows => 1}
177
+ docs = solr_result['response']['docs']
178
+ return nil if docs.nil? || docs.empty?
179
+ docs.first
180
+ end
181
+
182
+ end
183
+ # ===== ENDE der Class-Methods =====
184
+
185
+
186
+
187
+ # ===== START Instance-Methods =====
188
+
189
+
190
+ # Constructor
191
+ # params:
192
+ # options: optionaler Hash mit Options (als Option sind aller hier definierten Attribute erlaubt)
193
+ def initialize options=nil
194
+ if options
195
+ options.each do |k,v|
196
+ self.send("#{k}=", v)
197
+ end
198
+ end
199
+ end
200
+
201
+ # liefert lokalen Core-Namen und wenn nicht gesetzt den globalen Core-Namen (in der Klasse definierten)
202
+ def core_name
203
+ @core_name || self.class.core_name
204
+ end
205
+
206
+
207
+ # setzt lokalen Core-Namen ohne den globalen Core-Namen (in der Klasse definiert) zu ändern
208
+ def core_name=(name)
209
+ @core_name = name
210
+ end
211
+
212
+
213
+ # liefert SOLR-Connection
214
+ def solr_connection
215
+ return @solr_connection if @solr_connection
216
+ url = self.class.solr_url || raise("no solr-url configured!")
217
+ url = "#{url}/#{self.core_name}" if self.core_name
218
+ MultiSolr.logger.debug("solr_connection: url==#{url}")
219
+ @solr_connection = RSolr.connect :url => url
220
+ end
221
+
222
+
223
+
224
+ # Ausführen der Suche / Recherche
225
+ # params:
226
+ # solr_search_request: die Suchanfrage als SolrSearchRequest-Instance
227
+ # context: Hash mit weiteren Context-Informationen, dieser wird u.a. an den Force-Query-Builder übergeben
228
+ def execute solr_search_request, context=nil
229
+ solr_params = build_solr_params solr_search_request, context
230
+ solr_result = solr_connection.get 'select', :params => solr_params
231
+
232
+ # RAW-Result liefern wenn Result-Format gesetzt ist
233
+ return solr_result if self.result_format
234
+
235
+ # Parsen des Ergebnisses
236
+ result = self.result_class.new solr_result, solr_search_request, context
237
+ result
238
+ end
239
+
240
+
241
+ # Bilden der SOLR-Parameter für eine SOLR-Anfrage
242
+ # params:
243
+ # solr_search_request: die Suchanfrage als SolrSearchRequest-Instance
244
+ # context: Hash mit weiteren Context-Informationen, dieser wird an den Force-Query-Builder übergeben
245
+ # returns: Hash mit den SOLR-Parametern
246
+ def build_solr_params solr_search_request, context=nil
247
+ solr_params = {}
248
+ solr_params['stats.field'] = []
249
+
250
+ fq_params = self.force_query_params context
251
+ if fq_params && fq_params.is_a?(Hash)
252
+ fq = []
253
+ fq_params.each{|k, v| fq << "#{k}:#{v}"}
254
+ solr_params[:fq] = fq.join(' ')
255
+ end
256
+
257
+ q = solr_search_request.build_query
258
+ q = "*:*" if q.blank? # wenn keine Query angegeben ist, dann nach allem Suchen
259
+ solr_params[:q] = q
260
+
261
+ # Fieldlist
262
+ if q['_val_:']
263
+ # dann enthält die Query eine query-function
264
+ # Der Wert dieser wird immer im field "score" abgelegt
265
+ # daher dieses Feld zur Feldliste hinzufügen
266
+ if self.fieldlist
267
+ self.fieldlist << ',score' unless self.fieldlist[',score']
268
+ else
269
+ self.fieldlist = '*,score'
270
+ end
271
+ end
272
+ solr_params[:fl] = self.fieldlist if self.fieldlist
273
+
274
+ # Sortierung
275
+ if solr_search_request.sorts && !solr_search_request.sorts.empty?
276
+ solr_search_request.sorts.delete_if{|s| s.blank?}
277
+ solr_params[:sort] = solr_search_request.sorts.map{|s| s =~ /\s(asc|desc)$/ ? s : "#{s} asc"}.join(',')
278
+ end
279
+
280
+ # Facets
281
+ if !self.without_facets && solr_search_request.facets
282
+ parse_facets solr_search_request, solr_params
283
+ end
284
+
285
+ # Stats
286
+ if solr_search_request.stats_fields && !solr_search_request.stats_fields.empty?
287
+ s_fields = solr_search_request.stats_fields.select{|f| !f.blank?}
288
+ unless s_fields.empty?
289
+ solr_params[:stats] = true
290
+ solr_params['stats.field'] += s_fields
291
+ end
292
+ end
293
+ solr_params['stats.field'].map!{|f| f.to_s}.uniq!
294
+
295
+ # Gruppierung
296
+ if !solr_search_request.group_field.blank? && !self.facets_only
297
+ solr_params[:group] = true
298
+ solr_params['group.field'] = solr_search_request.group_field
299
+ solr_params['group.ngroups'] = true
300
+ solr_params['group.limit'] = solr_search_request.group_size || 1
301
+ solr_params['group.truncate'] = true if solr_params[:facet] && solr_search_request.group_truncate
302
+ end
303
+
304
+
305
+ # Paginierung
306
+ if self.facets_only
307
+ solr_params[:rows] = 0
308
+ else
309
+ solr_params[:rows] = solr_search_request.page_size
310
+ solr_params[:start] = (solr_search_request.page-1) * solr_search_request.page_size
311
+ end
312
+
313
+ # Ausgabe-Format
314
+ solr_params[:wt] = self.result_format if self.result_format
315
+
316
+ if MultiSolr.logger.debug?
317
+ MultiSolr.logger.debug "SolrSearch#build_solr_params: #{self.inspect}\n\tSEARCH-REQUEST=#{solr_search_request.inspect}\n\t=> SOLR_PARAMS=#{solr_params.inspect}\n"
318
+ end
319
+ solr_params
320
+ end
321
+
322
+
323
+ protected
324
+
325
+ # liefert wenn notwendig die Parameter als Hash für eine SOLR-Force-Query
326
+ # sollte bei Bedarf von der nutzenden Klasse überschrieben werden.
327
+ # params:
328
+ # context: Hash mit weiteren Context-Informationen
329
+ def force_query_params context
330
+ context
331
+ end
332
+
333
+
334
+ private
335
+
336
+
337
+ # Bilden der Facet-Solr-Params aus den Facet-Definitionen des Requests
338
+ def parse_facets solr_search_request, solr_params
339
+ solr_search_request.facets.delete_if(&:blank?) # leer Elemente entfernen
340
+ return if solr_search_request.facets.empty?
341
+
342
+ solr_params['facet.field'] = []
343
+ solr_params['facet.range'] = []
344
+ facet_params = solr_search_request.facet_params || {}
345
+ solr_search_request.facets.map(&:to_sym).each do |facet_field|
346
+ field_facet_params = facet_params[facet_field] || {}
347
+ stats_facet_field = field_facet_params[:stats_field]
348
+ if stats_facet_field
349
+ # dann Facet per Stats-Componente
350
+ solr_params[:stats] = true
351
+ if stats_facet_field.is_a?(Array)
352
+ solr_params['stats.field'] += stats_facet_field
353
+ else
354
+ solr_params['stats.field'] << stats_facet_field
355
+ stats_facet_field = [stats_facet_field]
356
+ end
357
+ stats_facet_field.each do |sfield_name|
358
+ solr_params["f.#{sfield_name}.stats.facet"] ||= []
359
+ solr_params["f.#{sfield_name}.stats.facet"] << facet_field
360
+ end
361
+ else
362
+ solr_params[:facet] = true
363
+ if field_facet_params[:range]
364
+ # Range-Facet
365
+ solr_params[:facet] = true
366
+ solr_params['facet.range'] << facet_field
367
+ field_facet_params[:end] ||= 'NOW/DAY'
368
+ field_facet_params[:gap] ||= '+1DAY'
369
+ field_facet_params.each do |option_name, value|
370
+ solr_params["f.#{facet_field}.facet.range.#{option_name}"] = value
371
+ end
372
+ else
373
+ # normale Facet-Field
374
+ solr_params['facet.field'] << facet_field
375
+ field_facet_params[:mincount] ||= 1 # Facets ohne Treffer ignorieren
376
+ # Nutzen der Facet-Enum-Methode fuer spezielle Felder (Felder mit kleinen Wertebereichen)
377
+ field_facet_params['method'] = 'enum' if self.facet_enum_fields.include?(facet_field)
378
+
379
+ field_facet_params.each do |option_name, value|
380
+ solr_params["f.#{facet_field}.facet.#{option_name}"] = value
381
+ end
382
+ end
383
+ end
384
+ end
385
+ if solr_params[:facet]
386
+ # Umschalten der Facet-Ergebnisse in Array-Darstellung
387
+ # (der json.nl-Schalter wirkt auch bei Ruby siehe http://wiki.apache.org/solr/SolJSON)
388
+ solr_params['json.nl'] = 'arrarr'
389
+ end
390
+
391
+ end
392
+
393
+ end
@@ -0,0 +1,33 @@
1
+ # Composite-Klasse von Filter und Filter-Value
2
+
3
+ class MultiSolr::FilterValueComposite
4
+
5
+ attr_accessor :filter
6
+ attr_accessor :value
7
+
8
+ # Constructor
9
+ # Params:
10
+ # filter: konkrete Filter-Instance (i.a. ein MultiSolr::SolrFilterSimple oder eine Subklasse davon)
11
+ # value: aktueller Wert für diesen Filter (String oder Hash)
12
+ def initialize filter, value=nil
13
+ @filter = filter
14
+ @value = value
15
+ end
16
+
17
+ # delegate der Methode 'render_value' an den Filter unter Nutzung des hinterlegten Wertes
18
+ def render_value
19
+ @filter.render_value @value
20
+ end
21
+
22
+ # delegate der Methode 'render_for_semantic_form' an den Filter unter Nutzung des hinterlegten Wertes
23
+ def render_for_semantic_form sform, context=nil, form_input_options={}
24
+ @filter.render_for_semantic_form sform, @value, context, form_input_options
25
+ end
26
+
27
+
28
+ # delegate der Methode 'build_solr_query' an den Filter unter Nutzung des hinterlegten Wertes
29
+ def build_solr_query
30
+ @filter.build_solr_query @value
31
+ end
32
+
33
+ end
@@ -0,0 +1,84 @@
1
+ module MultiSolr::RailsFormRenderHelper
2
+
3
+
4
+ # Generieren der HML-Form-Felder (input/select/..) für den angegeben Filter
5
+ # Params:
6
+ # form: das Rails-Form-Object, dieses MUSS als Object eine MultiSolr::SearchRequest-Instance haben
7
+ # filter_name: Name des Filters als Symbol (die SearchRequest-Instance im Form muss diesen Filter kennen)
8
+ # options: optionale Formular-Input-Feld-Options. Beschreibung => siehe jeweilige Beschreibung je Filter-Methode
9
+ # Diese werden i.d.R. an die Rails-Form-Methode 'text_field' weitergegeben.
10
+ #
11
+ # returns: HTML-Code des Input-Feldes als String
12
+ def render_solr_filter_for_form form, filter_name, options={}
13
+ cur_options = options.clone
14
+ search_request = form.object
15
+ filter = search_request.class.possible_filters[filter_name]
16
+ raise "unknown filter: #{filter_name}" if filter.nil?
17
+ label = cur_options.delete(:label) || filter.label
18
+ render_method = "render_#{filter.class.to_s.underscore}"
19
+ render_method.gsub!("/", '_')
20
+ render_method.gsub!("multi_solr_", '')
21
+ "<label>#{label}</label>".html_safe + send(render_method, form, filter, cur_options)
22
+ end
23
+
24
+
25
+ # generiert für einen SolrFilterSimple einen input-tag vom typ text
26
+ # mit der css-class "simple"
27
+ def render_solr_filter_simple form, filter, options
28
+ add_class options, 'simple'
29
+ form.text_field "filter_#{filter.name}", options
30
+ end
31
+
32
+
33
+ # generiert für einen SolrFilterSimple einen input-tag vom typ text
34
+ # mit der css-class "datepicker"
35
+ # Diese css-Klasse kann dann als jQuery-Selector für datepicker genutzt werden
36
+ def render_solr_filter_date form, filter, options
37
+ add_class options, 'datepicker'
38
+ form.text_field "filter_#{filter.name}", options
39
+ end
40
+
41
+
42
+ def render_solr_filter_date_range form, filter, options
43
+ add_class options, 'datepicker'
44
+ value = form.object.send("filter_#{filter.name}")
45
+ return nil if value.blank? || !value.is_a?(Hash) || value.empty?
46
+ from = value["#{filter.name}_from"]
47
+ to = value["#{filter.name}_to"]
48
+ date_range = Struct.new("#{filter.name}_from".to_sym, "#{filter.name}_to".to_sym).new from,to
49
+ form.fields_for "filter_#{filter.name}", date_range do |fields_form|
50
+ fields_form.template.concat("<label>ab</label>".html_safe)
51
+ fields_form.template.concat(fields_form.text_field("#{filter.name}_from", options))
52
+ fields_form.template.concat("<label>bis</label>".html_safe)
53
+ fields_form.template.concat(fields_form.text_field("#{filter.name}_to", options))
54
+ end
55
+ end
56
+
57
+
58
+
59
+ def render_solr_filter_collection form, filter, options
60
+ add_class options, 'collection'
61
+ core_handler = options.delete(:core_handler)
62
+ context = options.delete(:context)
63
+ data = filter.collection_data(core_handler, context)
64
+ form.select "filter_#{filter.name}", data, options
65
+ end
66
+
67
+
68
+ def render_solr_filter_free_query form, filter, options
69
+ add_class options, 'free_query'
70
+ form.text_field "filter_#{filter.name}", options
71
+ end
72
+
73
+
74
+ private
75
+
76
+
77
+ def add_class options, css_class_name
78
+ css_class = options[:class]
79
+ css_class = css_class.nil? ? css_class_name : "#{css_class} #{css_class_name}"
80
+ options[:class] = css_class
81
+ end
82
+
83
+
84
+ end