blacklight 4.0.1 → 4.1.0

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. checksums.yaml +6 -6
  2. checksums.yaml.gz.sig +2 -0
  3. data.tar.gz.sig +0 -0
  4. data/.gitignore +1 -0
  5. data/.travis.yml +14 -6
  6. data/Gemfile +2 -3
  7. data/README.md +3 -1
  8. data/VERSION +1 -1
  9. data/app/assets/stylesheets/blacklight/_blacklight_base.css.scss +1 -0
  10. data/app/assets/stylesheets/blacklight/_dropdown.css.scss +2 -1
  11. data/app/assets/stylesheets/blacklight/_search_history.css.scss +1 -1
  12. data/app/assets/stylesheets/blacklight/blacklight.css.scss +2 -0
  13. data/app/assets/stylesheets/improved-modal/bootstrap-modal.css +2 -0
  14. data/app/helpers/blacklight/blacklight_helper_behavior.rb +199 -48
  15. data/app/helpers/blacklight/catalog_helper_behavior.rb +1 -1
  16. data/app/helpers/blacklight/search_history_constraints_helper_behavior.rb +1 -1
  17. data/app/views/catalog/_document_header.html.erb +1 -1
  18. data/app/views/catalog/_index_default.html.erb +3 -3
  19. data/app/views/catalog/_per_page_widget.html.erb +1 -1
  20. data/app/views/catalog/_show_default.html.erb +3 -3
  21. data/app/views/catalog/_sort_widget.html.erb +1 -1
  22. data/app/views/catalog/show.html.erb +29 -32
  23. data/app/views/layouts/blacklight.html.erb +1 -1
  24. data/blacklight.gemspec +1 -1
  25. data/config/locales/blacklight.fr.yml +236 -0
  26. data/gemfiles/rails3.gemfile +9 -0
  27. data/gemfiles/rails4.gemfile +10 -0
  28. data/lib/blacklight/catalog.rb +22 -10
  29. data/lib/blacklight/configurable.rb +2 -3
  30. data/lib/blacklight/configuration/fields.rb +5 -4
  31. data/lib/blacklight/mash.rb +7 -139
  32. data/lib/blacklight/routes.rb +19 -18
  33. data/lib/blacklight/solr_helper.rb +14 -11
  34. data/lib/blacklight/solr_response.rb +1 -1
  35. data/lib/generators/blacklight/blacklight_generator.rb +9 -1
  36. data/lib/generators/blacklight/test_support_generator.rb +15 -0
  37. data/test_support/bin/setup-test-app.sh +8 -12
  38. data/test_support/bin/test.sh +20 -24
  39. data/test_support/features/search.feature +0 -3
  40. data/test_support/features/search_pagination.feature +53 -0
  41. data/test_support/features/step_definitions/search_pagination_steps.rb +29 -0
  42. data/test_support/features/step_definitions/search_steps.rb +0 -11
  43. data/test_support/spec/controllers/catalog_controller_spec.rb +15 -80
  44. data/test_support/spec/helpers/blacklight_helper_spec.rb +75 -22
  45. data/test_support/spec/helpers/catalog_helper_spec.rb +8 -1
  46. data/test_support/spec/helpers/html_head_helper_spec.rb +21 -7
  47. data/test_support/spec/lib/blacklight_configurable_spec.rb +18 -4
  48. data/test_support/spec/lib/blacklight_configuration_spec.rb +28 -0
  49. data/test_support/spec/lib/solr_helper_spec.rb +14 -4
  50. data/test_support/spec/routing/catalog_routing_spec.rb +67 -0
  51. data/test_support/spec/views/catalog/index.atom.builder_spec.rb +3 -7
  52. metadata +42 -15
  53. metadata.gz.sig +0 -0
@@ -6,10 +6,9 @@ module Blacklight::Configurable
6
6
  helper_method :blacklight_config if respond_to? :helper_method
7
7
  end
8
8
 
9
- #instance methods for blacklight_config, default to class
10
- # version unless set specifically on instance
9
+ #instance methods for blacklight_config, so get a deep copy of the class-level config
11
10
  def blacklight_config
12
- @blacklight_config || self.class.blacklight_config
11
+ @blacklight_config ||= self.class.blacklight_config.deep_copy
13
12
  end
