Skip to content

refactor: finalize phase 6g concern decomposition#1183

Merged
texpert merged 18 commits into
masterfrom
fix/phase-6b-helper-concern-foundation
May 31, 2026
Merged

refactor: finalize phase 6g concern decomposition#1183
texpert merged 18 commits into
masterfrom
fix/phase-6b-helper-concern-foundation

Conversation

@texpert

@texpert texpert commented May 20, 2026

Copy link
Copy Markdown
Collaborator

What and Why

This PR finalizes the Phase 6G runtime concern decomposition of CamaleonController and follows up with a comprehensive set of bug fixes discovered during code review and manual testing of the refactored code.

Refactor goals (original commits):

  • Extract seven runtime concerns from CamaleonCms::CamaleonController into focused *RuntimeConcern / *LifecycleConcern modules under app/controllers/concerns/camaleon_cms/
  • Replace duplicated helper method bodies in concerns with include of the corresponding helper module (single source of truth)
  • Restore PluginRoutes.all_helpers controller-side inclusion so plugin helper methods remain reachable from controllers
  • Move back-compat ivars (@current_site, @user, @_front_breadcrumb, @_hooks_skip) out of shared view helpers (which Rails mixes into every view) and into the controller concerns exclusively, eliminating view ivar pollution while preserving backwards compatibility for gems/plugins/themes

