blacklight-spotlight 3.0.0.rc3 → 3.0.0.rc4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/spotlight/admin/reindex_monitor.js +1 -0
- data/app/assets/stylesheets/spotlight/browse_group_categories_block.scss +23 -0
- data/app/controllers/spotlight/catalog_controller.rb +4 -1
- data/app/controllers/spotlight/dashboards_controller.rb +1 -1
- data/app/controllers/spotlight/exhibits_controller.rb +1 -1
- data/app/helpers/spotlight/application_helper.rb +19 -0
- data/app/helpers/spotlight/pages_helper.rb +1 -1
- data/app/jobs/concerns/spotlight/job_tracking.rb +47 -0
- data/app/jobs/concerns/spotlight/limit_concurrency.rb +33 -0
- data/app/jobs/spotlight/add_uploads_from_csv.rb +6 -3
- data/app/jobs/spotlight/application_job.rb +8 -0
- data/app/jobs/spotlight/cleanup_job_trackers_job.rb +13 -0
- data/app/jobs/spotlight/default_thumbnail_job.rb +1 -3
- data/app/jobs/spotlight/reindex_exhibit_job.rb +36 -0
- data/app/jobs/spotlight/reindex_job.rb +49 -41
- data/app/jobs/spotlight/rename_sidecar_field_job.rb +2 -2
- data/app/jobs/spotlight/update_job_trackers_job.rb +20 -0
- data/app/models/concerns/spotlight/user.rb +2 -1
- data/app/models/spotlight/event.rb +13 -0
- data/app/models/spotlight/exhibit.rb +4 -14
- data/app/models/spotlight/job_tracker.rb +105 -0
- data/app/models/spotlight/reindex_progress.rb +44 -27
- data/app/models/spotlight/resource.rb +24 -58
- data/app/models/spotlight/resources/iiif_harvester.rb +10 -1
- data/app/models/spotlight/resources/iiif_manifest.rb +3 -1
- data/app/models/spotlight/resources/iiif_service.rb +1 -1
- data/app/models/spotlight/resources/json_upload.rb +12 -0
- data/app/models/spotlight/resources/upload.rb +25 -2
- data/app/models/spotlight/solr_document_sidecar.rb +2 -1
- data/app/services/spotlight/etl.rb +7 -0
- data/app/services/spotlight/etl/context.rb +52 -0
- data/app/services/spotlight/etl/executor.rb +194 -0
- data/app/services/spotlight/etl/loaders.rb +12 -0
- data/app/services/spotlight/etl/pipeline.rb +81 -0
- data/app/services/spotlight/etl/solr_loader.rb +96 -0
- data/app/services/spotlight/etl/sources.rb +25 -0
- data/app/services/spotlight/etl/step.rb +82 -0
- data/app/services/spotlight/etl/transforms.rb +64 -0
- data/app/services/spotlight/validity_checker.rb +5 -5
- data/app/views/spotlight/dashboards/_reindexing_activity.html.erb +6 -6
- data/app/views/spotlight/shared/_locale_picker.html.erb +1 -1
- data/app/views/spotlight/sir_trevor/blocks/_browse_group_categories_block.html.erb +4 -3
- data/config/locales/spotlight.ar.yml +11 -1
- data/config/locales/spotlight.en.yml +3 -2
- data/db/migrate/20210122082032_create_job_trackers.rb +22 -0
- data/db/migrate/20210126123041_create_events.rb +15 -0
- data/lib/generators/spotlight/scaffold_resource_generator.rb +5 -13
- data/lib/spotlight/engine.rb +8 -1
- data/lib/spotlight/version.rb +1 -1
- data/spec/controllers/spotlight/catalog_controller_spec.rb +3 -1
- data/spec/examples.txt +1448 -1437
- data/spec/factories/job_trackers.rb +9 -0
- data/spec/features/add_items_spec.rb +9 -4
- data/spec/features/javascript/reindex_monitor_spec.rb +1 -1
- data/spec/features/site_users_management_spec.rb +4 -4
- data/spec/helpers/spotlight/pages_helper_spec.rb +8 -0
- data/spec/jobs/spotlight/reindex_exhibit_job_spec.rb +43 -0
- data/spec/jobs/spotlight/reindex_job_spec.rb +30 -59
- data/spec/models/spotlight/exhibit_spec.rb +3 -57
- data/spec/models/spotlight/reindex_progress_spec.rb +89 -87
- data/spec/models/spotlight/resource_spec.rb +69 -90
- data/spec/models/spotlight/resources/iiif_harvester_spec.rb +9 -10
- data/spec/models/spotlight/solr_document_sidecar_spec.rb +1 -0
- data/spec/services/spotlight/etl/context_spec.rb +66 -0
- data/spec/services/spotlight/etl/executor_spec.rb +149 -0
- data/spec/services/spotlight/etl/pipeline_spec.rb +22 -0
- data/spec/services/spotlight/etl/solr_loader_spec.rb +76 -0
- data/spec/services/spotlight/etl/step_spec.rb +70 -0
- data/spec/spec_helper.rb +2 -5
- data/spec/views/spotlight/dashboards/_reindexing_activity.html.erb_spec.rb +22 -19
- metadata +55 -15
- data/app/models/concerns/spotlight/resources/open_graph.rb +0 -36
- data/app/models/spotlight/reindexing_log_entry.rb +0 -42
- data/app/services/spotlight/resources/iiif_builder.rb +0 -19
- data/app/services/spotlight/solr_document_builder.rb +0 -77
- data/app/services/spotlight/upload_solr_document_builder.rb +0 -57
- data/spec/factories/reindexing_log_entries.rb +0 -54
- data/spec/models/spotlight/reindexing_log_entry_spec.rb +0 -129
- data/spec/models/spotlight/resources/open_graph_spec.rb +0 -65
- data/spec/services/spotlight/solr_document_builder_spec.rb +0 -66
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
module Etl
|
5
|
+
# Solr data loader with a built-in buffer to combine document updates into batches
|
6
|
+
class SolrLoader
|
7
|
+
attr_reader :queue, :batch_size
|
8
|
+
|
9
|
+
delegate :size, to: :queue
|
10
|
+
|
11
|
+
def initialize(batch_size: Spotlight::Engine.config.solr_batch_size, solr_connection: nil)
|
12
|
+
@queue = Queue.new
|
13
|
+
@batch_size = batch_size
|
14
|
+
@blacklight_solr = solr_connection
|
15
|
+
end
|
16
|
+
|
17
|
+
def call(data, pipeline = nil)
|
18
|
+
@queue << data
|
19
|
+
|
20
|
+
write_to_index(pipeline) if @queue.size >= @batch_size
|
21
|
+
end
|
22
|
+
|
23
|
+
def finalize(pipeline = nil)
|
24
|
+
write_to_index(pipeline)
|
25
|
+
|
26
|
+
commit! if pipeline.nil? || pipeline.context.additional_parameters[:commit]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def write_to_index(pipeline)
|
32
|
+
batch = drain_queue
|
33
|
+
|
34
|
+
return unless write? && batch.any?
|
35
|
+
|
36
|
+
send_batch(batch, pipeline)
|
37
|
+
end
|
38
|
+
|
39
|
+
def send_batch(documents, pipeline)
|
40
|
+
blacklight_solr.update params: { commitWithin: 500 },
|
41
|
+
data: documents.to_json,
|
42
|
+
headers: { 'Content-Type' => 'application/json' }
|
43
|
+
rescue StandardError => e
|
44
|
+
logger.warn "Error sending a batch of documents to solr: #{e}"
|
45
|
+
|
46
|
+
documents.each do |doc|
|
47
|
+
send_one(doc, pipeline)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def send_one(document, pipeline)
|
52
|
+
blacklight_solr.update params: { commitWithin: 500 },
|
53
|
+
data: [document].to_json,
|
54
|
+
headers: { 'Content-Type' => 'application/json' }
|
55
|
+
rescue StandardError => e
|
56
|
+
pipeline&.on_error(self, e, document.to_json)
|
57
|
+
end
|
58
|
+
|
59
|
+
def blacklight_solr
|
60
|
+
@blacklight_solr ||= RSolr.connect(connection_config.merge(adapter: connection_config[:http_adapter]))
|
61
|
+
end
|
62
|
+
|
63
|
+
def connection_config
|
64
|
+
Blacklight.connection_config
|
65
|
+
end
|
66
|
+
|
67
|
+
def drain_queue
|
68
|
+
arr = []
|
69
|
+
|
70
|
+
begin
|
71
|
+
arr << @queue.deq(true) while arr.length < @batch_size && !@queue.empty?
|
72
|
+
rescue ThreadError
|
73
|
+
# @queue throws a ThreadError if it is empty...
|
74
|
+
end
|
75
|
+
|
76
|
+
arr
|
77
|
+
end
|
78
|
+
|
79
|
+
def commit!
|
80
|
+
return unless write?
|
81
|
+
|
82
|
+
blacklight_solr.commit
|
83
|
+
rescue StandardError => e
|
84
|
+
logger.warn "Unable to commit to solr: #{e}"
|
85
|
+
end
|
86
|
+
|
87
|
+
def write?
|
88
|
+
Spotlight::Engine.config.writable_index
|
89
|
+
end
|
90
|
+
|
91
|
+
def logger
|
92
|
+
Rails.logger
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
module Etl
|
5
|
+
# Basic ETL source implementations
|
6
|
+
module Sources
|
7
|
+
# A simple source that just returns the original resource(s)
|
8
|
+
IdentitySource = lambda do |context|
|
9
|
+
Array.wrap(context.resource)
|
10
|
+
end
|
11
|
+
|
12
|
+
# A transform step that calls a method on the resource to generate a source
|
13
|
+
def self.SourceMethodSource(method) # rubocop:disable Naming/MethodName
|
14
|
+
lambda do |context|
|
15
|
+
context.resource.public_send(method)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# A simple source that retrieves the stored data from a Spotlight::Resource
|
20
|
+
StoredData = lambda do |context, **|
|
21
|
+
Array.wrap(context.resource.data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
module Etl
|
5
|
+
# ETL pipeline step
|
6
|
+
class Step
|
7
|
+
attr_reader :definition, :context, :executor
|
8
|
+
|
9
|
+
# @param [Class, Proc] definition the step to run
|
10
|
+
# @param [String] label
|
11
|
+
# @param [Spotlight::Etl::Executor] executor the execution environment
|
12
|
+
def initialize(definition, label: nil, executor: nil)
|
13
|
+
@definition = definition
|
14
|
+
@executor = executor
|
15
|
+
@label = label
|
16
|
+
end
|
17
|
+
|
18
|
+
# rubocop:disable Metrics/MethodLength
|
19
|
+
def call(*args)
|
20
|
+
with_logger do |logger|
|
21
|
+
logger.debug { "Called with #{transform_data_for_debugging(args.first)}" }
|
22
|
+
|
23
|
+
catch :skip do
|
24
|
+
return action.call(*args).tap do |result|
|
25
|
+
logger.debug { " => Returning #{transform_data_for_debugging(result)}" } if $VERBOSE
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
logger.debug ' => Caught skip.'
|
30
|
+
throw :skip
|
31
|
+
end
|
32
|
+
rescue StandardError => e
|
33
|
+
with_logger do |logger|
|
34
|
+
logger.error("Caught exception #{e}")
|
35
|
+
end
|
36
|
+
raise(e)
|
37
|
+
end
|
38
|
+
# rubocop:enable Metrics/MethodLength
|
39
|
+
|
40
|
+
def finalize(*args)
|
41
|
+
action.finalize(*args) if action.respond_to? :finalize
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# @return [#call]
|
47
|
+
def action
|
48
|
+
case definition
|
49
|
+
when Class
|
50
|
+
# memoize the class' instance for the lifetime of the step
|
51
|
+
@memoized_action ||= definition.new
|
52
|
+
else # Proc, etc
|
53
|
+
definition
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
# @return [#to_string]
|
58
|
+
def label
|
59
|
+
@label || definition
|
60
|
+
end
|
61
|
+
|
62
|
+
# NOTE: this is super weird to support Rails 5.2
|
63
|
+
# @return [Logger]
|
64
|
+
def with_logger
|
65
|
+
yield(Rails.logger) && return unless executor
|
66
|
+
|
67
|
+
executor.with_logger do |logger|
|
68
|
+
logger.tagged(label) do
|
69
|
+
yield logger
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
##
|
75
|
+
# @param [Hash] data
|
76
|
+
# @return [String] a simplified + truncated version of the data hash for debugging
|
77
|
+
def transform_data_for_debugging(data)
|
78
|
+
executor&.transform_data_for_debugging(data) || data.inspect.truncate(100)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Spotlight
|
4
|
+
module Etl
|
5
|
+
# Basic + default transform steps
|
6
|
+
module Transforms
|
7
|
+
# A transform step that "transforms" the source into the data element
|
8
|
+
IdentityTransform = lambda do |data, pipeline|
|
9
|
+
data.merge(pipeline.source)
|
10
|
+
end
|
11
|
+
|
12
|
+
# A transform step that calls a method on the source to generate a document
|
13
|
+
def self.SourceMethodTransform(method) # rubocop:disable Naming/MethodName
|
14
|
+
lambda do |data, pipeline|
|
15
|
+
data.merge(pipeline.source.public_send(method))
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
# A transform step that throws away blank data
|
20
|
+
RejectBlank = lambda do |data, _|
|
21
|
+
throw :skip if data.blank?
|
22
|
+
data
|
23
|
+
end
|
24
|
+
|
25
|
+
# A trasnform step that ensures data has a unique key attribute
|
26
|
+
RejectMissingUniqueId = lambda do |data, pipeline|
|
27
|
+
id = pipeline.context.unique_key(data)
|
28
|
+
|
29
|
+
throw :skip if id.blank?
|
30
|
+
data
|
31
|
+
end
|
32
|
+
|
33
|
+
# A transform that adds exhibit-specific metadata (like Spotlight sidecar data)
|
34
|
+
# to the document
|
35
|
+
ApplyExhibitMetadata = lambda do |data, pipeline|
|
36
|
+
resource = pipeline.context.resource
|
37
|
+
document_model = pipeline.context.document_model
|
38
|
+
id = pipeline.context.unique_key(data)
|
39
|
+
|
40
|
+
next data unless document_model && id.present?
|
41
|
+
|
42
|
+
exhibit_metadata = document_model.build_for_exhibit(id, resource.exhibit, resource: (resource if resource.persisted?))
|
43
|
+
|
44
|
+
data.reverse_merge(exhibit_metadata.to_solr)
|
45
|
+
end
|
46
|
+
|
47
|
+
# A transform that adds application-specific metadata (like what resource generated the solr document)
|
48
|
+
ApplyApplicationMetadata = lambda do |data, pipeline|
|
49
|
+
resource = pipeline.context.resource
|
50
|
+
document_model = pipeline.context.document_model
|
51
|
+
|
52
|
+
data.reverse_merge(
|
53
|
+
Spotlight::Engine.config.resource_global_id_field => (resource.to_global_id.to_s if resource.persisted?),
|
54
|
+
document_model.resource_type_field => resource.class.to_s.tableize
|
55
|
+
)
|
56
|
+
end
|
57
|
+
|
58
|
+
# A transform that adds externally-provided metadata to the document
|
59
|
+
ApplyPipelineMetadata = lambda do |data, pipeline|
|
60
|
+
data.reverse_merge(pipeline.context.additional_metadata)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -5,16 +5,16 @@ module Spotlight
|
|
5
5
|
# check if a delayed job still needs to run
|
6
6
|
class ValidityChecker
|
7
7
|
# Return a validity token
|
8
|
-
# @param [
|
8
|
+
# @param [ActiveJob::Base]
|
9
9
|
# @return [Object] any serializable object
|
10
|
-
def mint(
|
10
|
+
def mint(_job); end
|
11
11
|
|
12
12
|
# Check if the token is still valid for the model
|
13
|
-
# @param [
|
13
|
+
# @param [ActiveJob::Base]
|
14
14
|
# @param [Object] the serializable token minted by #mint
|
15
15
|
# @return [boolean]
|
16
|
-
def check(
|
17
|
-
true
|
16
|
+
def check(_job, validity_token: nil)
|
17
|
+
validity_token || true
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
@@ -12,13 +12,13 @@
|
|
12
12
|
</tr>
|
13
13
|
</thead>
|
14
14
|
<tbody>
|
15
|
-
<% @recent_reindexing.each do |
|
15
|
+
<% @recent_reindexing.each do |tracker| %>
|
16
16
|
<tr class="d-flex">
|
17
|
-
<td class="col-3"><%= l
|
18
|
-
<td class="col-3"><%=
|
19
|
-
<td class="col-1"><%=
|
20
|
-
<td class="col-3"><%= distance_of_time_in_words
|
21
|
-
<td class="col-2"><%= t "reindexing_log.status.#{
|
17
|
+
<td class="col-3"><%= l tracker.created_at, format: :long %></td>
|
18
|
+
<td class="col-3"><%= tracker.user.email if tracker.user %></td>
|
19
|
+
<td class="col-1"><%= tracker.progress %></td>
|
20
|
+
<td class="col-3"><%= distance_of_time_in_words tracker.created_at, tracker.updated_at, include_seconds: true if tracker.completed? || tracker.failed? %></td>
|
21
|
+
<td class="col-2"><%= t "reindexing_log.status.#{tracker.status}" %></td>
|
22
22
|
</tr>
|
23
23
|
<% end %>
|
24
24
|
</tbody>
|
@@ -6,7 +6,7 @@
|
|
6
6
|
<ul class="dropdown-menu">
|
7
7
|
<% locale_selecter_dropown_options.each do |language| %>
|
8
8
|
<li>
|
9
|
-
<%= link_to language.to_native, (
|
9
|
+
<%= link_to language.to_native, current_page_for_locale(language.locale), class: 'dropdown-item', data: { turbolinks: false } %>
|
10
10
|
</li>
|
11
11
|
<% end %>
|
12
12
|
</ul>
|
@@ -5,15 +5,15 @@
|
|
5
5
|
<div class="d-flex justify-content-between align-items-end">
|
6
6
|
<h2 class="m-0"><%= group.title %></h2>
|
7
7
|
<div class="pl-5">
|
8
|
-
<%= link_to '
|
8
|
+
<%= link_to t(:'.view_all'), exhibit_browse_groups_path(current_exhibit, group) %>
|
9
9
|
</div>
|
10
10
|
</div>
|
11
11
|
<% if group.searches.count > 1 %>
|
12
12
|
<ul class="browse-group-categories-controls p-0 pt-2 pt-md-0 ml-md-auto mb-0 d-flex justify-content-center align-items-end">
|
13
|
-
<li class="prev px-1">
|
13
|
+
<li class="prev px-1 overflow-hidden">
|
14
14
|
<%= blacklight_icon 'arrow-alt-circle-left' %>
|
15
15
|
</li>
|
16
|
-
<li class="next px-1">
|
16
|
+
<li class="next px-1 overflow-hidden">
|
17
17
|
<%= blacklight_icon 'arrow-alt-circle-right' %>
|
18
18
|
</li>
|
19
19
|
</ul>
|
@@ -34,6 +34,7 @@
|
|
34
34
|
<span class="item-count"><%= t(:'.items', count: search.count) %></span>
|
35
35
|
<% end %>
|
36
36
|
</div>
|
37
|
+
<div class="hover-overlay"></div>
|
37
38
|
</div>
|
38
39
|
<% end %>
|
39
40
|
</div>
|
@@ -34,6 +34,9 @@ ar:
|
|
34
34
|
zero_results:
|
35
35
|
expand_html: "تستطيع أن <a href=\"%{clear_search_url}\"> تمسح استعلام البحث </a> أو محاولة <a href=\"%{expand_search_url}\"> البحث في كل المواد المعروضة لاستعلام البحث ل\"%{browse_query}\"</a>"
|
36
36
|
result_number: لم يتطابق بحثك مع أي عنصر في هذه الفئة.
|
37
|
+
exhibits:
|
38
|
+
groups:
|
39
|
+
all: الكل
|
37
40
|
header_links:
|
38
41
|
contact: ملاحظات واقتراحات
|
39
42
|
login: تسجيل الدخول
|
@@ -52,7 +55,14 @@ ar:
|
|
52
55
|
few: "%{count} عناصر"
|
53
56
|
many: "%{count} عنصراً"
|
54
57
|
other: "%{count} عنصراً"
|
55
|
-
|
58
|
+
browse_group_categories_block:
|
59
|
+
items:
|
60
|
+
one: "%{count} عنصر"
|
61
|
+
two: "%{count} عنصرين"
|
62
|
+
few: "%{count} عناصر"
|
63
|
+
many: "%{count} عنصراً"
|
64
|
+
other: "%{count} عنصراً"
|
65
|
+
view_all: مشاهدة الكل
|
56
66
|
link_to_search_block:
|
57
67
|
items:
|
58
68
|
zero: "%{count} عنصر"
|
@@ -167,10 +167,10 @@ en:
|
|
167
167
|
zh: Chinese
|
168
168
|
reindexing_log:
|
169
169
|
status:
|
170
|
+
completed: Successful
|
171
|
+
enqueued: Not yet started
|
170
172
|
failed: Failed
|
171
173
|
in_progress: In progress
|
172
|
-
succeeded: Successful
|
173
|
-
unstarted: Not yet started
|
174
174
|
shared:
|
175
175
|
site_sidebar:
|
176
176
|
documentation: Curator documentation
|
@@ -765,6 +765,7 @@ en:
|
|
765
765
|
items:
|
766
766
|
one: "%{count} item"
|
767
767
|
other: "%{count} items"
|
768
|
+
view_all: View all
|
768
769
|
link_to_search_block:
|
769
770
|
items:
|
770
771
|
one: "%{count} item"
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateJobTrackers < ActiveRecord::Migration[5.2]
|
4
|
+
def change
|
5
|
+
create_table :spotlight_job_trackers do |t|
|
6
|
+
t.references :on, null: false, polymorphic: true, index: true
|
7
|
+
t.references :resource, null: false, polymorphic: true, index: true
|
8
|
+
t.string :job_id
|
9
|
+
t.string :job_class
|
10
|
+
t.string :parent_job_id
|
11
|
+
t.string :parent_job_class
|
12
|
+
t.string :status
|
13
|
+
t.references :user
|
14
|
+
t.text :log
|
15
|
+
t.text :data
|
16
|
+
|
17
|
+
t.timestamps
|
18
|
+
end
|
19
|
+
|
20
|
+
add_index :spotlight_job_trackers, :job_id
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class CreateEvents < ActiveRecord::Migration[5.2]
|
4
|
+
def change
|
5
|
+
create_table :spotlight_events do |t|
|
6
|
+
t.references :exhibit, null: false, polymorphic: true
|
7
|
+
t.references :resource, null: false, polymorphic: true, index: true
|
8
|
+
t.string :type
|
9
|
+
t.string :collation_key
|
10
|
+
t.text :data
|
11
|
+
|
12
|
+
t.timestamps
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -7,23 +7,15 @@ module Spotlight
|
|
7
7
|
# spotlight:scaffold_resource generator
|
8
8
|
class ScaffoldResource < Rails::Generators::NamedBase
|
9
9
|
source_root File.expand_path('templates', __dir__)
|
10
|
-
def create_document_builder
|
11
|
-
create_file "app/services/#{file_name}_builder.rb", <<-FILE.strip_heredoc
|
12
|
-
class #{class_name}Builder < Spotlight::SolrDocumentBuilder
|
13
|
-
def to_solr
|
14
|
-
return to_enum(:to_solr) unless block_given?
|
15
|
-
|
16
|
-
# TODO: your implementation here
|
17
|
-
# yield { id: resource.id }
|
18
|
-
end
|
19
|
-
end
|
20
|
-
FILE
|
21
|
-
end
|
22
10
|
|
23
11
|
def create_model
|
24
12
|
create_file "app/models/#{file_name}_resource.rb", <<-FILE.strip_heredoc
|
25
13
|
class #{class_name}Resource < Spotlight::Resource
|
26
|
-
self.
|
14
|
+
def self.indexing_pipeline
|
15
|
+
@indexing_pipeline ||= super.dup.tap do |pipeline|
|
16
|
+
# your pipeline here...
|
17
|
+
end
|
18
|
+
end
|
27
19
|
end
|
28
20
|
FILE
|
29
21
|
end
|