14
13
  attr_writer :blacklight_config
15
14
 
@@ -1,6 +1,5 @@
1
1
  module Blacklight
2
2
  class Configuration
3
-
4
3
  # This mixin provides Blacklight::Configuration with generic
5
4
  # solr fields configuration
6
5
  module Fields
@@ -9,14 +8,16 @@ module Blacklight
9
8
  module ClassMethods
10
9
 
11
10
  # Add a configuration block for a collection of solr fields
12
- def define_field_access(key)
11
+ def define_field_access(key, options = {})
13
12
  key = key.to_s if respond_to? :to_s
14
13
 
15
14
  self.default_values[key.pluralize.to_sym] = ActiveSupport::OrderedHash.new
16
15
 
16
+ base_class_name = options.fetch(:class, SolrField)
17
+
17
18
  unless self.const_defined? key.camelcase
18
19
  class_eval <<-END_EVAL, __FILE__, __LINE__ + 1
19
- class #{key.camelcase} < SolrField; end
20
+ class #{key.camelcase} < #{base_class_name}; end
20
21
  END_EVAL
21
22
  end
22
23
 
@@ -70,7 +71,7 @@ module Blacklight
70
71
  when String
71
72
  field_config_from_key_and_hash(config_key, *args)
72
73
  when Symbol
73
- args.first = args.first.to_s
74
+ args[0] = args[0].to_s
74
75
  field_config_from_key_and_hash(config_key, *args)
75
76
  when Array
76
77
  field_config_from_array(config_key, *args)
@@ -1,151 +1,19 @@
1
1
  # This class has dubious semantics and we only have it so that people can write
2
2
  # params[:key] instead of params['key'].
3
- class Mash < Hash
3
+ class Mash < HashWithIndifferentAccess
4
+ def initialize *args, &block
5
+ ActiveSupport::Deprecation.warn("Mash is deprecated, and should be replaced with HashWithIndifferentAccess")
4
6
 
5
- # @param constructor<Object>
6
- # The default value for the mash. Defaults to an empty hash.
7
- #
8
- # @details [Alternatives]
9
- # If constructor is a Hash, a new mash will be created based on the keys of
10
- # the hash and no default value will be set.
11
- def initialize(constructor = {})
12
- if constructor.is_a?(Hash)
13
- super()
14
- update(constructor)
15
- else
16
- super(constructor)
17
- end
18
- end
19
-
20
- # @param key<Object> The default value for the mash. Defaults to nil.
21
- #
22
- # @details [Alternatives]
23
- # If key is a Symbol and it is a key in the mash, then the default value will
24
- # be set to the value matching the key.
25
- def default(key = nil)
26
- if key.is_a?(Symbol) && include?(key = key.to_s)
27
- self[key]
28
- else
29
- super
30
- end
31
- end
32
-
33
- alias_method :regular_writer, :[]= unless method_defined?(:regular_writer)
34
- alias_method :regular_update, :update unless method_defined?(:regular_update)
35
-
36
- # @param key<Object> The key to set.
37
- # @param value<Object>
38
- # The value to set the key to.
39
- #
40
- # @see Mash#convert_key
41
- # @see Mash#convert_value
42
- def []=(key, value)
43
- regular_writer(convert_key(key), convert_value(value))
44
- end
45
-
46
- # @param other_hash<Hash>
47
- # A hash to update values in the mash with. The keys and the values will be
48
- # converted to Mash format.
49
- #
50
- # @return <Mash> The updated mash.
51
- def update(other_hash)
52
- other_hash.each_pair { |key, value| regular_writer(convert_key(key), convert_value(value)) }
53
- self
54
- end
55
-
56
- alias_method :merge!, :update
57
-
58
- # @param key<Object> The key to check for. This will be run through convert_key.
59
- #
60
- # @return <TrueClass, FalseClass> True if the key exists in the mash.
61
- def key?(key)
62
- super(convert_key(key))
63
- end
64
-
65
- # def include? def has_key? def member?
66
- alias_method :include?, :key?
67
- alias_method :has_key?, :key?
68
- alias_method :member?, :key?
69
-
70
- # @param key<Object> The key to fetch. This will be run through convert_key.
71
- # @param *extras<Array> Default value.
72
- #
73
- # @return <Object> The value at key or the default value.
74
- def fetch(key, *extras)
75
- super(convert_key(key), *extras)
76
- end
77
-
78
- # @param *indices<Array>
79
- # The keys to retrieve values for. These will be run through +convert_key+.
80
- #
81
- # @return <Array> The values at each of the provided keys
82
- def values_at(*indices)
83
- indices.collect {|key| self[convert_key(key)]}
84
- end
85
-
86
- # @return <Mash> A duplicate of this mash.
87
- def dup
88
- Mash.new(self)
89
- end
90
-
91
- # @param hash<Hash> The hash to merge with the mash.
92
- #
93
- # @return <Mash> A new mash with the hash values merged in.
94
- def merge(hash)
95
- self.dup.update(hash)
96
- end
97
-
98
- # @param key<Object>
99
- # The key to delete from the mash.\
100
- def delete(key)
101
- super(convert_key(key))
102
- end
103
-
104
- # Used to provide the same interface as Hash.
105
- #
106
- # @return <Mash> This mash unchanged.
107
- def stringify_keys!; self end
108
-
109
- # @return <Hash> The mash as a Hash with string keys.
110
- def to_hash
111
- Hash.new(default).merge(self)
112
- end
113
-
114
- protected
115
- # @param key<Object> The key to convert.
116
- #
117
- # @param <Object>
118
- # The converted key. If the key was a symbol, it will be converted to a
119
- # string.
120
- #
121
- # @api private
122
- def convert_key(key)
123
- key.kind_of?(Symbol) ? key.to_s : key
124
- end
125
-
126
- # @param value<Object> The value to convert.
127
- #
128
- # @return <Object>
129
- # The converted value. A Hash or an Array of hashes, will be converted to
130
- # their Mash equivalents.
131
- #
132
- # @api private
133
- def convert_value(value)
134
- case value
135
- when Hash
136
- value.to_mash
137
- when Array
138
- value.collect { |e| convert_value(e) }
139
- else
140
- value
141
- end
7
+ super
142
8
  end