Bug fixes (code-review follow-ups):

  • Fix NoMethodError (undefined method 'theme_asset') raised when plugin/theme hooks (e.g. a theme's on_install_theme) run in controller context: RuntimeShortcodeThemeConcern now includes CamaleonCms::ThemeHelper instead of duplicating only a subset of its methods, restoring theme_asset/theme_gem_asset aliases plus theme_view/theme_layout on the controller runtime stack
  • Fix NoMethodError (undefined method 'cama_captcha_tag') raised when shortcodes/forms rendered in controller context (e.g. the contact-form plugin) call captcha rendering helpers: SessionCaptchaRuntimeConcern now includes CamaleonCms::CaptchaHelper instead of re-implementing only the under-attack session counters
  • Fix NoMethodError (undefined method 'cama_content_append') raised when plugin hooks running in controller context (e.g. camaleon_post_order's on_list_post on the admin posts list) call the cama_content_* helpers: RuntimeHtmlContentConcern now includes CamaleonCms::ContentHelper instead of duplicating only cama_content_init/cama_content_state
  • Fix per-site theme view override (app/apps/themes/<site_id>/views) no longer being rendered on the frontend: FrontendController#configure_frontend_lookup_prefixes again appends the themes/<site_id>/views lookup prefix (guarded by Dir.exist?) ahead of the active theme prefix, so site-specific overrides take precedence
  • Fix ActionView::MissingTemplate raised when a plugin front controller renders one of its own templates (e.g. /store/plugins/ecommerce => render 'detail'): the LookupContext#find/#exists? override (added in fix: Phase 5 — Restore theme preview rendering and bootstrap missing nav menus #1181) dropped the plugin's init_plugin-prepended plugins/<name>/views/... lookup prefix. The override now only restricts to the current theme when all explicit prefixes are theme-scoped; otherwise it merges self.prefixes as before
  • Fix 404s for legacy thumbnails: older Camaleon releases stored raster thumbnails as PNG regardless of source extension (e.g. photo.jpg => thumb/photo-jpg.png). CamaleonCmsLocalUploader#file_parse and #objects now fall back to the legacy .png thumbnail when the computed thumb is missing on disk but a .png sibling exists (backwards-compatible)
  • Fix 404s for image files that never get a thumbnail (e.g. .ico favicons): cama_compat_legacy_thumb now falls back to the original file URL when neither the computed thumb nor a legacy .png sibling exists on disk
  • Fix 404 for the default theme's Genericons webfont: themes/default/assets/genericons/genericons.css referenced font files with relative url('font/...') paths that the browser resolves against the page root. The three @font-face references (.eot/.ttf/.svg) now use absolute asset-pipeline paths
  • Fix NoMethodError (undefined method 'to_sym' for nil) raised when editing a custom field group that contains a legacy/orphaned field whose stored options have no field_key: _get_items.html.erb now guards against a blank @key so the form renders instead of crashing
  • Fix frontend posts with localized (multi-language) slugs returning 404 (e.g. a slug stored as <!--:en-->sample-post<!--:--><!--:ru-->sample-post<!--:--> not matching /sample-post), while it worked on 2.9.2: restored the multi-language-aware CamaleonCms::PostDefault.find_by_slug finder at the post lookup sites and converted every slug lookup that should be locale-aware from find_by(slug:) to find_by_slug (frontend controller, decorators, Site#get_valid_post_slug, PostType#default_category, nav-menu/shortcode/custom-field call sites). Each call carries an inline # rubocop:disable Rails/DynamicFindBy for visibility
  • Fix Sprockets::Rails::Helper::AssetNotPrecompiledError for plugin/theme assets (sample: editing a post raised it for plugins/visibility_post/assets/js/form.js when the Sprockets manifest cache was cold/incomplete): on Sprockets >= 4 (with unknown_asset_fallback disabled) the gem's precompile declaration was gated to Sprockets 3 only and used a proc/glob, so on Sprockets 4 plugin/theme assets were not reliably declared as precompiled. The new CamaleonCms::AssetsPrecompile.logical_paths enumerates the concrete plugin/theme asset files from the real Sprockets load paths (config.assets.paths) and declares their exact logical paths in config.assets.precompile as plain strings — the canonical, Sprockets-version-agnostic form. This covers host, gem-bundled (e.g. visibility_post) and separately gem-packaged gem_mode plugins/themes (e.g. plugins/cama_contact_form/admin_editor.js), matching the reach of the old proc.

Added in the last 2 commits:

  • Fix: Restore object_class scoping on CustomField metas (67b3dbb)
  • Fix: Restore TinyMCE editor icons in development (8546f4f)
    • Fixed missing TinyMCE editor toolbar icons in development environments caused by Sprockets::Rails::AssetUrlProcessor incorrectly rewriting the TinyMCE skin's relative font URLs to invalid absolute paths.
    • Solution: Swapped the global AssetUrlProcessor with a TinymceSkinSafeAssetUrlProcessor subclass that selectively expands relative URLs for the TinyMCE skin to full logical asset paths before delegating to the original processor for digest-rewriting.
    • Bumped config.assets.version to '1.1' to invalidate stale cached assets.

Changes

Concern decomposition (64 files, ~2,950 insertions / 270 deletions)

Area Change
app/controllers/concerns/camaleon_cms/ 7 new runtime concerns: RequestContextConcern, SessionRuntimeConcern, SessionCaptchaRuntimeConcern, HookLifecycleConcern, RuntimeHtmlContentConcern, RuntimeShortcodeThemeConcern, RuntimeUploaderConcern
app/controllers/camaleon_cms/camaleon_controller.rb Slim include list; PluginRoutes.all_helpers inclusion restored
app/helpers/camaleon_cms/ Helpers made ivar-free; back-compat ivars moved to concerns
app/uploaders/camaleon_cms_local_uploader.rb Legacy thumbnail fallback (.png sibling, original URL)
app/controllers/camaleon_cms/frontend_controller.rb Restored themes/<site_id>/views lookup prefix
config/initializers/action_view.rb Fixed theme-scoped prefix guard to not drop plugin prefixes
app/views/.../custom_fields/_get_items.html.erb Guard against nil @key for orphaned fields
app/apps/themes/default/assets/genericons/genericons.css Absolute asset-pipeline font URLs
lib/camaleon_cms/assets_precompile.rb New helper for comprehensive plugin/theme asset precompile
config/initializers/assets.rb Patched AssetUrlProcessor for TinyMCE icons (development)
app/models/camaleon_cms/custom_field.rb Restored object_class scope for metas

Specs added / updated

  • spec/find_by_slug_usage_spec.rb — new organic, behavioural guard spec ensuring multi-language-aware slug lookups don't revert to find_by(slug:)
  • spec/lib/camaleon_cms/assets_precompile_spec.rb — new spec for comprehensive asset precompile enumeration (incl. gem_mode)
  • spec/controllers/concerns/camaleon_cms/ — 4 new concern specs (request context, session runtime, session captcha, runtime state aggregate)
  • spec/controllers/camaleon_cms/frontend_controller_lookup_prefixes_spec.rb — extended with site-override and plugin-prefix assertions
  • spec/initializers/action_view_lookup_context_spec.rb — new spec for the LookupContext override
  • spec/uploaders/local_uploader_spec.rb — 19 examples covering legacy thumb fallback, favicon fallback, and objects correction
  • spec/views/camaleon_cms/admin/settings/custom_fields/ — new view specs for _get_items and _render partials
  • spec/helpers/ — extended coverage for hooks, theme, nav-menu, session, shortcode helpers
  • spec/models/camaleon_cms/custom_field_metas_scope_spec.rb — new regression spec for meta ID collisions
  • spec/initializers/tinymce_asset_url_processor_spec.rb — new regression spec for TinyMCE skin font resolution

User-Visible Impact

Plugin/theme authors: back-compat ivars (@current_site, @user, @_front_breadcrumb, @_hooks_skip) are still assigned for templates and plugins — they are now set by controller concerns rather than helpers. No action required.

Upgraders: the bugs fixed above (missing methods in controller context, broken site-override views, legacy thumbnail 404s, plugin template lookup, Sprockets 4 incompatibilities, missing TinyMCE icons/frame) were regressions introduced by the Phase 6G refactor commits or pre-existing latent issues; all are resolved in this PR.

Test Results

Full suite (bin/rspec): 0 failures (15 pre-existing ImageMagick-dependent failures in environments without ImageMagick are unrelated to this PR). Organic guard specs (find_by_slug, assets precompile, TinyMCE, metas scope): 30 examples, 0 failures.

texpert and others added 14 commits May 18, 2026 18:54
Extract controller runtime concerns for request context, session runtime, hook lifecycle, and frontend visited-state wiring.\n\nFix admin custom field rendering fallback so missing/ string-key field_key values no longer resolve to an empty partial path, covering Footer Description and Seo Site.\n\nUpdate focused specs and phase plan notes for the combined Phase 6B scope.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
[skip ci]

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
- Restore PluginRoutes.all_helpers include in CamaleonController for plugin
  controller-side method availability.
- De-duplicate concerns by including SiteHelper into RequestContextConcern and
  SessionHelper/EmailHelper into SessionRuntimeConcern (single source of truth).
- Restore backwards-compatibility ivars (@current_site, @user,
  @_front_breadcrumb, @_hooks_skip honored as initial input) without making
  helper logic depend on them.
- short_code_helper: assign locals before resolve_shortcode_theme_asset so the
  AssetNotFound rescue cannot reference nil; broaden theme asset regex to
  accept a leading slash.
- .gitignore: ignore SQLite WAL/SHM files.

Co-authored-by: Junie <junie@jetbrains.com>
… compatibility (#1183)

Co-authored-by: Junie <junie@jetbrains.com>
@texpert texpert self-assigned this May 30, 2026
@texpert texpert requested review from brian-kephart and owen2345 May 30, 2026 21:16
texpert and others added 4 commits May 31, 2026 16:50
…ural guard spec (#1183)

Co-authored-by: Junie <junie@jetbrains.com>
Meta rows are keyed by (objectid, object_class). The #1173 polymorphic
meta refactor dropped the object_class scope, so a custom field whose
numeric id collided with another model's id read the wrong _default meta
and lost field_key, causing the TinyMCE editor field on Theme settings to
render as a plain text_box. Restore the explicit scopes and add a
regression spec.

Co-authored-by: Junie <junie@jetbrains.com>
…cessor

Co-authored-by: Junie <junie@jetbrains.com>
@texpert texpert merged commit 9a01b61 into master May 31, 2026
21 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant