blacklight_cql 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +142 -0
  3. data/Rakefile +43 -0
  4. data/VERSION +1 -0
  5. data/app/controllers/blacklight_cql/explain_controller.rb +17 -0
  6. data/app/helpers/blacklight_cql/explain_helper.rb +44 -0
  7. data/app/views/blacklight_cql/explain/explain.xml.builder +30 -0
  8. data/config/routes.rb +10 -0
  9. data/init.rb +1 -0
  10. data/install.rb +1 -0
  11. data/lib/blacklight_cql/blacklight_to_solr.rb +115 -0
  12. data/lib/blacklight_cql/solr_helper_extension.rb +24 -0
  13. data/lib/blacklight_cql/template_helper_extension.rb +19 -0
  14. data/lib/blacklight_cql.rb +25 -0
  15. data/rails/init.rb +32 -0
  16. data/spec/app_root/app/controllers/application_controller.rb +2 -0
  17. data/spec/app_root/config/boot.rb +115 -0
  18. data/spec/app_root/config/database.yml +31 -0
  19. data/spec/app_root/config/environment.rb +30 -0
  20. data/spec/app_root/config/environments/in_memory.rb +0 -0
  21. data/spec/app_root/config/environments/mysql.rb +0 -0
  22. data/spec/app_root/config/environments/postgresql.rb +0 -0
  23. data/spec/app_root/config/environments/sqlite.rb +0 -0
  24. data/spec/app_root/config/environments/sqlite3.rb +0 -0
  25. data/spec/app_root/config/routes.rb +4 -0
  26. data/spec/app_root/lib/blacklight/search_fields.rb +97 -0
  27. data/spec/app_root/lib/console_with_fixtures.rb +4 -0
  28. data/spec/blacklight_to_solr_spec.rb +50 -0
  29. data/spec/data/luke.yaml +75 -0
  30. data/spec/data/zeerex-2.0.xsd +482 -0
  31. data/spec/marc_data/chomsky.mrc +1 -0
  32. data/spec/marc_data/social_journal.mrc +1 -0
  33. data/spec/rcov.opts +2 -0
  34. data/spec/spec.opts +4 -0
  35. data/spec/spec_helper.rb +73 -0
  36. data/spec/views/explain.xml.builder_spec.rb +125 -0
  37. data/tasks/blacklight_cql_tasks.rake +4 -0
  38. data/uninstall.rb +1 -0
  39. metadata +146 -0
