blacklight 4.0.1 → 4.1.0

Sign up to get free protection for your applications and to get access to all the features.
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'