From a1ddc25da0d2aa79a4d9216ef7792f26233bd38e Mon Sep 17 00:00:00 2001 From: erdgeist Date: Fri, 26 Jun 2026 05:19:28 +0200 Subject: Stage 5 fixes: RouteWithParams removal, Globalize fallbacks, search stub, to_s(:db) → to_fs(:db), LockedByAnotherUser autoload, test environment config MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Remove safe_path helper and content_path shim from link_helper.rb - Update all safe_path call sites in views to use named route helpers directly - Fix Globalize fallbacks via config.i18n.fallbacks in application.rb, remove i18n initializer - Stub Node.search returning none (search disabled pending PostgreSQL upgrade) - Replace to_s(:db) with to_fs(:db) in node.rb, nodes_helper.rb, link_helper.rb, admin view - Move LockedByAnotherUser to app/models/locked_by_another_user.rb for Zeitwerk autoloading - Fix config/environments/test.rb: config.assets removed, cache_classes → enable_reloading, test_order removed, minitest pinned to ~> 5.25 - Fix config/environments/development.rb: cache_classes → enable_reloading - Park search vector migration in doc/ pending PostgreSQL and plpgsql availability --- Gemfile | 1 + Gemfile.lock | 7 ++-- app/helpers/link_helper.rb | 35 +++------------- app/helpers/nodes_helper.rb | 2 +- app/models/locked_by_another_user.rb | 1 + app/models/node.rb | 13 +++--- app/views/admin/_recent_changes.html.erb | 2 +- app/views/content/_search.html.erb | 2 +- app/views/content/_tags.html.erb | 2 +- app/views/layouts/application.html.erb | 4 +- config/application.rb | 1 + config/environments/development.rb | 2 +- config/environments/test.rb | 4 +- config/initializers/i18n.rb | 3 -- config/initializers/will_paginate_patch.rb | 13 ------ ...d_search_vector_to_page_translations.rb.pending | 47 ++++++++++++++++++++++ 16 files changed, 75 insertions(+), 64 deletions(-) create mode 100644 app/models/locked_by_another_user.rb delete mode 100644 config/initializers/i18n.rb delete mode 100644 config/initializers/will_paginate_patch.rb create mode 100644 doc/20260626025705_add_search_vector_to_page_translations.rb.pending diff --git a/Gemfile b/Gemfile index 2f99c64..2f6e394 100644 --- a/Gemfile +++ b/Gemfile @@ -26,6 +26,7 @@ group :assets do gem 'sass-rails', '~> 6.0' gem 'coffee-rails', '~> 4.0' gem 'uglifier', '>= 1.0.3' + gem 'minitest', '~> 5.25' end group :test do diff --git a/Gemfile.lock b/Gemfile.lock index 357998d..9d5ec90 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -157,9 +157,7 @@ GEM marcel (1.2.1) mini_mime (1.1.5) mini_portile2 (2.8.9) - minitest (6.0.6) - drb (~> 2.0) - prism (~> 1.5) + minitest (5.27.0) net-imap (0.6.4.1) date net-protocol @@ -323,6 +321,7 @@ DEPENDENCIES globalize (~> 7.0) jquery-rails libxml-ruby (~> 5.0) + minitest (~> 5.25) nokogiri (~> 1.18) pg (~> 1.4.6) puma @@ -394,7 +393,7 @@ CHECKSUMS marcel (1.2.1) sha256=1678e9360e32f9eafa917c80029e2f6d10b2715c66a4b87b6d0da9b9cd1f859f mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef mini_portile2 (2.8.9) sha256=0cd7c7f824e010c072e33f68bc02d85a00aeb6fce05bb4819c03dfd3c140c289 - minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1 + minitest (5.27.0) sha256=2d3b17f8a36fe7801c1adcffdbc38233b938eb0b4966e97a6739055a45fa77d5 net-imap (0.6.4.1) sha256=29f0360d75a7efd3539f16ac1957dea5c0a51ddeceb348db4553c3120914ea0d net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3 net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8 diff --git a/app/helpers/link_helper.rb b/app/helpers/link_helper.rb index 39ec495..cb13c8d 100644 --- a/app/helpers/link_helper.rb +++ b/app/helpers/link_helper.rb @@ -1,5 +1,5 @@ module LinkHelper - + def content_path_helper path_array url_for( :controller => :content, @@ -8,11 +8,11 @@ module LinkHelper :page_path => path_array ) end - + def content_url_helper path_array request.protocol + request.host_with_port + content_path_helper(path_array) end - + def link_to_path title, path, html_options = {} return "" if path.nil? @@ -22,9 +22,7 @@ module LinkHelper end active_class = active ? {:class => 'active'} : {:class => 'inactive'} - html_options = html_options.merge(active_class) - locale = params[:locale] || I18n.locale link_to( @@ -39,34 +37,13 @@ module LinkHelper return :class => "selected" end end - + def unlock_link message = "Are you sure you want to unlock?\n" + "Locked by #{@node.lock_owner.login}\n" + - "Last modified #{@page.updated_at.to_s(:db)}" - - link_to 'Unlock', safe_path(:unlock_node_path, @node), :method => :put, :data => { :confirm => message } - end - - # Rails 6.1 workaround: content_path named helper returns RouteWithParams - # when called from within a catch-all glob route request context. - # Rails 6.1 workaround: named route helpers return RouteWithParams when called - # from within a catch-all glob route request context. - # Remove this method when upgrading to Rails 7.0+, where this is fixed. - def safe_path(name, *args) - Rails.application.routes.url_helpers.send(name, *args) - end + "Last modified #{@page.updated_at.to_fs(:db)}" - def content_path(page_path = nil, options = {}) - if page_path.is_a?(Hash) - options = page_path - page_path = options.delete(:page_path) - end - options[:locale] ||= params[:locale] || I18n.locale - Rails.application.routes.url_helpers.content_path( - Array(page_path).join("/").sub(/^\//, ""), - options - ) + link_to 'Unlock', unlock_node_path(@node), :method => :put, :data => { :confirm => message } end end diff --git a/app/helpers/nodes_helper.rb b/app/helpers/nodes_helper.rb index 204ad8a..c739ccd 100644 --- a/app/helpers/nodes_helper.rb +++ b/app/helpers/nodes_helper.rb @@ -31,7 +31,7 @@ module NodesHelper def event_information if @node.event - "#{@node.event.start_time.to_s(:db)} - #{@node.event.end_time.to_s(:db)} > " \ + "#{@node.event.start_time.to_fs(:db)} - #{@node.event.end_time.to_fs(:db)} > " \ "#{link_to 'show', event_path(@node.event)} " \ "#{link_to 'edit', edit_event_path(@node.event)}" else diff --git a/app/models/locked_by_another_user.rb b/app/models/locked_by_another_user.rb new file mode 100644 index 0000000..6f9e272 --- /dev/null +++ b/app/models/locked_by_another_user.rb @@ -0,0 +1 @@ +class LockedByAnotherUser < StandardError; end diff --git a/app/models/node.rb b/app/models/node.rb index f7a70d0..41c3867 100644 --- a/app/models/node.rb +++ b/app/models/node.rb @@ -73,7 +73,7 @@ class Node < ApplicationRecord raise( LockedByAnotherUser, "Page is locked by another user who is working on it! " \ - "Last modification: #{draft.updated_at.to_s(:db)}" + "Last modification: #{draft.updated_at.to_fs(:db)}" ) else lock_for! current_user @@ -211,6 +211,13 @@ class Node < ApplicationRecord self.created_at < new_id_format_date ? unique_path : id end + # TODO: restore full-text search once PostgreSQL is upgraded. + # The tsvector/plpgsql approach requires PostgreSQL 10+ with plpgsql available. + # For now, search is disabled to unblock the Rails 7.2 upgrade. + def self.search(term, _ = {}) + none + end + protected def lock_for! current_user self.lock_owner = current_user @@ -255,7 +262,3 @@ class Node < ApplicationRecord end end end - -class LockedByAnotherUser < StandardError; end - - diff --git a/app/views/admin/_recent_changes.html.erb b/app/views/admin/_recent_changes.html.erb index 300d088..88b5e93 100644 --- a/app/views/admin/_recent_changes.html.erb +++ b/app/views/admin/_recent_changes.html.erb @@ -13,7 +13,7 @@ <%= truncated_title_for_node node %> <%= node.unique_name %> <%= node.draft.user.login rescue "" %> - <%= node.updated_at.to_s(:db) %> + <%= node.updated_at.to_fs(:db) %> <%= link_to 'Show', node_path(node) %> <%= link_to "Revisions", revision_path(:id => node.id) %> diff --git a/app/views/content/_search.html.erb b/app/views/content/_search.html.erb index f732fca..aa91424 100644 --- a/app/views/content/_search.html.erb +++ b/app/views/content/_search.html.erb @@ -1,3 +1,3 @@ -<%= form_tag safe_path(:search_path), :method => 'get' do %> +<%= form_tag search_path, :method => 'get' do %>
<%= text_field_tag :search_term, params[:search_term], :placeholder => 'suchen', :type => 'search' %>
<% end %> diff --git a/app/views/content/_tags.html.erb b/app/views/content/_tags.html.erb index 387f51c..f0e7210 100644 --- a/app/views/content/_tags.html.erb +++ b/app/views/content/_tags.html.erb @@ -3,7 +3,7 @@

Tags

diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index 84dcdc6..c5cbf14 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -52,8 +52,8 @@ <% end %> diff --git a/config/application.rb b/config/application.rb index 1a7f32b..d92802f 100644 --- a/config/application.rb +++ b/config/application.rb @@ -54,6 +54,7 @@ module Cccms # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded. # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}')] config.i18n.default_locale = :de + config.i18n.fallbacks = { en: [:en, :de] } config.filter_parameters += [:password, :password_confirmation] config.serve_static_files = true diff --git a/config/environments/development.rb b/config/environments/development.rb index 8e2e7ef..43a6846 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -4,7 +4,7 @@ Cccms::Application.configure do # In the development environment your application's code is reloaded on # every request. This slows down response time but is perfect for development # since you don't have to restart the webserver when you make code changes. - config.cache_classes = false + config.enable_reloading = true # Log error messages when you accidentally call methods on nil. diff --git a/config/environments/test.rb b/config/environments/test.rb index a23c6d4..48aafe8 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,6 +1,6 @@ Cccms::Application.configure do - config.cache_classes = true + config.enable_reloading = false config.action_controller.consider_all_requests_local = true config.action_controller.perform_caching = false @@ -10,10 +10,8 @@ Cccms::Application.configure do config.action_mailer.delivery_method = :test config.active_support.deprecation = :log - config.active_support.test_order = :sorted config.eager_load = false config.public_file_server.enabled = true config.public_file_server.headers = { 'Cache-Control' => 'public, max-age=3600' } - config.assets.compile = true end diff --git a/config/initializers/i18n.rb b/config/initializers/i18n.rb deleted file mode 100644 index 0190f63..0000000 --- a/config/initializers/i18n.rb +++ /dev/null @@ -1,3 +0,0 @@ -require "i18n/backend/fallbacks" -I18n::Backend::Simple.send(:include, I18n::Backend::Fallbacks) -I18n.fallbacks.map "en" => ["de"] diff --git a/config/initializers/will_paginate_patch.rb b/config/initializers/will_paginate_patch.rb deleted file mode 100644 index d03c882..0000000 --- a/config/initializers/will_paginate_patch.rb +++ /dev/null @@ -1,13 +0,0 @@ -require 'will_paginate/view_helpers/action_view' - -WillPaginate::ActionView::LinkRenderer.class_eval do - def url(page) - path = @template.request.path - page_param = WillPaginate::PageNumber(page) - if page_param == 1 - path - else - "#{path}?#{@options[:param_name]}=#{page}" - end - end -end diff --git a/doc/20260626025705_add_search_vector_to_page_translations.rb.pending b/doc/20260626025705_add_search_vector_to_page_translations.rb.pending new file mode 100644 index 0000000..0747637 --- /dev/null +++ b/doc/20260626025705_add_search_vector_to_page_translations.rb.pending @@ -0,0 +1,47 @@ +class AddSearchVectorToPageTranslations < ActiveRecord::Migration[7.2] + def up + add_column :page_translations, :search_vector, :tsvector + + execute <<~SQL + UPDATE page_translations + SET search_vector = to_tsvector( + 'simple', + coalesce(title, '') || ' ' || + coalesce(abstract, '') || ' ' || + coalesce(body, '') + ) + SQL + + add_index :page_translations, :search_vector, + using: :gin, + name: 'index_page_translations_on_search_vector' + + execute <<~SQL + CREATE OR REPLACE FUNCTION page_translations_search_vector_update() + RETURNS trigger AS $$ + BEGIN + NEW.search_vector := to_tsvector( + 'simple', + coalesce(NEW.title, '') || ' ' || + coalesce(NEW.abstract, '') || ' ' || + coalesce(NEW.body, '') + ); + RETURN NEW; + END; + $$ LANGUAGE plpgsql; + + CREATE TRIGGER page_translations_search_vector_trigger + BEFORE INSERT OR UPDATE ON page_translations + FOR EACH ROW EXECUTE PROCEDURE page_translations_search_vector_update(); + SQL + end + + def down + execute <<~SQL + DROP TRIGGER IF EXISTS page_translations_search_vector_trigger ON page_translations; + DROP FUNCTION IF EXISTS page_translations_search_vector_update(); + SQL + remove_index :page_translations, name: 'index_page_translations_on_search_vector' + remove_column :page_translations, :search_vector + end +end -- cgit v1.3