supplejack_api 1
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.
- checksums.yaml +7 -0
- data/README.md +80 -0
- data/Rakefile +42 -0
- data/app/assets/javascripts/supplejack_api/application.js +26 -0
- data/app/assets/stylesheets/supplejack_api/application.css +30 -0
- data/app/controllers/supplejack_api/admin/base_controller.rb +24 -0
- data/app/controllers/supplejack_api/admin/sessions_controller.rb +25 -0
- data/app/controllers/supplejack_api/admin/site_activities_controller.rb +21 -0
- data/app/controllers/supplejack_api/admin/users_controller.rb +55 -0
- data/app/controllers/supplejack_api/application_controller.rb +70 -0
- data/app/controllers/supplejack_api/concepts_controller.rb +52 -0
- data/app/controllers/supplejack_api/concerns/ignore_metrics.rb +14 -0
- data/app/controllers/supplejack_api/concerns/records_controller_metrics.rb +26 -0
- data/app/controllers/supplejack_api/concerns/set_items_controller_metrics.rb +20 -0
- data/app/controllers/supplejack_api/concerns/user_sets_controller_metrics.rb +26 -0
- data/app/controllers/supplejack_api/harvester/concepts_controller.rb +41 -0
- data/app/controllers/supplejack_api/harvester/fragments_controller.rb +30 -0
- data/app/controllers/supplejack_api/harvester/records_controller.rb +68 -0
- data/app/controllers/supplejack_api/metrics_api_controller.rb +44 -0
- data/app/controllers/supplejack_api/partners_controller.rb +39 -0
- data/app/controllers/supplejack_api/records_controller.rb +71 -0
- data/app/controllers/supplejack_api/schema_controller.rb +19 -0
- data/app/controllers/supplejack_api/set_items_controller.rb +38 -0
- data/app/controllers/supplejack_api/sources_controller.rb +67 -0
- data/app/controllers/supplejack_api/status_controller.rb +67 -0
- data/app/controllers/supplejack_api/user_sets_controller.rb +97 -0
- data/app/controllers/supplejack_api/users_controller.rb +49 -0
- data/app/helpers/supplejack_api/application_helper.rb +39 -0
- data/app/helpers/supplejack_api/facets_helper.rb +30 -0
- data/app/mailers/supplejack_api/request_limit_mailer.rb +43 -0
- data/app/models/supplejack_api/api_concept/concept_fragment.rb +31 -0
- data/app/models/supplejack_api/api_record/record_fragment.rb +15 -0
- data/app/models/supplejack_api/concept.rb +46 -0
- data/app/models/supplejack_api/concept_search.rb +86 -0
- data/app/models/supplejack_api/concerns/queryable_by_date.rb +31 -0
- data/app/models/supplejack_api/concerns/record.rb +108 -0
- data/app/models/supplejack_api/concerns/record_fragmentable.rb +24 -0
- data/app/models/supplejack_api/concerns/searchable.rb +430 -0
- data/app/models/supplejack_api/concerns/user_set.rb +219 -0
- data/app/models/supplejack_api/daily_metrics.rb +20 -0
- data/app/models/supplejack_api/faceted_metrics.rb +55 -0
- data/app/models/supplejack_api/fragment.rb +82 -0
- data/app/models/supplejack_api/interaction_models/record.rb +60 -0
- data/app/models/supplejack_api/interaction_models/set.rb +13 -0
- data/app/models/supplejack_api/interaction_updaters/all_usage_metric.rb +41 -0
- data/app/models/supplejack_api/interaction_updaters/set_metrics.rb +32 -0
- data/app/models/supplejack_api/interaction_updaters/usage_metrics.rb +73 -0
- data/app/models/supplejack_api/partner.rb +24 -0
- data/app/models/supplejack_api/preview_record.rb +30 -0
- data/app/models/supplejack_api/record.rb +18 -0
- data/app/models/supplejack_api/record_search.rb +12 -0
- data/app/models/supplejack_api/schema_definition.rb +147 -0
- data/app/models/supplejack_api/search.rb +14 -0
- data/app/models/supplejack_api/set_item.rb +57 -0
- data/app/models/supplejack_api/site_activity.rb +59 -0
- data/app/models/supplejack_api/source.rb +28 -0
- data/app/models/supplejack_api/source_activity.rb +36 -0
- data/app/models/supplejack_api/source_authority.rb +42 -0
- data/app/models/supplejack_api/supplejack_schema.rb +37 -0
- data/app/models/supplejack_api/support/concept/searchable.rb +79 -0
- data/app/models/supplejack_api/support/concept/storable.rb +59 -0
- data/app/models/supplejack_api/support/fragment_helpers.rb +96 -0
- data/app/models/supplejack_api/support/harvestable.rb +105 -0
- data/app/models/supplejack_api/support/searchable.rb +115 -0
- data/app/models/supplejack_api/support/status_logger.rb +23 -0
- data/app/models/supplejack_api/support/storable.rb +49 -0
- data/app/models/supplejack_api/support/validation_logger.rb +23 -0
- data/app/models/supplejack_api/usage_metrics.rb +25 -0
- data/app/models/supplejack_api/user.rb +211 -0
- data/app/models/supplejack_api/user_activity.rb +65 -0
- data/app/models/supplejack_api/user_set.rb +17 -0
- data/app/serializers/supplejack_api/application_serializer.rb +12 -0
- data/app/serializers/supplejack_api/concept_record_serializer.rb +23 -0
- data/app/serializers/supplejack_api/concept_search_serializer.rb +12 -0
- data/app/serializers/supplejack_api/concept_serializer.rb +100 -0
- data/app/serializers/supplejack_api/concerns/record_serializable.rb +119 -0
- data/app/serializers/supplejack_api/concerns/search_serializable.rb +24 -0
- data/app/serializers/supplejack_api/record_search_serializer.rb +64 -0
- data/app/serializers/supplejack_api/record_serializer.rb +13 -0
- data/app/serializers/supplejack_api/search_serializer.rb +13 -0
- data/app/serializers/supplejack_api/source_authority_serializer.rb +23 -0
- data/app/serializers/supplejack_api/user_serializer.rb +13 -0
- data/app/serializers/supplejack_api/user_set_record_serializer.rb +14 -0
- data/app/serializers/supplejack_api/user_set_serializer.rb +77 -0
- data/app/services/metrics_api/v3/api.rb +30 -0
- data/app/services/metrics_api/v3/endpoints/facets.rb +23 -0
- data/app/services/metrics_api/v3/endpoints/global.rb +26 -0
- data/app/services/metrics_api/v3/endpoints/helpers.rb +14 -0
- data/app/services/metrics_api/v3/endpoints/root.rb +97 -0
- data/app/services/metrics_api/v3/presenters/daily_metric.rb +23 -0
- data/app/services/metrics_api/v3/presenters/extended_metadata.rb +41 -0
- data/app/services/metrics_api/v3/presenters/record.rb +26 -0
- data/app/services/metrics_api/v3/presenters/view.rb +28 -0
- data/app/views/layouts/supplejack_api/_head.html.erb +17 -0
- data/app/views/layouts/supplejack_api/_top_nav.html.erb +33 -0
- data/app/views/layouts/supplejack_api/application.html.erb +33 -0
- data/app/views/supplejack_api/admin/sessions/new.html.erb +25 -0
- data/app/views/supplejack_api/admin/shared/_links.erb +34 -0
- data/app/views/supplejack_api/admin/site_activities/index.csv.erb +22 -0
- data/app/views/supplejack_api/admin/site_activities/index.html.erb +54 -0
- data/app/views/supplejack_api/admin/users/edit.html.erb +16 -0
- data/app/views/supplejack_api/admin/users/index.csv.erb +22 -0
- data/app/views/supplejack_api/admin/users/index.html.erb +57 -0
- data/app/views/supplejack_api/admin/users/show.html.erb +33 -0
- data/app/views/supplejack_api/request_limit_mailer/at100percent.text.erb +13 -0
- data/app/views/supplejack_api/request_limit_mailer/at100percent_admin.text.erb +1 -0
- data/app/views/supplejack_api/request_limit_mailer/at90percent.text.erb +13 -0
- data/app/views/supplejack_api/request_limit_mailer/at90percent_admin.text.erb +1 -0
- data/app/workers/supplejack_api/daily_metrics_worker.rb +112 -0
- data/app/workers/supplejack_api/interaction_metrics_worker.rb +45 -0
- data/config/cucumber.yml +16 -0
- data/config/initializers/force_eagerload.rb +11 -0
- data/config/initializers/interaction_updaters.rb +7 -0
- data/config/routes.rb +81 -0
- data/db/binding_records.development.json +7 -0
- data/db/binding_records.staging.json +7 -0
- data/db/concepts.json +33 -0
- data/db/concepts_data.json +569745 -0
- data/db/source_authorities.json +119 -0
- data/lib/generators/supplejack_api/install_generator.rb +124 -0
- data/lib/mongoid/paperclip.rb +53 -0
- data/lib/mongoid/string.rb +20 -0
- data/lib/sunspot/mongoid.rb +51 -0
- data/lib/sunspot/resque_session_proxy.rb +72 -0
- data/lib/sunspot/sunspot_spellcheck.rb +98 -0
- data/lib/supplejack_api.rb +13 -0
- data/lib/supplejack_api/admin/sortable.rb +40 -0
- data/lib/supplejack_api/engine.rb +46 -0
- data/lib/supplejack_api/harvester_constraint.rb +28 -0
- data/lib/supplejack_api/stylesheets.rb +36 -0
- data/lib/supplejack_api/utils.rb +75 -0
- data/lib/supplejack_api/version.rb +11 -0
- data/lib/tasks/resque.rake +22 -0
- data/lib/url_validator.rb +38 -0
- data/spec/controllers/supplejack_api/admin/base_controller_spec.rb +55 -0
- data/spec/controllers/supplejack_api/admin/site_activities_controller_spec.rb +43 -0
- data/spec/controllers/supplejack_api/admin/users_controller_spec.rb +79 -0
- data/spec/controllers/supplejack_api/application_controller_spec.rb +133 -0
- data/spec/controllers/supplejack_api/concepts_controller_spec.rb +83 -0
- data/spec/controllers/supplejack_api/concerns/records_controller_metrics_spec.rb +60 -0
- data/spec/controllers/supplejack_api/harvester/concepts_controller_spec.rb +57 -0
- data/spec/controllers/supplejack_api/harvester/records_controller_spec.rb +138 -0
- data/spec/controllers/supplejack_api/metrics_api_controller_spec.rb +71 -0
- data/spec/controllers/supplejack_api/partners_controller_spec.rb +77 -0
- data/spec/controllers/supplejack_api/records_controller_spec.rb +143 -0
- data/spec/controllers/supplejack_api/set_items_controller_spec.rb +78 -0
- data/spec/controllers/supplejack_api/sources_controller_spec.rb +161 -0
- data/spec/controllers/supplejack_api/status_controller_spec.rb +120 -0
- data/spec/controllers/supplejack_api/user_sets_controller_spec.rb +233 -0
- data/spec/controllers/supplejack_api/users_controller_spec.rb +61 -0
- data/spec/dummy/README.rdoc +268 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +23 -0
- data/spec/dummy/app/assets/stylesheets/application.css +22 -0
- data/spec/dummy/app/controllers/application_controller.rb +10 -0
- data/spec/dummy/app/helpers/application_helper.rb +9 -0
- data/spec/dummy/app/supplejack_api/concept_schema.rb +83 -0
- data/spec/dummy/app/supplejack_api/record_schema.rb +64 -0
- data/spec/dummy/app/supplejack_api/record_schema.txt +66 -0
- data/spec/dummy/app/views/layouts/application.html.erb +23 -0
- data/spec/dummy/app/workers/supplejack_api/clear_index_buffer.rb +32 -0
- data/spec/dummy/app/workers/supplejack_api/flush_old_records_worker.rb +17 -0
- data/spec/dummy/app/workers/supplejack_api/index_buffer.rb +49 -0
- data/spec/dummy/app/workers/supplejack_api/index_source_worker.rb +39 -0
- data/spec/dummy/app/workers/supplejack_api/index_worker.rb +82 -0
- data/spec/dummy/app/workers/supplejack_api/store_user_activity_worker.rb +24 -0
- data/spec/dummy/config.ru +11 -0
- data/spec/dummy/config/application.rb +76 -0
- data/spec/dummy/config/application.yml +31 -0
- data/spec/dummy/config/application.yml.example +36 -0
- data/spec/dummy/config/boot.rb +17 -0
- data/spec/dummy/config/environment.rb +12 -0
- data/spec/dummy/config/environments/development.rb +42 -0
- data/spec/dummy/config/environments/production.rb +76 -0
- data/spec/dummy/config/environments/test.rb +46 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +14 -0
- data/spec/dummy/config/initializers/devise.rb +214 -0
- data/spec/dummy/config/initializers/inflections.rb +22 -0
- data/spec/dummy/config/initializers/kaminari_config.rb +17 -0
- data/spec/dummy/config/initializers/mime_types.rb +12 -0
- data/spec/dummy/config/initializers/mongoid.rb +9 -0
- data/spec/dummy/config/initializers/quiet_logger.rb +23 -0
- data/spec/dummy/config/initializers/resque.rb +18 -0
- data/spec/dummy/config/initializers/secret_token.rb +14 -0
- data/spec/dummy/config/initializers/session_store.rb +15 -0
- data/spec/dummy/config/initializers/simple_form.rb +149 -0
- data/spec/dummy/config/initializers/simple_form_foundation.rb +33 -0
- data/spec/dummy/config/initializers/state_machine.rb +8 -0
- data/spec/dummy/config/initializers/sunspot.rb +32 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +17 -0
- data/spec/dummy/config/locales/devise.en.yml +63 -0
- data/spec/dummy/config/locales/en.yml +66 -0
- data/spec/dummy/config/locales/simple_form.en.yml +33 -0
- data/spec/dummy/config/mongoid.travis.yml +34 -0
- data/spec/dummy/config/mongoid.yml +36 -0
- data/spec/dummy/config/resque-pool.yml +18 -0
- data/spec/dummy/config/resque_schedule.yml +12 -0
- data/spec/dummy/config/routes.rb +11 -0
- data/spec/dummy/config/secrets.yml +8 -0
- data/spec/dummy/config/sunspot.yml +38 -0
- data/spec/dummy/db/concepts.json +37 -0
- data/spec/dummy/db/source_authorities.json +116 -0
- data/spec/dummy/public/404.html +35 -0
- data/spec/dummy/public/422.html +35 -0
- data/spec/dummy/public/500.html +34 -0
- data/spec/dummy/public/favicon.ico +8 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/solr/collection1/conf/elevate.xml +36 -0
- data/spec/dummy/solr/collection1/conf/mapping-FoldToASCII.txt +3813 -0
- data/spec/dummy/solr/collection1/conf/schema.xml +292 -0
- data/spec/dummy/solr/collection1/conf/solrconfig.xml +1780 -0
- data/spec/dummy/solr/collection1/conf/spellings.txt +2 -0
- data/spec/dummy/solr/collection1/conf/stopwords.txt +58 -0
- data/spec/dummy/solr/collection1/conf/synonyms.txt +31 -0
- data/spec/factories/concepts.rb +16 -0
- data/spec/factories/daily_metrics.rb +10 -0
- data/spec/factories/faceted_metrics.rb +25 -0
- data/spec/factories/fragment.rb +14 -0
- data/spec/factories/partners.rb +14 -0
- data/spec/factories/record_interaction.rb +17 -0
- data/spec/factories/records.rb +47 -0
- data/spec/factories/set_interaction.rb +15 -0
- data/spec/factories/source_authorities.rb +19 -0
- data/spec/factories/sources.rb +16 -0
- data/spec/factories/usage_metrics.rb +20 -0
- data/spec/factories/user_activities.rb +14 -0
- data/spec/factories/user_sets.rb +27 -0
- data/spec/factories/users.rb +23 -0
- data/spec/helpers/application_helper_spec.rb +35 -0
- data/spec/models/concept_spec.rb +163 -0
- data/spec/models/fragment_spec.rb +15 -0
- data/spec/models/site_activity_spec.rb +103 -0
- data/spec/models/source_activity_spec.rb +56 -0
- data/spec/models/source_authority_spec.rb +42 -0
- data/spec/models/supplejack_api/api_concept/concept_fragment_spec.rb +189 -0
- data/spec/models/supplejack_api/api_record/record_fragment_spec.rb +189 -0
- data/spec/models/supplejack_api/concept_spec.rb +0 -0
- data/spec/models/supplejack_api/interaction_updaters/all_usage_metric_spec.rb +41 -0
- data/spec/models/supplejack_api/interaction_updaters/set_metrics_spec.rb +32 -0
- data/spec/models/supplejack_api/interaction_updaters/usage_metrics_spec.rb +44 -0
- data/spec/models/supplejack_api/partner_spec.rb +20 -0
- data/spec/models/supplejack_api/record_search_spec.rb +429 -0
- data/spec/models/supplejack_api/record_spec.rb +280 -0
- data/spec/models/supplejack_api/schema_definition_spec.rb +272 -0
- data/spec/models/supplejack_api/search_spec.rb +243 -0
- data/spec/models/supplejack_api/set_item_spec.rb +123 -0
- data/spec/models/supplejack_api/source_spec.rb +22 -0
- data/spec/models/supplejack_api/support/fragment_helpers_spec.rb +216 -0
- data/spec/models/supplejack_api/support/harvestable_spec.rb +177 -0
- data/spec/models/supplejack_api/support/searchable_spec.rb +85 -0
- data/spec/models/supplejack_api/support/storable_spec.rb +18 -0
- data/spec/models/supplejack_api/user_activity_spec.rb +88 -0
- data/spec/models/supplejack_api/user_set_spec.rb +559 -0
- data/spec/models/supplejack_api/user_spec.rb +348 -0
- data/spec/routing/concepts_routing_spec.rb +22 -0
- data/spec/routing/harvester_constraint_spec.rb +66 -0
- data/spec/routing/harvester_routing_spec.rb +51 -0
- data/spec/routing/partner_routing_spec.rb +34 -0
- data/spec/routing/records_routing_spec.rb +26 -0
- data/spec/routing/sets_routing_spec.rb +44 -0
- data/spec/routing/source_routing_spec.rb +38 -0
- data/spec/routing/users_routing_spec.rb +18 -0
- data/spec/serializers/concept_record_serializer_spec.rb +30 -0
- data/spec/serializers/supplejack_api/application_serializer_spec.rb +14 -0
- data/spec/serializers/supplejack_api/concept_search_serializer_spec.rb +34 -0
- data/spec/serializers/supplejack_api/concept_serializer_spec.rb +92 -0
- data/spec/serializers/supplejack_api/record_search_serializer_spec.rb +34 -0
- data/spec/serializers/supplejack_api/record_serializer_spec.rb +271 -0
- data/spec/serializers/supplejack_api/search_serializer_spec.rb +90 -0
- data/spec/serializers/supplejack_api/user_serializer_spec.rb +22 -0
- data/spec/serializers/supplejack_api/user_set_serializer_spec.rb +96 -0
- data/spec/services/metrics_api/v3/api_spec.rb +23 -0
- data/spec/services/metrics_api/v3/endpoints/facets_spec.rb +25 -0
- data/spec/services/metrics_api/v3/endpoints/global_spec.rb +22 -0
- data/spec/services/metrics_api/v3/endpoints/root_spec.rb +49 -0
- data/spec/services/metrics_api/v3/presenters/extended_metadata_spec.rb +49 -0
- data/spec/spec_helper.rb +70 -0
- data/spec/support/api/schemas/metrics/daily_metrics_metadata.json +24 -0
- data/spec/support/api/schemas/metrics/extended_metrics.json +26 -0
- data/spec/support/api/schemas/metrics/extended_response.json +6 -0
- data/spec/support/api/schemas/metrics/facets_response.json +6 -0
- data/spec/support/api/schemas/metrics/record_metadata.json +33 -0
- data/spec/support/api/schemas/metrics/top_level_response.json +6 -0
- data/spec/support/api/schemas/metrics/view_metadata.json +33 -0
- data/spec/support/api_schema_matcher.rb +14 -0
- data/spec/support/devise.rb +10 -0
- data/spec/workers/supplejack_api/daily_metrics_worker_spec.rb +140 -0
- data/spec/workers/supplejack_api/flush_old_records_worker_spec.rb +20 -0
- data/spec/workers/supplejack_api/index_worker_spec.rb +52 -0
- data/spec/workers/supplejack_api/source_index_worker_spec.rb +61 -0
- metadata +1231 -0
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
|
3
|
+
# and is licensed under the GNU General Public License, version 3.
|
4
|
+
# One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
|
5
|
+
#
|
6
|
+
# Supplejack was created by DigitalNZ at the National Library of NZ and
|
7
|
+
# the Department of Internal Affairs. http://digitalnz.org/supplejack
|
8
|
+
|
9
|
+
module SupplejackApi
|
10
|
+
class Concept
|
11
|
+
include Support::Concept::Storable
|
12
|
+
include Support::Concept::Searchable
|
13
|
+
include ActiveModel::SerializerSupport
|
14
|
+
|
15
|
+
def self.build_context(fields)
|
16
|
+
context = {}
|
17
|
+
namespaces = []
|
18
|
+
|
19
|
+
fields.each do |field|
|
20
|
+
namespaces << ConceptSchema.model_fields[field].try(:namespace)
|
21
|
+
end
|
22
|
+
|
23
|
+
namespaces.compact.uniq.each do |namespace|
|
24
|
+
context[namespace] = ConceptSchema.namespaces[namespace].url
|
25
|
+
namespaced_fields = ConceptSchema.fields.select { |_key, field| field.namespace == namespace }
|
26
|
+
namespaced_fields.each do |name, field|
|
27
|
+
if fields.include?(name) && name != field.namespace
|
28
|
+
context[name] = "#{field.namespace}:#{field.namespace_field}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
# Manually build context for concept_id
|
34
|
+
context[:dcterms] = ConceptSchema.namespaces[:dcterms].url
|
35
|
+
context[:concept_id] = {}
|
36
|
+
context[:concept_id]['@id'] = 'dcterms:identifier'
|
37
|
+
|
38
|
+
fields.each do |field|
|
39
|
+
context[field] = {}
|
40
|
+
namespace = ConceptSchema.model_fields[field].try(:namespace)
|
41
|
+
context[field]['@id'] = "#{namespace}:#{field}"
|
42
|
+
end
|
43
|
+
context
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
|
3
|
+
# and is licensed under the GNU General Public License, version 3.
|
4
|
+
# One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
|
5
|
+
#
|
6
|
+
# Supplejack was created by DigitalNZ at the National Library of NZ and
|
7
|
+
# the Department of Internal Affairs. http://digitalnz.org/supplejack
|
8
|
+
|
9
|
+
module SupplejackApi
|
10
|
+
class ConceptSearch < Search
|
11
|
+
def initialize(options = {})
|
12
|
+
@options = options.dup
|
13
|
+
@options.reverse_merge!(
|
14
|
+
and: {},
|
15
|
+
or: {},
|
16
|
+
without: {},
|
17
|
+
page: 1,
|
18
|
+
per_page: 20,
|
19
|
+
sort: nil,
|
20
|
+
direction: 'desc',
|
21
|
+
fields: ConceptSchema.model_fields.keys.join(','),
|
22
|
+
debug: nil
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
# FIXME: make me smaller!
|
27
|
+
def search_builder
|
28
|
+
@search_builder ||= Sunspot.new_search(SupplejackApi::Concept) do
|
29
|
+
spellcheck collate: true, only_more_popular: true if options[:suggest]
|
30
|
+
|
31
|
+
options[:without].each do |name, values|
|
32
|
+
values = values.split(',')
|
33
|
+
values.each do |value|
|
34
|
+
without(name, to_proper_value(name, value))
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
if options[:geo_bbox]
|
39
|
+
coords = options[:geo_bbox].split(',').map(&:to_f)
|
40
|
+
with(:lat_lng).in_bounding_box([coords[2], coords[1]], [coords[0], coords[3]])
|
41
|
+
end
|
42
|
+
|
43
|
+
adjust_solr_params do |params|
|
44
|
+
if options[:solr_query].present?
|
45
|
+
params[:q] ||= ''
|
46
|
+
params['q.alt'] = options[:solr_query]
|
47
|
+
params[:defType] = 'dismax'
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
order_by(sort, direction) if options[:sort].present?
|
52
|
+
|
53
|
+
paginate page: page, per_page: per_page
|
54
|
+
end
|
55
|
+
|
56
|
+
@search_builder.build(&build_conditions)
|
57
|
+
@search_builder
|
58
|
+
end
|
59
|
+
# rubocop:enable Metrics/MethodLength
|
60
|
+
|
61
|
+
def query_fields
|
62
|
+
query_fields_list = super
|
63
|
+
query_fields_list += [:name, :label] if (query_fields_list && [:name, :label]).present?
|
64
|
+
end
|
65
|
+
|
66
|
+
def field_list
|
67
|
+
return @field_list if @field_list
|
68
|
+
model_fields = ConceptSchema.model_fields.dup
|
69
|
+
valid_fields = model_fields.keep_if { |_key, field| field.try(:store).nil? }
|
70
|
+
|
71
|
+
@field_list = options[:fields].split(',').map { |f| f.strip.tr(':', '_').to_sym }
|
72
|
+
@field_list.keep_if do |f|
|
73
|
+
valid_fields.include?(f)
|
74
|
+
end
|
75
|
+
|
76
|
+
@field_list
|
77
|
+
end
|
78
|
+
|
79
|
+
def group_list
|
80
|
+
return @group_list if @group_list
|
81
|
+
@group_list = options[:fields].split(',').map { |f| f.strip.to_sym }
|
82
|
+
@group_list.keep_if { |f| ConceptSchema.groups.keys.include?(f) }
|
83
|
+
@group_list
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# The majority of the Supplejack API code is Crown copyright (C) 2014, New Zealand Government,
|
3
|
+
# and is licensed under the GNU General Public License, version 3.
|
4
|
+
# One component is a third party component. See https://github.com/DigitalNZ/supplejack_api for details.
|
5
|
+
#
|
6
|
+
# Supplejack was created by DigitalNZ at the National Library of NZ and
|
7
|
+
# the Department of Internal Affairs. http://digitalnz.org/supplejack
|
8
|
+
|
9
|
+
module SupplejackApi
|
10
|
+
module Concerns
|
11
|
+
# Contains convenience methods for querying documents by their day field
|
12
|
+
# This concern assumes documents have the field 'day' of type +Date+
|
13
|
+
module QueryableByDate
|
14
|
+
extend ActiveSupport::Concern
|
15
|
+
|
16
|
+
included do
|
17
|
+
index date: 1
|
18
|
+
end
|
19
|
+
|
20
|
+
module ClassMethods
|
21
|
+
def created_on(date)
|
22
|
+
where(:date.gte => date.at_beginning_of_day, :date.lte => date.at_end_of_day)
|
23
|
+
end
|
24
|
+
|
25
|
+
def created_between(start_date, end_date)
|
26
|
+
where(:date.gte => start_date, :date.lte => end_date)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module SupplejackApi::Concerns::Record
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
attr_accessor :next_record, :previous_record, :next_page, :previous_page
|
7
|
+
attr_accessor :should_index_flag
|
8
|
+
|
9
|
+
# Associations
|
10
|
+
embeds_many :fragments, cascade_callbacks: true, class_name: 'SupplejackApi::ApiRecord::RecordFragment'
|
11
|
+
embeds_one :merged_fragment, class_name: 'SupplejackApi::ApiRecord::RecordFragment'
|
12
|
+
has_and_belongs_to_many :concepts, class_name: 'SupplejackApi::Concept'
|
13
|
+
|
14
|
+
# From storable
|
15
|
+
store_in collection: 'records'
|
16
|
+
index(concept_ids: 1)
|
17
|
+
index({ record_id: 1 }, unique: true)
|
18
|
+
auto_increment :record_id, session: 'strong'
|
19
|
+
|
20
|
+
# Callbacks
|
21
|
+
before_save :merge_fragments
|
22
|
+
|
23
|
+
# Scopes
|
24
|
+
scope :active, -> { where(status: 'active') }
|
25
|
+
scope :deleted, -> { where(status: 'deleted') }
|
26
|
+
scope :suppressed, -> { where(status: 'suppressed') }
|
27
|
+
scope :solr_rejected, -> { where(status: 'solr_rejected') }
|
28
|
+
|
29
|
+
build_model_fields
|
30
|
+
|
31
|
+
def self.created_on(date)
|
32
|
+
where(:created_at.gte => date.at_beginning_of_day, :created_at.lte => date.at_end_of_day)
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.find_multiple(ids)
|
36
|
+
return [] unless ids.try(:any?)
|
37
|
+
string_ids = ids.find_all { |id| id.to_s.length > 10 }
|
38
|
+
integer_ids = ids.find_all { |id| id.to_s.length <= 10 }
|
39
|
+
|
40
|
+
records = []
|
41
|
+
records += active.find(string_ids) if string_ids.present?
|
42
|
+
records += active.where(:record_id.in => integer_ids)
|
43
|
+
records = records.sort_by { |r| ids.find_index(r.record_id) || 100 }
|
44
|
+
end
|
45
|
+
|
46
|
+
# rubocop:disable Metrics/MethodLength
|
47
|
+
# FIXME: make me smaller!
|
48
|
+
def find_next_and_previous_records(scope, options = {})
|
49
|
+
return unless options.try(:any?)
|
50
|
+
|
51
|
+
search = ::SupplejackApi::RecordSearch.new(options)
|
52
|
+
search.scope = scope
|
53
|
+
|
54
|
+
return nil unless search.valid?
|
55
|
+
|
56
|
+
# Find the index in the array for the current record
|
57
|
+
record_index = search.hits.find_index { |i| i.primary_key == id.to_s }
|
58
|
+
total_pages = (search.total.to_f / search.per_page).ceil
|
59
|
+
|
60
|
+
self.next_page = search.page
|
61
|
+
self.previous_page = search.page
|
62
|
+
|
63
|
+
return unless record_index
|
64
|
+
|
65
|
+
if record_index.zero?
|
66
|
+
unless search.page == 1
|
67
|
+
previous_page_search = ::SupplejackApi::RecordSearch.new(options.merge(page: search.page - 1))
|
68
|
+
previous_primary_key = previous_page_search.hits[-1].try(:primary_key)
|
69
|
+
self.previous_page = search.page - 1
|
70
|
+
end
|
71
|
+
else
|
72
|
+
previous_primary_key = search.hits[record_index - 1].try(:primary_key)
|
73
|
+
end
|
74
|
+
|
75
|
+
if previous_primary_key.present?
|
76
|
+
self.previous_record = SupplejackApi::Record.find(previous_primary_key).try(:record_id) rescue nil
|
77
|
+
end
|
78
|
+
|
79
|
+
if record_index == search.hits.size - 1
|
80
|
+
unless search.page >= total_pages
|
81
|
+
next_page_search = ::SupplejackApi::RecordSearch.new(options.merge(page: search.page + 1))
|
82
|
+
next_primary_key = next_page_search.hits[0].try(:primary_key)
|
83
|
+
self.next_page = search.page + 1
|
84
|
+
end
|
85
|
+
else
|
86
|
+
next_primary_key = search.hits[record_index + 1].try(:primary_key)
|
87
|
+
end
|
88
|
+
|
89
|
+
return unless next_primary_key.present?
|
90
|
+
|
91
|
+
self.next_record = ::SupplejackApi::Record.find(next_primary_key).try(:record_id) rescue nil
|
92
|
+
end
|
93
|
+
# rubocop:enable Metrics/MethodLength
|
94
|
+
|
95
|
+
def active?
|
96
|
+
status == 'active'
|
97
|
+
end
|
98
|
+
|
99
|
+
def should_index?
|
100
|
+
return should_index_flag unless should_index_flag.nil?
|
101
|
+
active?
|
102
|
+
end
|
103
|
+
|
104
|
+
def fragment_class
|
105
|
+
SupplejackApi::ApiRecord::RecordFragment
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module SupplejackApi::Concerns::RecordFragmentable
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
included do
|
6
|
+
embedded_in :record
|
7
|
+
|
8
|
+
delegate :record_id, to: :record
|
9
|
+
|
10
|
+
def self.schema_class
|
11
|
+
RecordSchema
|
12
|
+
end
|
13
|
+
|
14
|
+
build_mongoid_schema
|
15
|
+
|
16
|
+
def self.mutable_fields
|
17
|
+
@@mutable_fields ||= begin
|
18
|
+
immutable_fields = %w(_id _type source_id created_at updated_at)
|
19
|
+
mutable_fields = fields.keys - immutable_fields
|
20
|
+
Hash[mutable_fields.map { |name| [name, fields[name].type] }]
|
21
|
+
end.freeze
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,430 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
# rubocop:disable Metrics/ModuleLength
|
3
|
+
module SupplejackApi::Concerns::Searchable
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
INTEGER_ATTRIBUTES ||= [:page, :per_page, :facets_per_page, :facets_page, :record_type].freeze
|
8
|
+
|
9
|
+
attr_accessor :options, :request_url, :scope, :solr_request_params, :errors, :warnings
|
10
|
+
|
11
|
+
class_attribute :max_values
|
12
|
+
|
13
|
+
self.max_values = {
|
14
|
+
page: 100_000,
|
15
|
+
per_page: 100,
|
16
|
+
facets_per_page: 150,
|
17
|
+
facets_page: 5000
|
18
|
+
}
|
19
|
+
|
20
|
+
def initialize(options = {})
|
21
|
+
@options = options.dup
|
22
|
+
@options.reverse_merge!(
|
23
|
+
facets: '',
|
24
|
+
and: {},
|
25
|
+
or: {},
|
26
|
+
without: {},
|
27
|
+
page: 1,
|
28
|
+
per_page: 20,
|
29
|
+
record_type: 0,
|
30
|
+
facets_per_page: 10,
|
31
|
+
facets_page: 1,
|
32
|
+
sort: nil,
|
33
|
+
direction: 'desc',
|
34
|
+
fields: 'default',
|
35
|
+
facet_query: {},
|
36
|
+
debug: nil
|
37
|
+
)
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.model_class
|
41
|
+
to_s.gsub(/Search/, '').constantize
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.schema_class
|
45
|
+
"#{model_class.to_s.demodulize}Schema".constantize
|
46
|
+
end
|
47
|
+
|
48
|
+
# The records that match the criteria within each role will be removed
|
49
|
+
# from the search results
|
50
|
+
#
|
51
|
+
def self.role_collection_restrictions(scope)
|
52
|
+
restrictions = []
|
53
|
+
|
54
|
+
if scope
|
55
|
+
role = scope.role.try(:to_sym)
|
56
|
+
if schema_class.roles[role].record_restrictions
|
57
|
+
restrictions = schema_class.roles[role].record_restrictions
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
restrictions
|
62
|
+
end
|
63
|
+
|
64
|
+
# rubocop:disable Metrics/MethodLength
|
65
|
+
# rubocop:disable Metrics/AbcSize
|
66
|
+
# FIXME: Make this method smaller, it's triple the max method length
|
67
|
+
def search_builder
|
68
|
+
search_model = self
|
69
|
+
|
70
|
+
@search_builder ||= Sunspot.new_search(search_model.class.model_class) do
|
71
|
+
with(:record_type, record_type) unless options[:record_type] == 'all'
|
72
|
+
|
73
|
+
search_model.facet_list.each do |facet_name|
|
74
|
+
facet(facet_name, limit: facets_per_page, offset: facets_offset)
|
75
|
+
end
|
76
|
+
|
77
|
+
spellcheck collate: true, only_more_popular: true if options[:suggest]
|
78
|
+
|
79
|
+
options[:without].each do |name, values|
|
80
|
+
values = values.split(',')
|
81
|
+
values.each do |value|
|
82
|
+
without(name, to_proper_value(name, value))
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
if options[:geo_bbox]
|
87
|
+
coords = options[:geo_bbox].split(',').map(&:to_f)
|
88
|
+
with(:lat_lng).in_bounding_box([coords[2], coords[1]], [coords[0], coords[3]])
|
89
|
+
end
|
90
|
+
|
91
|
+
adjust_solr_params do |params|
|
92
|
+
if options[:solr_query].present?
|
93
|
+
params[:q] ||= ''
|
94
|
+
params['q.alt'] = options[:solr_query]
|
95
|
+
params[:defType] = 'dismax'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# Facet Queries
|
100
|
+
#
|
101
|
+
# The facet query parameter should have the following format:
|
102
|
+
#
|
103
|
+
# facet_query: {images: {"creator" => "all"}, headings: {"record_type" => 1}}
|
104
|
+
#
|
105
|
+
# - Each key in the top level hash will be the name of each facet row returned.
|
106
|
+
# - Each value in the top level hash is a hash similar with all the restrictions
|
107
|
+
#
|
108
|
+
|
109
|
+
if options[:facet_query].any?
|
110
|
+
facet(:counts) do
|
111
|
+
options[:facet_query].each_pair do |row_name, filters_hash|
|
112
|
+
row(row_name.to_s) do
|
113
|
+
filters_hash.each_pair do |filter, value|
|
114
|
+
if value == 'all'
|
115
|
+
without(filter.to_sym, nil)
|
116
|
+
elsif filter =~ /-(.+)/
|
117
|
+
without(Regexp.last_match(1).to_sym, to_proper_value(filter, value))
|
118
|
+
else
|
119
|
+
if value.is_a?(Array)
|
120
|
+
with(filter.to_sym).all_of(value)
|
121
|
+
else
|
122
|
+
with(filter.to_sym, to_proper_value(filter, value))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
order_by(sort, direction) if options[:sort].present?
|
132
|
+
|
133
|
+
search_model.class.role_collection_restrictions(search_model.scope).each do |field, values|
|
134
|
+
without(field.to_sym, values)
|
135
|
+
end
|
136
|
+
|
137
|
+
SupplejackApi::Source.suppressed.each do |source|
|
138
|
+
without(:source_id, source.source_id)
|
139
|
+
end
|
140
|
+
|
141
|
+
paginate page: page, per_page: per_page
|
142
|
+
end
|
143
|
+
|
144
|
+
@search_builder.build(&build_conditions)
|
145
|
+
|
146
|
+
@search_builder
|
147
|
+
end
|
148
|
+
# rubocop:enable Metrics/AbcSize
|
149
|
+
# rubocop:enable Metrics/MethodLength
|
150
|
+
|
151
|
+
# Return an array of valid facets
|
152
|
+
# It will remove any invalid facets in order to avoid Solr errors
|
153
|
+
#
|
154
|
+
def facet_list
|
155
|
+
return @facet_list if @facet_list
|
156
|
+
|
157
|
+
@facet_list = options[:facets].split(',').map { |f| f.strip.to_sym }
|
158
|
+
@facet_list.keep_if { |f| self.class.model_class.valid_facets.include?(f) }
|
159
|
+
@facet_list
|
160
|
+
end
|
161
|
+
|
162
|
+
def field_list
|
163
|
+
return @field_list if @field_list
|
164
|
+
valid_fields = self.class.schema_class.fields.keys.dup
|
165
|
+
|
166
|
+
@field_list = options[:fields].split(',').map { |f| f.strip.tr(':', '_').to_sym }
|
167
|
+
@field_list.delete_if do |f|
|
168
|
+
!valid_fields.include?(f)
|
169
|
+
end
|
170
|
+
|
171
|
+
@field_list
|
172
|
+
end
|
173
|
+
|
174
|
+
# Returns the facets part of the search results converted to a hash
|
175
|
+
#
|
176
|
+
# @return [Hash] facets in hash form, each facet is respresented as +facet_name => facet_values+
|
177
|
+
def facets_hash
|
178
|
+
facets = {}
|
179
|
+
|
180
|
+
self.facets.each do |facet|
|
181
|
+
rows = {}
|
182
|
+
facet.rows.each do |row|
|
183
|
+
rows[row.value] = row.count
|
184
|
+
end
|
185
|
+
|
186
|
+
facets.merge!(facet.name => rows)
|
187
|
+
end
|
188
|
+
|
189
|
+
facets
|
190
|
+
end
|
191
|
+
|
192
|
+
# Returns all valid groups of fields
|
193
|
+
# The groups are extracted from the "fields" parameter
|
194
|
+
#
|
195
|
+
def group_list
|
196
|
+
return @group_list if @group_list
|
197
|
+
@group_list = options[:fields].split(',').map { |f| f.strip.to_sym }
|
198
|
+
@group_list.keep_if { |f| self.class.model_class.valid_groups.include?(f) }
|
199
|
+
@group_list
|
200
|
+
end
|
201
|
+
|
202
|
+
def query_fields
|
203
|
+
query_field_list = nil
|
204
|
+
|
205
|
+
if options[:query_fields].is_a?(String)
|
206
|
+
query_field_list = options[:query_fields].split(',').map(&:strip).map(&:to_sym)
|
207
|
+
elsif options[:query_fields].is_a?(Array)
|
208
|
+
query_field_list = options[:query_fields].map(&:to_sym)
|
209
|
+
end
|
210
|
+
|
211
|
+
return nil if query_field_list.try(:empty?)
|
212
|
+
query_field_list
|
213
|
+
end
|
214
|
+
|
215
|
+
def extract_range(value)
|
216
|
+
if value =~ /^\[(\d+)\sTO\s(\d+)\]$/
|
217
|
+
Regexp.last_match(1).to_i..Regexp.last_match(2).to_i
|
218
|
+
else
|
219
|
+
value.to_i.positive? ? value.to_i : value.strip
|
220
|
+
end
|
221
|
+
end
|
222
|
+
|
223
|
+
def to_proper_value(_name, value)
|
224
|
+
return false if value == 'false'
|
225
|
+
return true if value == 'true'
|
226
|
+
return nil if %w(nil null).include?(value)
|
227
|
+
|
228
|
+
value = value.strip if value.is_a?(String)
|
229
|
+
value
|
230
|
+
end
|
231
|
+
|
232
|
+
# Downcase all queries before sending to SOLR, except queries
|
233
|
+
# which have specific lucene syntax.
|
234
|
+
#
|
235
|
+
def text
|
236
|
+
@text = options[:text]
|
237
|
+
if @text.present? && !@text.match(/:\"/)
|
238
|
+
@text.downcase!
|
239
|
+
@text.gsub!(/ and | or | not /, &:upcase)
|
240
|
+
end
|
241
|
+
@text
|
242
|
+
end
|
243
|
+
|
244
|
+
def offset
|
245
|
+
(page * per_page) - per_page
|
246
|
+
end
|
247
|
+
|
248
|
+
def facets_offset
|
249
|
+
offset = (facets_page * facets_per_page) - facets_per_page
|
250
|
+
offset.negative? ? 0 : offset
|
251
|
+
end
|
252
|
+
|
253
|
+
def valid?
|
254
|
+
self.errors ||= []
|
255
|
+
self.warnings ||= []
|
256
|
+
self.class.max_values.each do |attribute, max_value|
|
257
|
+
max_value = self.class.max_values[attribute]
|
258
|
+
if @options[attribute].to_i > max_value
|
259
|
+
self.warnings << "The #{attribute} parameter can not exceed #{max_value}"
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
solr_search_object
|
264
|
+
self.errors.empty?
|
265
|
+
end
|
266
|
+
|
267
|
+
def records
|
268
|
+
solr_search_object.results
|
269
|
+
end
|
270
|
+
|
271
|
+
def jsonp
|
272
|
+
@options[:jsonp].present? ? @options[:jsonp] : nil
|
273
|
+
end
|
274
|
+
|
275
|
+
# It's currently required to make the active_model_serializers gem to work with XML
|
276
|
+
# The XML Serialization is handled by the respective serializer
|
277
|
+
#
|
278
|
+
def to_xml; end
|
279
|
+
|
280
|
+
# IMPORTANT !!!!
|
281
|
+
#
|
282
|
+
# Try to make this a bit prettier
|
283
|
+
#
|
284
|
+
INTEGER_ATTRIBUTES.each do |method|
|
285
|
+
define_method(method) do
|
286
|
+
value = @options[:"#{method.to_sym}"].to_i
|
287
|
+
value = [value, self.class.max_values[method]].min if self.class.max_values[method]
|
288
|
+
value
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
def sort
|
293
|
+
value = @options[:sort].to_sym
|
294
|
+
|
295
|
+
begin
|
296
|
+
field = Sunspot::Setup.for(self.class.model_class).field(value)
|
297
|
+
return value
|
298
|
+
rescue Sunspot::UnrecognizedFieldError => e
|
299
|
+
return 'score'
|
300
|
+
end
|
301
|
+
end
|
302
|
+
|
303
|
+
def direction
|
304
|
+
if %w(asc desc).include?(@options[:direction])
|
305
|
+
@options[:direction].to_sym
|
306
|
+
else
|
307
|
+
:desc
|
308
|
+
end
|
309
|
+
end
|
310
|
+
|
311
|
+
def solr_search_object
|
312
|
+
return @solr_search_object if @solr_search_object
|
313
|
+
@solr_search_object = execute_solr_search
|
314
|
+
|
315
|
+
if options[:debug] == 'true' && @solr_search_object.respond_to?(:query)
|
316
|
+
self.solr_request_params = @solr_search_object.query.to_params
|
317
|
+
end
|
318
|
+
|
319
|
+
@solr_search_object
|
320
|
+
end
|
321
|
+
|
322
|
+
def solr_error_message(exception)
|
323
|
+
{
|
324
|
+
title: "#{exception.response[:status]} #{RSolr::Error::Http::STATUS_CODES[exception.response[:status].to_i]}",
|
325
|
+
body: exception.send(:parse_solr_error_response, exception.response[:body])
|
326
|
+
}
|
327
|
+
end
|
328
|
+
|
329
|
+
# rubocop:disable Style/MethodMissing
|
330
|
+
def method_missing(symbol, *args)
|
331
|
+
return nil unless solr_search_object.respond_to?(:hits)
|
332
|
+
solr_search_object.send(symbol, *args)
|
333
|
+
end
|
334
|
+
# rubocop:enable Style/MethodMissing
|
335
|
+
|
336
|
+
def execute_solr_search
|
337
|
+
search = search_builder
|
338
|
+
|
339
|
+
search.build do
|
340
|
+
keywords text, fields: query_fields
|
341
|
+
end
|
342
|
+
|
343
|
+
execute_solr_search_and_handle_errors(search)
|
344
|
+
end
|
345
|
+
|
346
|
+
def execute_solr_search_and_handle_errors(search)
|
347
|
+
self.errors ||= []
|
348
|
+
sunspot = search.execute
|
349
|
+
rescue RSolr::Error::Http => e
|
350
|
+
self.errors << solr_error_message(e)
|
351
|
+
Rails.logger.info e.message
|
352
|
+
sunspot = {}
|
353
|
+
rescue Timeout::Error, Errno::ECONNREFUSED, Errno::ECONNRESET => e
|
354
|
+
self.errors << 'Solr is temporarily unavailable please try again in a few seconds.'
|
355
|
+
Rails.logger.info e.message
|
356
|
+
sunspot = {}
|
357
|
+
ensure
|
358
|
+
return sunspot
|
359
|
+
end
|
360
|
+
|
361
|
+
private
|
362
|
+
|
363
|
+
# Generates the :and and :or conditions for a search object
|
364
|
+
#
|
365
|
+
def build_conditions
|
366
|
+
proc do
|
367
|
+
{ and: options[:and], or: options[:or] }.each do |operator, value|
|
368
|
+
Utils.call_block(self, &recurse_conditions(operator, value))
|
369
|
+
end
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
# Detects when the key is a operator (:and, :or) and calls itself
|
374
|
+
# recursively until it finds facets defined in Sunspot.
|
375
|
+
#
|
376
|
+
def recurse_conditions(key, conditions, current_operator = :and)
|
377
|
+
proc do
|
378
|
+
case key.to_sym
|
379
|
+
when :and
|
380
|
+
all_of do
|
381
|
+
conditions.each do |filter, value|
|
382
|
+
Utils.call_block(self, &recurse_conditions(filter, value, :and))
|
383
|
+
end
|
384
|
+
end
|
385
|
+
when :or
|
386
|
+
any_of do
|
387
|
+
conditions.each do |filter, value|
|
388
|
+
Utils.call_block(self, &recurse_conditions(filter, value, :or))
|
389
|
+
end
|
390
|
+
end
|
391
|
+
else
|
392
|
+
Utils.call_block(self, &filter_values(key, conditions, current_operator))
|
393
|
+
end
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
# Generates a single condition. It can take a operator to
|
398
|
+
# determine how the values within the filter are going to be
|
399
|
+
# joined.
|
400
|
+
#
|
401
|
+
def filter_values(key, conditions, current_operator = :and)
|
402
|
+
proc do
|
403
|
+
if conditions.is_a? Hash
|
404
|
+
operator, values = conditions.first
|
405
|
+
else
|
406
|
+
operator = current_operator
|
407
|
+
values = conditions
|
408
|
+
end
|
409
|
+
|
410
|
+
if values.is_a?(Array)
|
411
|
+
case operator.to_sym
|
412
|
+
when :or
|
413
|
+
with(key).any_of(values)
|
414
|
+
when :and
|
415
|
+
with(key).all_of(values)
|
416
|
+
else
|
417
|
+
raise Exception, 'Expected operator (:and, :or)'
|
418
|
+
end
|
419
|
+
else
|
420
|
+
if values =~ /(.+)\*$/
|
421
|
+
with(key).starting_with(Regexp.last_match(1))
|
422
|
+
else
|
423
|
+
with(key, to_proper_value(key, values))
|
424
|
+
end
|
425
|
+
end
|
426
|
+
end
|
427
|
+
end
|
428
|
+
end
|
429
|
+
end
|
430
|
+
# rubocop:enable Metrics/ModuleLength
|