Class: RubyCms::Generators::InstallGenerator
- Inherits:
-
Rails::Generators::Base
- Object
- Rails::Generators::Base
- RubyCms::Generators::InstallGenerator
- Defined in:
- lib/generators/ruby_cms/install_generator.rb
Constant Summary collapse
- NEXT_STEPS_MESSAGE =
<<~TEXT ✓ RubyCMS install complete. Next steps (if not already done): - rails db:migrate - rails ruby_cms:seed_permissions (includes manage_visitor_errors and manage_analytics) - rails ruby_cms:setup_admin (or: rails ruby_cms:grant_manage_admin email=you@example.com) - To seed content blocks from YAML: add content under content_blocks in config/locales/<locale>.yml, then run rails ruby_cms:content_blocks:seed (or call it from db/seeds.rb). Notes: - If the host uses /admin already, remove or change those routes. - Avoid root to: redirect("/admin") — use a real root or ruby_cms.unauthorized_redirect_path. - Review config/initializers/ruby_cms.rb (session, CSP). - RubyCMS admin styles are compiled once on install to app/assets/stylesheets/ruby_cms/admin.css. - Visit /admin (sign in as the admin you configured). Tracking: - Visitor errors: Automatically captured via ApplicationController (see /admin/visitor_errors) - Page views (Ahoy): Include RubyCms::PageTracking in your public controllers to track page views Example: class PagesController < ApplicationController; include RubyCms::PageTracking; end - Conversions: Call ahoy.track RubyCms::Analytics::Report::EVENT_CONVERSION, goal: "contact_form" from any controller action (e.g. after a successful form submit). Goal names are free-form strings. - Bot filtering: Set config.ruby_cms.analytics_visit_scope to exclude IPs/bots (see config/initializers/ruby_cms.rb) - Analytics: View visit/event data in Ahoy tables (ahoy_visits, ahoy_events) TEXT
- SKIP_VIEW_DIRS =
Directories to skip when scanning for page templates
%w[layouts shared mailers components admin].freeze
Instance Method Summary collapse
- #add_catch_all_route ⇒ Object
- #add_current_user_to_authentication ⇒ Object
- #add_page_tracking_to_home_controller ⇒ Object
- #add_permittable_to_user ⇒ Object
- #add_visitor_error_capture ⇒ Object
- #copy_fallback_css ⇒ Object
- #create_admin_layout ⇒ Object
- #create_initializer ⇒ Object
- #install_action_text ⇒ Object
- #install_ahoy ⇒ Object
- #install_ruby_ui ⇒ Object
- #install_tailwind ⇒ Object
- #mount_engine ⇒ Object
- #run_authentication ⇒ Object
- #run_migrate ⇒ Object
- #run_ruby_ui_install ⇒ Object
- #run_seed_permissions ⇒ Object
- #run_setup_admin ⇒ Object
- #show_next_steps ⇒ Object
- #verify_application_controller ⇒ Object
- #verify_auth ⇒ Object
- #verify_session_model ⇒ Object
- #verify_user_model ⇒ Object
Instance Method Details
#add_catch_all_route ⇒ Object
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 99 def add_catch_all_route routes_path = Rails.root.join("config/routes.rb") return unless routes_path.exist? content = File.read(routes_path) return if content.include?("ruby_cms/errors#not_found") # Add catch-all route at the end of the routes block (before final 'end') catch_all = <<~ROUTE # RubyCMS: Catch-all route for 404 error tracking (must be LAST) match "*path", to: "ruby_cms/errors#not_found", via: :all, constraints: ->(req) { !req.path.start_with?("/rails/", "/assets/") } ROUTE # Insert before the last 'end' in the file gsub_file routes_path, /(\nend)\s*\z/ do "#{catch_all}end\n" end say "✓ Catch-all route: Added for 404 error tracking", :green rescue StandardError => e say "⚠ Catch-all route: Could not add automatically: #{e.}. " \ "Add manually at the END of routes.rb:\n " \ 'match "*path", to: "ruby_cms/errors#not_found", via: :all, ' \ 'constraints: ->(req) { !req.path.start_with?("/rails/", "/assets/") }', :yellow end |
#add_current_user_to_authentication ⇒ Object
141 142 143 144 145 146 147 148 149 150 151 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 141 def add_current_user_to_authentication auth_path = Rails.root.join("app/controllers/concerns/authentication.rb") return unless auth_path.exist? return if File.read(auth_path).include?("def current_user") gsub_file auth_path, " helper_method :authenticated?\n", " helper_method :authenticated?, :current_user\n" inject_into_file auth_path, after: " private\n" do " def current_user\n Current.user\n end\n\n" end end |
#add_page_tracking_to_home_controller ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 174 def add_page_tracking_to_home_controller home_path = Rails.root.join("app/controllers/home_controller.rb") return unless home_path.exist? content = File.read(home_path) return if content.include?("RubyCms::PageTracking") inject_into_file home_path, after: /class HomeController.*\n/ do " include RubyCms::PageTracking\n" end say "✓ Page tracking: Added RubyCms::PageTracking to HomeController", :green rescue StandardError => e say "⚠ Page tracking: Could not add to HomeController: #{e.}. " \ "Add manually: include RubyCms::PageTracking", :yellow end |
#add_permittable_to_user ⇒ Object
127 128 129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 127 def add_permittable_to_user user_path = Rails.root.join("app/models/user.rb") unless File.exist?(user_path) say "Skipping User: app/models/user.rb not found.", :yellow return end return if File.read(user_path).include?("RubyCms::Permittable") inject_into_file user_path, after: /class User .*\n/ do " include RubyCms::Permittable\n" end end |
#add_visitor_error_capture ⇒ Object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 153 def add_visitor_error_capture ac_path = Rails.root.join("app/controllers/application_controller.rb") return unless ac_path.exist? content = File.read(ac_path) return if content.include?("RubyCms::VisitorErrorCapture") to_inject = " include RubyCms::VisitorErrorCapture\n" to_inject += " rescue_from StandardError, with: :handle_visitor_error\n" \ unless content.include?("rescue_from StandardError") inject_into_file ac_path, after: /class ApplicationController.*\n/ do to_inject end say "✓ Visitor error capture: Added to ApplicationController", :green rescue StandardError => e say "⚠ Visitor error capture: Could not add to ApplicationController: #{e.}. " \ "Add manually: include RubyCms::VisitorErrorCapture and rescue_from StandardError, with: :handle_visitor_error", :yellow end |
#copy_fallback_css ⇒ Object
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 192 def copy_fallback_css src_dir = RubyCms::Engine.root.join("app/assets/stylesheets/ruby_cms") dest_dir = Rails.root.join("app/assets/stylesheets/ruby_cms") return unless src_dir.exist? FileUtils.mkdir_p(dest_dir) copy_admin_css(dest_dir) # Don't copy component files - only the compiled admin.css is needed # copy_components_css(src_dir, dest_dir) say "✓ Task css/copy: Combined component CSS into " \ "app/assets/stylesheets/ruby_cms/admin.css", :green rescue StandardError => e say "⚠ Task css/copy: Could not copy CSS files: #{e.}.", :yellow end |
#create_admin_layout ⇒ Object
208 209 210 211 212 213 214 215 216 217 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 208 def create_admin_layout layout_path = Rails.root.join("app/views/layouts/admin.html.erb") return if File.exist?(layout_path) template "admin.html.erb", layout_path.to_s say "✓ Layout admin: Created app/views/layouts/admin.html.erb", :green rescue StandardError => e say "⚠ Layout admin: Could not create admin.html.erb: #{e.}. " \ "Create it manually using the RubyCMS template.", :yellow end |
#create_initializer ⇒ Object
90 91 92 93 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 90 def create_initializer @detected_pages = detect_page_templates template "ruby_cms.rb", "config/initializers/ruby_cms.rb" end |
#install_action_text ⇒ Object
274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 274 def install_action_text migrate_dir = Rails.root.join("db/migrate") return unless migrate_dir.directory? if action_text_already_installed?(migrate_dir) say "ℹ Task action_text: Existing Action Text setup detected. Skipping action_text:install.", :cyan else say "ℹ Task action_text: Installing Action Text for rich text/image content blocks.", :cyan run "bin/rails action_text:install" say "✓ Task action_text: Installed Action Text", :green end configure_action_text_assets rescue StandardError => e say "⚠ Task action_text: Could not install: #{e.}. Rich text will be disabled.", :yellow end |
#install_ahoy ⇒ Object
255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 255 def install_ahoy if ahoy_already_installed? say "ℹ Task ahoy: Existing Ahoy setup detected (tables or migrations). Skipping ahoy:install.", :cyan configure_ahoy_server_side_only return end say "ℹ Task ahoy: Installing Ahoy for visit/event tracking.", :cyan run "bin/rails generate ahoy:install" add_ahoy_security_fields_migration configure_ahoy_server_side_only say "✓ Task ahoy: Installed Ahoy (visits, events, tracking)", :green rescue StandardError => e say "⚠ Task ahoy: Could not install: #{e.}. " \ "Run 'rails g ahoy:install' manually.", :yellow end |
#install_ruby_ui ⇒ Object
503 504 505 506 507 508 509 510 511 512 513 514 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 503 def install_ruby_ui gemfile = Rails.root.join("Gemfile") gemfile_content = File.read(gemfile) return if ruby_ui_in_gemfile?(gemfile_content) add_ruby_ui_gem rescue StandardError => e say "⚠ Task ruby_ui: Could not add: #{e.}. " \ "Run 'bundle add ruby_ui --group development --require false' manually.", :yellow nil end |
#install_tailwind ⇒ Object
460 461 462 463 464 465 466 467 468 469 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 460 def install_tailwind gemfile = Rails.root.join("Gemfile") tailwind_css = detect_tailwind_entry_css_path install_tailwind_if_needed(gemfile, tailwind_css) configure_tailwind(tailwind_css) rescue StandardError => e say "⚠ Task tailwind: Could not install: #{e.}. Add tailwindcss-rails manually.", :yellow end |
#mount_engine ⇒ Object
95 96 97 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 95 def mount_engine route 'mount RubyCms::Engine => "/"' end |
#run_authentication ⇒ Object
37 38 39 40 41 42 43 44 45 46 47 48 49 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 37 def run_authentication user_path = Rails.root.join("app/models/user.rb") return if File.exist?(user_path) say "ℹ Task authentication: User model not found. " \ "Running 'rails g authentication' (Rails 8+).", :cyan @authentication_attempted = true run "bin/rails generate authentication" run "bundle install" rescue StandardError => e say "⚠ Could not run 'rails g authentication': #{e.}.", :yellow say " On Rails 8+, run 'rails g authentication' and 'bundle install' manually.", :yellow end |
#run_migrate ⇒ Object
1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 1004 def run_migrate say "ℹ Task db:migrate: Running db:migrate.", :cyan success = run("bin/rails db:migrate") raise "db:migrate failed" unless success say "✓ Task db:migrate: Completed", :green rescue StandardError => e say "⚠ Task db:migrate: Failed: #{e.}. Run rails db:create db:migrate if needed.", :yellow end |
#run_ruby_ui_install ⇒ Object
516 517 518 519 520 521 522 523 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 516 def run_ruby_ui_install gemfile = Rails.root.join("Gemfile") gemfile_content = File.read(gemfile) return unless ruby_ui_in_gemfile?(gemfile_content) return if ruby_ui_already_installed? install_ruby_ui_generator end |
#run_seed_permissions ⇒ Object
1015 1016 1017 1018 1019 1020 1021 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 1015 def say "ℹ Task permissions: Seeding RubyCMS permissions.", :cyan success = (success) rescue StandardError => e (e) end |
#run_setup_admin ⇒ Object
1023 1024 1025 1026 1027 1028 1029 1030 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 1023 def run_setup_admin return if skip_setup_admin_due_to_existing_admin? return unless setup_admin_tty? run_setup_admin_task rescue StandardError => e say_setup_admin_error(e) end |
#show_next_steps ⇒ Object
1154 1155 1156 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 1154 def show_next_steps say NEXT_STEPS_MESSAGE, :green end |
#verify_application_controller ⇒ Object
76 77 78 79 80 81 82 83 84 85 86 87 88 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 76 def verify_application_controller ac_path = Rails.root.join("app/controllers/application_controller.rb") return unless ac_path.exist? content = File.read(ac_path) return if content.include?("include Authentication") return if @authentication_warning_shown say "ℹ Task authentication: ApplicationController does not include " \ "Authentication. Ensure /admin is protected.", :yellow @authentication_warning_shown = true end |
#verify_auth ⇒ Object
51 52 53 54 55 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 51 def verify_auth verify_user_model verify_session_model verify_application_controller end |
#verify_session_model ⇒ Object
68 69 70 71 72 73 74 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 68 def verify_session_model return if defined?(::Session) say "ℹ Task authentication: Session model not found. " \ "The host app should provide authentication.", :yellow end |
#verify_user_model ⇒ Object
57 58 59 60 61 62 63 64 65 66 |
# File 'lib/generators/ruby_cms/install_generator.rb', line 57 def verify_user_model return if defined?(::User) = if @authentication_attempted "Run 'rails db:migrate' if the authentication generator succeeded." else "User model not found. Run 'rails g authentication' before using /admin." end say "ℹ Task authentication: #{}", :yellow end |