@@ -0,0 +1,31 @@
1
+ in_memory:
2
+ adapter: sqlite3
3
+ database: ":memory:"
4
+ verbosity: quiet
5
+ pool: 5
6
+ timeout: 5000
7
+ sqlite:
8
+ adapter: sqlite
9
+ dbfile: plugin_test.sqlite.db
10
+ pool: 5
11
+ timeout: 5000
12
+ sqlite3:
13
+ adapter: sqlite3
14
+ dbfile: plugin_test.sqlite3.db
15
+ pool: 5
16
+ timeout: 5000
17
+ postgresql:
18
+ adapter: postgresql
19
+ username: postgres
20
+ password: postgres
21
+ database: plugin_test
22
+ pool: 5
23
+ timeout: 5000
24
+ mysql:
25
+ adapter: mysql
26
+ host: localhost
27
+ username: root
28
+ password:
29
+ database: plugin_test
30
+ pool: 5
31
+ timeout: 5000
@@ -0,0 +1,30 @@
1
+ require File.join(File.dirname(__FILE__), 'boot')
2
+
3
+ Rails::Initializer.run do |config|
4
+
5
+ config.cache_classes = false
6
+ config.whiny_nils = true
7
+ config.action_controller.session = {:key => 'rails_session', :secret => 'd229e4d22437432705ab3985d4d246'}
8
+ config.plugin_locators.unshift(
9
+ Class.new(Rails::Plugin::Locator) do
10
+ def plugins
11
+ [Rails::Plugin.new(File.expand_path('.'))]
12
+ end
13
+ end
14
+ ) unless defined?(PluginTestHelper::PluginLocator)
15
+
16
+ # jrochkind addition to plugin_test_helper generated rails stub.
17
+ # Adds our plugin code itself to the Rails load path, so it will be
18
+ # auto-loaded. Not entirely sure why plugin_test_helper doesn't do
19
+ # this itself.
20
+ config.load_paths << File.expand_path(File.dirname(__FILE__)+ "../../../../lib")
21
+ config.load_paths << File.expand_path(File.dirname(__FILE__)+ "../../../../app/helpers")
22
+ config.load_paths << File.expand_path(File.dirname(__FILE__)+ "../../../../app/models")
23
+
24
+ # We only get one view path, we want it to be our plugins, not the
25
+ # pseudo-app_root
26
+ config.view_path = File.expand_path(File.dirname(__FILE__)+ "../../../../app/views")
27
+
28
+
29
+
30
+ end
File without changes
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,4 @@
1
+ ActionController::Routing::Routes.draw do |map|
2
+ map.connect ':controller/:action/:id'
3
+ map.connect ':controller/:action/:id.:format'
4
+ end
@@ -0,0 +1,97 @@
1
+ ##
2
+ # Module to deal with accessing (and setting some defaults) in an array of
3
+ # hashes that describe Blacklight search fields. Requires the base class this
4
+ # module is added to implements a #config method that returns a hash, where
5
+ # config[:search_fields] will be an array of hashes describing search fields.
6
+ #
7
+ # = Search Field Configuration Hash =
8
+ # [:display_label]
9
+ # "Title", # user-displayable label
10
+ # [:qt]
11
+ # "search", # Solr qt param, request handler, defaults to Blacklight.config[:default_qt] if left blank.
12
+ # [:solr_parameters]
13
+ # {:qf => "something"} # optional hash of additional parameters to pass to solr for searches on this field.
14
+ # [:solr_local_parameters]
15
+ # {:qf => "$something"} # optional hash of additional parameters that will be passed using Solr LocalParams syntax, that can use dollar sign to reference other solr variables.
16
+ # [:include_in_simple_select]
17
+ # false. Defaults to true, but you can set to false to have a search field defined for deep-links or BL extensions, but not actually included in the HTML select for simple search choice.
18
+ #
19
+ # Optionally you can supply a :key, which is what Blacklight will use
20
+ # to identify this search field in HTTP query params. If no :key is
21
+ # supplied, one will be computed from the :display_label. If that will
22
+ # result in a collision of keys, you should supply one explicitly.
23
+ #
24
+ ##
25
+ module Blacklight::SearchFields
26
+ extend ActiveSupport::Memoizable
27
+
28
+ # Looks up search field config list from config[:search_fields], and
29
+ # 'normalizes' all field config hashes using normalize_config method.
30
+ # Memoized for efficiency of normalization.
31
+ def search_field_list
32
+ config[:search_fields].collect {|obj| normalize_config(obj)}
33
+ end
34
+ memoize :search_field_list
35
+
36
+ # Returns suitable argument to options_for_select method, to create
37
+ # an html select based on #search_field_list. Skips search_fields
38
+ # marked :include_in_simple_select => false
39
+ def search_field_options_for_select
40
+ search_field_list.collect do |field_def|
41
+ [field_def[:display_label], field_def[:key]] unless field_def[:include_in_simple_select] == false
42
+ end.compact
43
+ end
44
+
45
+ # Looks up a search field config hash from search_field_list having
46
+ # a certain supplied :key.
47
+ def search_field_def_for_key(key)
48
+ return nil if key.blank?
49
+ search_field_list.find {|c| c[:key] == key}
50
+ end
51
+
52
+ # Returns default search field, used for simpler display in history, etc.
53
+ # if not set in config, defaults to first field listed in #search_field_list
54
+ def default_search_field
55
+ config[:default_search_field] || search_field_list[0]
56
+ end
57
+ memoize :default_search_field
58
+
59
+ # Shortcut for commonly needed operation, look up display
60
+ # label for the key specified. Returns "Keyword" if a label
61
+ # can't be found.
62
+ def label_for_search_field(key)
63
+ field_def = search_field_def_for_key(key)
64
+ if field_def && field_def[:display_label]
65
+ field_def[:display_label]
66
+ else
67
+ "Keyword"
68
+ end
69
+ end
70
+
71
+ protected
72
+ # Fill in missing default values in a search_field config hash.
73
+ def normalize_config(field_hash)
74
+
75
+
76
+ # Accept legacy two-element array, if it's not a Hash, assume it's legacy.
77
+ # No great way to 'duck type' here.
78
+ unless ( field_hash.kind_of?(Hash))
79
+ # Consistent with legacy behavior where two fields can have the same label,
80
+ # as long as they have different qt's, we base the unique :key on :qt.
81
+ field_hash = {:display_label => field_hash[0], :key => field_hash[1], :qt => field_hash[1]}
82
+ else
83
+ # Make a copy of passed in Hash so we don't alter original.
84
+ field_hash = field_hash.clone
85
+ end
86
+
87
+ # If no key was provided, turn the display label into one.
88
+ field_hash[:key] ||= field_hash[:display_label].downcase.gsub(/[^a-z0-9]+/,'_')
89
+
90
+ # If no :qt was provided, take from config default
91
+ field_hash[:qt] ||= config[:default_qt]
92
+
93
+ field_hash
94
+ end
95
+
96
+
97
+ end
@@ -0,0 +1,4 @@
1
+ # Loads fixtures into the database when running the test app via the console
2
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/) : Dir.glob(File.join(Rails.root, '../fixtures/*.{yml,csv}'))).each do |fixture_file|
3
+ Fixtures.create_fixtures(File.join(Rails.root, '../fixtures'), File.basename(fixture_file, '.*'))
4
+ end
@@ -0,0 +1,50 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+
4
+ describe "blacklight_to_solr" do
5
+ before do
6
+ @config = Class.new do
7
+ include Blacklight::SearchFields
8
+
9
+ def config
10
+ {
11
+ :search_fields => [
12
+ {
13
+ :display_label => "Title",
14
+ :key => "title",
15
+ :solr_parameters => {
16
+ :qf => "ti_something"
17
+ },
18
+ :solr_local_parameters => {
19
+ :pf => "$ti_something"
20
+ }
21
+ },
22
+ {
23
+ :display_label => "Author",
24
+ :key => "author",
25
+ :solr_parameters => {
26
+ :qf => "au_something^10 au_else^100"
27
+ }
28
+ }
29
+
30
+ ]
31
+ }
32
+ end
33
+
34
+ end.new
35
+
36
+ @parser = CqlRuby::CqlParser.new
37
+ end
38
+
39
+ it "should convert to nested queries with local dismax param definitions" do
40
+ output = @parser.parse('title = "foo +bar" AND author = smith OR some_solr_field = frog').to_bl_solr(@config)
41
+
42
+ output.should == "( ( _query_:\"{!dismax qf=ti_something pf=$ti_something} foo +bar \" AND _query_:\"{!dismax qf='au_something^10 au_else^100'} smith \" ) OR some_solr_field:frog )"
43
+ end
44
+
45
+ it "should use default BL config'd search for solr.dismax or '=' relation" do
46
+ output = @parser.parse("cql.serverChoice solr.dismax \"foo bar\"").to_bl_solr(@config)
47
+
48
+ output.should == " _query_:\"{!dismax qf=ti_something pf=$ti_something} foo bar \" "
49
+ end
50
+ end
@@ -0,0 +1,75 @@
1
+ ---
2
+ :fields:
3
+ :subject_unstem_search:
4
+ :schema: IT-M---------
5
+ :type: textNoStem
6
+ :dynamicBase: "*_unstem_search"
7
+ :url_suppl_display:
8
+ :schema: --SM---------
9
+ :type: string
10
+ :dynamicBase: "*_display"
11
+ :timestamp:
12
+ :schema: I-S----O----l
13
+ :type: date
14
+ :title_spell:
15
+ :schema: IT-M---------
16
+ :type: textSpell
17
+ :dynamicBase: "*spell"
18
+ :format:
19
+ :schema: I-SM---O----l
20
+ :type: string
21
+ :subtitle_unstem_search:
22
+ :schema: IT-M---------
23
+ :type: textNoStem
24
+ :dynamicBase: "*_unstem_search"
25
+ :text:
26
+ :schema: IT-M---------
27
+ :type: text
28
+ :author_facet:
29
+ :schema: I--M---O----l
30
+ :type: string
31
+ :dynamicBase: "*_facet"
32
+ :material_type_display:
33
+ :schema: --SM---------
34
+ :type: string
35
+ :dynamicBase: "*_display"
36
+ :isbn_t:
37
+ :schema: ITSM---O-----
38
+ :type: isbn
39
+ :dynamicBase: "*_t"
40
+ :spell:
41
+ :schema: IT-M---------
42
+ :type: textSpell
43
+ :dynamicBase: "*spell"
44
+ :url_fulltext_display:
45
+ :schema: --SM---------
46
+ :type: string
47
+ :dynamicBase: "*_display"
48
+ :info:
49
+ :NOTE: Document Frequency (df) is not updated when a document is marked for deletion. df values include deleted documents.
50
+ :key:
51
+ :V: TermVector Stored
52
+ :L: Lazy
53
+ :l: Sort Missing Last
54
+ :M: Multivalued
55
+ :B: Binary
56
+ :C: Compressed
57
+ :o: Store Offset With TermVector
58
+ :O: Omit Norms
59
+ :p: Store Position With TermVector
60
+ :f: Sort Missing First
61
+ :S: Stored
62
+ :I: Indexed
63
+ :T: Tokenized
64
+ :responseHeader:
65
+ :status: 0
66
+ :QTime: 6
67
+ :index:
68
+ :hasDeletions: false
69
+ :directory: org.apache.lucene.store.:NIOFSDirectory:org.apache.lucene.store.NIOFSDirectory@/usr/share/jetty6/solr/dev/data/index
70
+ :lastModified: "2010-06-:15T14::23:37Z"
71
+ :current: true
72
+ :numDocs: 994
73
+ :version: 1265038861837
74
+ :optimized: true
75
+ :maxDoc: 994