143
9
  end
144
10
 
145
11
  unless Hash.respond_to?(:to_mash)
146
12
  class Hash
147
13
  def to_mash
148
- Mash.new(self)
14
+ ActiveSupport::Deprecation.warn("Hash#to_mash is deprecated, and should be replaced with #with_indifferent_access")
15
+
16
+ HashWithIndifferentAccess.new(self)
149
17
  end
150
18
  end
151
19
  end
@@ -30,43 +30,44 @@ module Blacklight
30
30
  module RouteSets
31
31
  def bookmarks
32
32
  add_routes do |options|
33
- match "bookmarks/clear", :to => "bookmarks#clear", :as => "clear_bookmarks"
33
+ delete "bookmarks/clear", :to => "bookmarks#clear", :as => "clear_bookmarks"
34
34
  resources :bookmarks
35
35
  end
36
36
  end
37
37
 
38
38
  def search_history
39
39
  add_routes do |options|
40
- match "search_history", :to => "search_history#index", :as => "search_history"
41
- match "search_history/clear", :to => "search_history#clear", :as => "clear_search_history"
40
+ get "search_history", :to => "search_history#index", :as => "search_history"
41
+ delete "search_history/clear", :to => "search_history#clear", :as => "clear_search_history"
42
42
  end
43
43
  end
44
44
 
45
45
 
46
46
  def saved_searches
47
47
  add_routes do |options|
48
- match "saved_searches/clear", :to => "saved_searches#clear", :as => "clear_saved_searches"
49
- match "saved_searches", :to => "saved_searches#index", :as => "saved_searches"
50
- match "saved_searches/save/:id", :to => "saved_searches#save", :as => "save_search"
51
- match "saved_searches/forget/:id", :to => "saved_searches#forget", :as => "forget_search"
48
+ delete "saved_searches/clear", :to => "saved_searches#clear", :as => "clear_saved_searches"
49
+ get "saved_searches", :to => "saved_searches#index", :as => "saved_searches"
50
+ put "saved_searches/save/:id", :to => "saved_searches#save", :as => "save_search"
51
+ delete "saved_searches/forget/:id", :to => "saved_searches#forget", :as => "forget_search"
52
+ post "saved_searches/forget/:id", :to => "saved_searches#forget", :as => "forget_search"
52
53
  end
