Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ gem 'elasticsearch', '~> 8'
gem 'searchkick'

# Use the Puma web server [https://github.com/puma/puma]
gem 'puma', '~> 5.0'
gem 'puma', '~> 8.0'

# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
Expand All @@ -33,7 +33,13 @@ gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
gem 'bootsnap', require: false

# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
gem 'image_processing', '~> 1.2'
gem 'image_processing', '~> 2.0'
# mini_magick/ruby-vips became soft dependencies of image_processing in 2.0 and must be
# added explicitly. This app's config.load_defaults 7.0 (config/application.rb) sets
# config.active_storage.variant_processor = :vips - vips is the actually-active processor,
# not mini_magick (previously present only as an unused transitive dependency of
# image_processing 1.x's gemspec, which required both backends unconditionally).
gem 'ruby-vips', '~> 2.0'

# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible
gem 'rack-cors'
Expand Down Expand Up @@ -84,9 +90,9 @@ gem 'acts-as-taggable-on', '~> 13.0'

gem 'administrate-field-list', '~> 0.0.6'

gem 'httparty', '~> 0.20.0'
gem 'httparty', '~> 0.24.0'

gem 'roo', '~> 2.9'
gem 'roo', '~> 3.0'

gem 'namae', '~> 1.1'

Expand Down
111 changes: 58 additions & 53 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -183,15 +183,13 @@ GEM
raabro (~> 1.4)
globalid (1.2.1)
activesupport (>= 6.1)
hashie (5.0.0)
httparty (0.20.0)
mime-types (~> 3.0)
httparty (0.24.2)
csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.14.8)
concurrent-ruby (~> 1.0)
image_processing (1.13.0)
mini_magick (>= 4.9.5, < 5)
ruby-vips (>= 2.0.17, < 3)
image_processing (2.0.3)
importmap-rails (2.0.3)
actionpack (>= 6.0.0)
activesupport (>= 6.0.0)
Expand All @@ -218,6 +216,7 @@ GEM
kaminari-core (= 1.2.2)
kaminari-core (1.2.2)
language_server-protocol (3.17.0.6)
lint_roller (1.1.0)
logger (1.6.6)
loofah (2.25.2)
crass (~> 1.0.2)
Expand All @@ -230,17 +229,13 @@ GEM
net-smtp
marcel (1.2.1)
matrix (0.4.3)
mime-types (3.5.2)
mime-types-data (~> 3.2015)
mime-types-data (3.2024.1203)
mini_magick (4.13.2)
mini_mime (1.1.5)
mini_portile2 (2.8.9)
minitest (5.25.5)
msgpack (1.8.4)
multi_json (1.21.1)
multi_xml (0.7.2)
bigdecimal (~> 3.1)
multi_xml (0.9.1)
bigdecimal (>= 3.1, < 5)
namae (1.2.0)
racc (~> 1.7)
net-http (0.9.1)
Expand Down Expand Up @@ -280,10 +275,11 @@ GEM
ast (~> 2.4.1)
racc
pg (1.5.9)
prism (1.9.0)
psych (5.1.2)
stringio
public_suffix (7.0.5)
puma (5.6.9)
puma (8.0.2)
nio4r (~> 2.0)
raabro (1.4.0)
racc (1.8.1)
Expand Down Expand Up @@ -337,9 +333,12 @@ GEM
reline (0.5.12)
io-console (~> 0.5)
rexml (3.4.4)
roo (2.10.1)
roo (3.0.0)
base64 (~> 0.2)
csv (~> 3)
logger (~> 1)
nokogiri (~> 1)
rubyzip (>= 1.3.0, < 3.0.0)
rubyzip (>= 3.0.0, < 4.0.0)
rspec-core (3.13.6)
rspec-support (~> 3.13.0)
rspec-expectations (3.13.5)
Expand All @@ -348,45 +347,51 @@ GEM
rspec-mocks (3.13.8)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.13.0)
rspec-rails (6.1.5)
actionpack (>= 6.1)
activesupport (>= 6.1)
railties (>= 6.1)
rspec-core (~> 3.13)
rspec-expectations (~> 3.13)
rspec-mocks (~> 3.13)
rspec-support (~> 3.13)
rspec-rails (8.0.4)
actionpack (>= 7.2)
activesupport (>= 7.2)
railties (>= 7.2)
rspec-core (>= 3.13.0, < 5.0.0)
rspec-expectations (>= 3.13.0, < 5.0.0)
rspec-mocks (>= 3.13.0, < 5.0.0)
rspec-support (>= 3.13.0, < 5.0.0)
rspec-support (3.13.7)
rubocop (1.65.1)
rubocop (1.89.0)
json (~> 2.3)
language_server-protocol (>= 3.17.0)
parallel (~> 1.10)
language_server-protocol (~> 3.17.0.2)
lint_roller (~> 1.1.0)
parallel (>= 1.10)
parser (>= 3.3.0.2)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 2.4, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.31.1, < 2.0)
regexp_parser (>= 2.9.3, < 3.0)
rubocop-ast (>= 1.49.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 2.4.0, < 3.0)
rubocop-ast (1.32.3)
parser (>= 3.3.1.0)
rubocop-factory_bot (2.26.1)
rubocop (~> 1.61)
rubocop-rails (2.26.2)
unicode-display_width (>= 2.4.0, < 4.0)
rubocop-ast (1.50.0)
parser (>= 3.3.7.2)
prism (~> 1.7)
rubocop-factory_bot (2.28.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rails (2.36.0)
activesupport (>= 4.2.0)
lint_roller (~> 1.1)
rack (>= 1.1)
rubocop (>= 1.52.0, < 2.0)
rubocop-ast (>= 1.31.1, < 2.0)
rubocop-rspec (3.0.5)
rubocop (~> 1.61)
rubocop-rspec_rails (2.30.0)
rubocop (~> 1.61)
rubocop-rspec (~> 3, >= 3.0.1)
rubocop (>= 1.75.0, < 2.0)
rubocop-ast (>= 1.44.0, < 2.0)
rubocop-rspec (3.10.2)
lint_roller (~> 1.1)
regexp_parser (>= 2.0)
rubocop (~> 1.86, >= 1.86.2)
rubocop-rspec_rails (2.32.0)
lint_roller (~> 1.1)
rubocop (~> 1.72, >= 1.72.1)
rubocop-rspec (~> 3.5)
ruby-progressbar (1.13.0)
ruby-vips (2.2.5)
ruby-vips (2.3.0)
ffi (~> 1.12)
logger
rubyzip (2.3.2)
rubyzip (3.4.1)
sassc (2.4.0)
ffi (~> 1.9)
sassc-rails (2.1.2)
Expand All @@ -395,9 +400,8 @@ GEM
sprockets (> 3.0)
sprockets-rails
tilt
searchkick (5.3.1)
activemodel (>= 6.1)
hashie
searchkick (6.1.2)
activemodel (>= 7.2)
securerandom (0.3.2)
selenium-devtools (0.151.0)
selenium-webdriver (~> 4.2)
Expand All @@ -407,8 +411,8 @@ GEM
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 4.0)
websocket (~> 1.0)
shoulda-matchers (6.4.0)
activesupport (>= 5.2.0)
shoulda-matchers (8.0.1)
activesupport (>= 7.2)
sidekiq (7.3.10)
base64
connection_pool (>= 2.3.0, < 3)
Expand Down Expand Up @@ -484,23 +488,24 @@ DEPENDENCIES
elasticsearch (~> 8)
factory_bot_rails
faker
httparty (~> 0.20.0)
image_processing (~> 1.2)
httparty (~> 0.24.0)
image_processing (~> 2.0)
importmap-rails (~> 2.0)
jbuilder (~> 2.11)
kaminari (~> 1.2)
namae (~> 1.1)
pg (~> 1.1)
puma (~> 5.0)
puma (~> 8.0)
rack-cors
rails (~> 8.1.3)
roo (~> 2.9)
roo (~> 3.0)
rspec-rails
rubocop
rubocop-factory_bot
rubocop-rails
rubocop-rspec
rubocop-rspec_rails
ruby-vips (~> 2.0)
sassc-rails
searchkick
selenium-devtools
Expand Down
8 changes: 6 additions & 2 deletions app/controllers/entities_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@ def letters
private

def reindex
Entity.reindex if ENV['RAILS_ENV'] == 'test'
PublishedEntity.reindex if ENV['RAILS_ENV'] == 'test'
# mode: :inline forces a synchronous reindex regardless of Searchable's
# `callbacks: :async` option - searchkick's default mode resolution falls back to
# the model's callbacks option (see Searchkick::Index#reindex_records), so without
# this the search immediately below could run against a not-yet-indexed record.
Entity.reindex(mode: :inline) if ENV['RAILS_ENV'] == 'test'
PublishedEntity.reindex(mode: :inline) if ENV['RAILS_ENV'] == 'test'
rescue Searchkick::Error
end

Expand Down
10 changes: 7 additions & 3 deletions app/controllers/letters_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ def letters_from_results(results)
volume: letter.volume,
recipients: letter.recipients,
destinations: letter.destinations,
origins: letter.orgins,
origins: letter.origins,
mentions: letter.mentions
}
end
Expand Down Expand Up @@ -134,8 +134,12 @@ def set_filters
# rubocop:enable Metrics/AbcSize, Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity

def reindex
Letter.reindex if ENV['RAILS_ENV'] == 'test'
PublishedLetter.reindex if ENV['RAILS_ENV'] == 'test'
# mode: :inline forces a synchronous reindex regardless of Searchable's
# `callbacks: :async` option - searchkick's default mode resolution falls back to
# the model's callbacks option (see Searchkick::Index#reindex_records), so without
# this the search immediately below could run against a not-yet-indexed record.
Letter.reindex(mode: :inline) if ENV['RAILS_ENV'] == 'test'
PublishedLetter.reindex(mode: :inline) if ENV['RAILS_ENV'] == 'test'
end