53
54
  end
54
55
 
55
56
  def catalog
56
57
  add_routes do |options|
57
58
  # Catalog stuff.
58
- match 'catalog/opensearch', :as => "opensearch_catalog"
59
- match 'catalog/citation', :as => "citation_catalog"
60
- match 'catalog/email', :as => "email_catalog"
61
- match 'catalog/sms', :as => "sms_catalog"
62
- match 'catalog/endnote', :as => "endnote_catalog"
63
- match 'catalog/send_email_record', :as => "send_email_record_catalog"
64
- match "catalog/facet/:id", :to => 'catalog#facet', :as => 'catalog_facet'
59
+ get 'catalog/opensearch', :as => "opensearch_catalog"
60
+ get 'catalog/citation', :as => "citation_catalog"
61
+ get 'catalog/email', :as => "email_catalog"
62
+ get 'catalog/sms', :as => "sms_catalog"
63
+ get 'catalog/endnote', :as => "endnote_catalog"
64
+ get 'catalog/send_email_record', :as => "send_email_record_catalog"
65
+ get "catalog/facet/:id", :to => 'catalog#facet', :as => 'catalog_facet'
65
66
 
66
67
 
67
- match "catalog", :to => 'catalog#index', :as => 'catalog_index'
68
+ get "catalog", :to => 'catalog#index', :as => 'catalog_index'
68
69
 
69
- match 'catalog/:id/librarian_view', :to => "catalog#librarian_view", :as => "librarian_view_catalog"
70
+ get 'catalog/:id/librarian_view', :to => "catalog#librarian_view", :as => "librarian_view_catalog"
70
71
  end
71
72
  end
72
73
 
@@ -83,8 +84,8 @@ module Blacklight
83
84
  # Feedback
84
85
  def feedback
85
86
  add_routes do |options|
86
- match "feedback", :to => "feedback#show"
87
- match "feedback/complete", :to => "feedback#complete"
87
+ get "feedback", :to => "feedback#show"
88
+ get "feedback/complete", :to => "feedback#complete"
88
89
  end
89
90
  end
90
91
  end
@@ -84,10 +84,10 @@ module Blacklight::SolrHelper
84
84
 
85
85
  def find(*args)
86
86
  path = blacklight_config.solr_path
87
- response = Blacklight.solr.get(path, :params=> args[1])
87
+ response = blacklight_solr.get(path, :params=> args[1])
88
88
  Blacklight::SolrResponse.new(force_to_utf8(response), args[1])
89
89
  rescue Errno::ECONNREFUSED => e
90
- raise Blacklight::Exceptions::ECONNREFUSED.new("Unable to connect to Solr instance using #{Blacklight.solr.inspect}")
90
+ raise Blacklight::Exceptions::ECONNREFUSED.new("Unable to connect to Solr instance using #{blacklight_solr.inspect}")
91
91
  end
92
92
 
93
93
 
@@ -154,6 +154,7 @@ module Blacklight::SolrHelper
154
154
  end
155
155
 
156
156
  # Now any over-rides from current URL?
157
+ solr_params[:rows] = user_params[:rows].to_i unless user_params[:rows].blank?
157
158
  solr_params[:rows] = user_params[:per_page].to_i unless user_params[:per_page].blank?
158
159
 
159
160
  # Do we need to translate :page to Solr :start?
@@ -166,8 +167,8 @@ module Blacklight::SolrHelper
166
167
  if solr_params[:rows].blank?
167
168
  raise Exception.new("To use pagination when no :per_page is supplied in the URL, :rows must be configured in blacklight_config default_solr_params")
168
169
  end
169
-
170
- solr_params[:page] = user_params[:page].to_i
170
+ solr_params[:start] = solr_params[:rows].to_i * (user_params[:page].to_i - 1)
171
+ solr_params[:start] = 0 if solr_params[:start].to_i < 0
171
172
  end
172
173
 
173
174
  solr_params[:rows] ||= blacklight_config.per_page.first unless blacklight_config.per_page.blank?
@@ -381,14 +382,16 @@ module Blacklight::SolrHelper
381
382
  # In later versions of Rails, the #benchmark method can do timing
382
383
  # better for us.
383
384
  bench_start = Time.now
384
- params = self.solr_search_params(user_params).merge(extra_controller_params)
385
- params[:qt] ||= blacklight_config.qt
385
+ solr_params = self.solr_search_params(user_params).merge(extra_controller_params)
386
+ solr_params[:qt] ||= blacklight_config.qt
386
387
  path = blacklight_config.solr_path
387
- raise "don't set start, use page and rows instead" if params['start'] || params[:start]
388
- rows = params.delete(:rows) #only transmit rows once
389
- res = Blacklight.solr.paginate(params[:page] || 1, rows, path, :params=>params)
390
- solr_response = Blacklight::SolrResponse.new(force_to_utf8(res), params)
391
- Rails.logger.debug("Solr query: #{params.inspect}")
388
+
389
+ # delete these parameters, otherwise rsolr will pass them through.
390
+ res = blacklight_solr.send_and_receive(path, :params=>solr_params)
391
+
392
+ solr_response = Blacklight::SolrResponse.new(force_to_utf8(res), solr_params)
393
+
394
+ Rails.logger.debug("Solr query: #{solr_params.inspect}")
392
395
  Rails.logger.debug("Solr response: #{solr_response.inspect}") if defined?(::BLACKLIGHT_VERBOSE_LOGGING) and ::BLACKLIGHT_VERBOSE_LOGGING
393
396
  Rails.logger.debug("Solr fetch: #{self.class}#query_solr (#{'%.1f' % ((Time.now.to_f - bench_start.to_f)*1000)}ms)")
394
397
 
@@ -1,4 +1,4 @@
1
- class Blacklight::SolrResponse < Mash
1
+ class Blacklight::SolrResponse < HashWithIndifferentAccess
2
2
 
3
3
  autoload :Spelling, 'blacklight/solr_response/spelling'
4
4
  autoload :Facets, 'blacklight/solr_response/facets'
@@ -71,8 +71,16 @@ EOF
71
71
  # Install Devise?
72
72
  def generate_devise_assets
73
73
  if options[:devise]
74
- gem "devise"
74
+ if Rails::VERSION::MAJOR == 4
75
+ gem "devise", github:'plataformatec/devise', branch: 'rails4'
76
+ else
77
+ gem "devise"
78
+ end
79
+
75
80
  gem "devise-guests", "~> 0.3"
81
+ if Rails::VERSION::MAJOR == 4
82
+ gem 'protected_attributes' # Required for devise
83
+ end
76
84
 
77
85
  Bundler.with_clean_env do
78
86
  run "bundle install"
@@ -31,5 +31,20 @@ Requires system('unzip... ') to work, probably won't work on Windows.
31
31
 
32
32
 
33
33
  end
34
+
35
+ def configure_action_mailer
36
+
37
+ if Rails::VERSION::MAJOR == 4
38
+ insert_into_file "config/environments/test.rb", :after => "config.action_mailer.delivery_method = :test\n" do <<-EOF
39
+ config.action_mailer.default_options = {from: 'no-reply@example.org'}
40
+ EOF
41
+ end
42
+ else
43
+ insert_into_file "config/environments/test.rb", :after => "config.action_mailer.delivery_method = :test\n" do <<-EOF
44
+ ActionMailer::Base.default(from: 'no-reply@example.org')
45
+ EOF
46
+ end
47
+ end
48
+ end
34
49
  end
35
50
  end
@@ -89,23 +89,19 @@ end
89
89
  gem 'blacklight', :path => '../../'
90
90
  gem 'jquery-rails'
91
91
 
92
- group :assets do
93
- gem 'compass-rails', '~> 1.0.0'
94
- gem 'compass-susy-plugin', '~> 0.9.0'
95
- end
96
-
97
-
98
92
  # For testing
99
93
  group :development, :test do
100
- gem 'rspec'
101
- gem 'rspec-rails'
94
+ gem 'rspec-rails', '~> 2.12.0'
95
+ end
96
+
97
+ group :test do
98
+ gem 'cucumber-rails', :require => false
102
99
  gem 'generator_spec'