# Only allow a list of trusted parameters through.
Expand Down
1 change: 1 addition & 0 deletions app/dashboards/entity_dashboard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

class EntityDashboard < Administrate::BaseDashboard
include ActionView::Helpers::SanitizeHelper

# ATTRIBUTE_TYPES
# a hash that describes the type of each of the model's fields.
#
Expand Down
3 changes: 2 additions & 1 deletion app/jobs/load_big_sam_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

class LoadBigSamJob < ApplicationJob
include ActionView::Helpers::SanitizeHelper

queue_as :default

# Raised to abandon a single row (e.g. an unparseable date) without treating it as a
Expand Down Expand Up @@ -372,7 +373,7 @@ def get_entity(label: nil, type: nil, return_nil: false)
def get_person(name)
entity = nil
names = Namae.parse(name).first
if names&.given && names&.family
if names&.given && names.family
names.family = "Van #{names.family}" if names.particle&.downcase == 'van'
names.family = "von #{names.family}" if names.particle&.downcase == 'von'
names = mc_or_mac?(names)
Expand Down
4 changes: 2 additions & 2 deletions app/models/concerns/entity_common.rb
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ def short_display
lines.push("<strong>Date</strong> #{date_str}") if date_str.present?
end

paragraphs = lines.map {|line| "<p>#{line}</p>" }.flatten.join.strip
paragraphs = lines.map {|line| "<p>#{line}</p>" }.join.strip
Loofah.fragment("<section>#{paragraphs}</section>").scrub!(:prune).to_html
end

Expand Down Expand Up @@ -299,7 +299,7 @@ def full_display
rows.push("<th scope='row'>See Also</th><td colsapn=3>#{link_list}</td>") if links.present?
end

table_rows = rows.map {|row| "<tr>#{row}</tr>" }.flatten.join.strip
table_rows = rows.map {|row| "<tr>#{row}</tr>" }.join.strip
Loofah.fragment("<table>#{table_rows}</table>").scrub!(:prune).to_html
end

Expand Down
4 changes: 2 additions & 2 deletions app/models/entity.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,9 @@ def concat_label
"#{event_types&.map(&:titleize)&.join(',')} #{description}".strip
end
when 'person'
if label && (last_name.nil? && first_name.nil?)
if label && last_name.nil? && first_name.nil?
names = Namae.parse label
if names&.first&.given && names&.first&.family
if names&.first&.given && names&.first.family
self.first_name = names.first.given
self.last_name = names.first.family
end
Expand Down
2 changes: 1 addition & 1 deletion app/models/faq.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ class Faq < ApplicationRecord
before_save :initial_position
after_save :update_position

default_scope { order('position') }
default_scope { order(:position) }

private

Expand Down
5 changes: 4 additions & 1 deletion config/puma.rb
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,10 @@

# Specifies the `port` that Puma will listen on to receive requests; default is 3000.
#
port ENV.fetch('PORT', 3000)
# Puma 8 defaults to binding IPv6 (::) instead of IPv4 (0.0.0.0) when a non-loopback
# IPv6 interface is available. Pinning the host explicitly preserves this app's
# existing IPv4 behavior regardless of Puma version or the host's network interfaces.
port ENV.fetch('PORT', 3000), '0.0.0.0'

# Specifies the `environment` that Puma will run in.
#
Expand Down
3 changes: 0 additions & 3 deletions spec/factories/entities.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
# frozen_string_literal: true

# rubocop:disable Layout/LineLength

FactoryBot.define do
factory :entity do
label { Faker::Movies::HitchhikersGuideToTheGalaxy.character }
Expand Down Expand Up @@ -170,4 +168,3 @@
end
end
end
# rubocop:enable Layout/LineLength
2 changes: 1 addition & 1 deletion spec/jobs/load_big_sam_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -262,7 +262,7 @@ def valid_row(overrides = {})
skipped = job.instance_variable_get(:@row_skipped)
expect(skipped.size).to eq(1)
expect(skipped.first[:code]).to eq('BAD')
expect(skipped.first[:reason]).to match(/bad date/)
expect(skipped.first[:reason]).to include('bad date')
expect(Letter.find_by(legacy_pk: 955).code).to eq('GOOD')
end

Expand Down
11 changes: 11 additions & 0 deletions spec/requests/letters_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@
expect(json[:letters].count).to eq(9)
end

# Regression test: LettersController#letters_from_results called `letter.orgins`
# (typo for `origins`) on a Searchkick::HashWrapper. Searchkick 5.x silently
# returned nil for the typo'd key; 6.x raises NoMethodError instead, surfacing a
# bug that was always there but never covered - nothing asserted on the `origins`
# key in a response before this.
it 'includes the origins of a letter' do
create(:published_letter, origins: create_list(:place_entity, 1, label: 'Reynoldstown'))
get "#{letters_url}.json"
expect(json[:letters].first[:origins]).to eq(['Reynoldstown'])
end

it 'returns letters with start_date param' do
create_list(:published_letter, 10)
create(:published_letter, date: DateTime.new(1961, 2, 22))
Expand Down
Loading