103
- gem 'cucumber-rails'
104
100
  gem 'database_cleaner'
105
101
  gem 'capybara'
106
- gem 'rcov', :platform => :mri_18
107
- gem 'simplecov', :platform => :mri_19
108
- gem 'simplecov-rcov', :platform => :mri_19
102
+ gem 'rcov', :platform => :mri_18
103
+ gem 'simplecov', :platform => :mri_19
104
+ gem 'simplecov-rcov', :platform => :mri_19
109
105
  end
110
106
 
111
107
  gem 'jettywrapper', '>= 1.2.0'
@@ -2,8 +2,7 @@
2
2
  # test.sh
3
3
  # Create a default rails appliaction, install blacklight, and run all the tests.
4
4
 
5
- #If null or empty, use default value
6
- RAILS_VERSION=${RAILS_VERSION:-"~> 3.2"}
5
+ #If null or empty, use default valueRAILS
7
6
  JETTY_URL=${JETTY_URL:-"https://github.com/projectblacklight/blacklight-jetty/zipball/v4.0.0"}
8
7
 
9
8
  before="$(date +%s)"
@@ -38,7 +37,6 @@ rm -rf tmp/test_app
38
37
  mkdir -p tmp/test_app
39
38
  cd tmp
40
39
 
41
-
42
40
  if [[ $# -gt 0 ]]
43
41
  then
44
42
  # Make certain rvm will work correctly.
@@ -58,18 +56,20 @@ rvm use "$@" --create
58
56
  check_errs $? "rvm failed. please run 'rvm install $@', and then re-run these tests."
59
57
  fi
60
58
 
61
- if ! gem query -n rails -v "$RAILS_VERSION" --installed > /dev/null; then
62
- gem install --no-rdoc --no-ri 'rails' -v "$RAILS_VERSION"
63
- fi
59
+ rails new test_app
64
60
 
65
- if ! gem query -n bundler -v ">=1.0" --installed > /dev/null; then
66
- gem install --no-rdoc --no-ri 'bundler'
61
+ cd test_app
62
+
63
+ if [ -e public/index.html ]; then
64
+ rm public/index.html
67
65
  fi
68
66
 
69
- rails new test_app
70
67
 
71
- cd test_app
72
- rm public/index.html
68
+ if [ "${TRAVIS}" = "true" ]; then
69
+ echo "adding utf-8 header for the css under travis"
70
+ echo '@charset "UTF-8";'|cat - app/assets/stylesheets/application.css > app/assets/stylesheets/application.css.utf8 && mv app/assets/stylesheets/application.css.utf8 app/assets/stylesheets/application.css
71
+ fi
72
+
73
73
 
74
74
  echo "
75
75
  platforms :jruby do
@@ -89,27 +89,23 @@ end
89
89
  gem 'blacklight', :path => '../../'
90
90
  gem 'jquery-rails'
91
91
 
92
- group :assets do
93
- gem 'compass-rails', '~> 1.0.0'
94
- gem 'compass-susy-plugin', '~> 0.9.0'
95
- end
96
-
97
-
98
92
  # For testing
99
93
  group :development, :test do
100
- gem 'rspec'
101
- gem 'rspec-rails'
94
+ gem 'rspec-rails', '~> 2.12.0'
95
+ end
96
+
97
+ group :test do
102
98
  gem 'generator_spec'
103
- gem 'cucumber-rails'
104
- gem 'database_cleaner'
99
+ gem 'cucumber-rails', :require => false
100
+ gem 'database_cleaner', '>= 1.0.0.RC1'
105
101
  if defined? :JRUBY_VERSION
106
102
  gem 'capybara', '~> 1.0'
107
103
  else
108
104
  gem 'capybara'
109
105
  end
110
- gem 'rcov', :platform => :mri_18
111
- gem 'simplecov', :platform => :mri_19
112
- gem 'simplecov-rcov', :platform => :mri_19
106
+ gem 'rcov', :platform => :mri_18
107
+ gem 'simplecov', :platform => :mri_19
108
+ gem 'simplecov-rcov', :platform => :mri_19
113
109
  end
114
110
 
115
111
  gem 'jettywrapper', '>= 1.2.0'