From ca670e8d43238f741c8cc7c5b0c6256af7f1540e Mon Sep 17 00:00:00 2001 From: Juani Villarejo Date: Wed, 8 May 2024 18:08:33 -0300 Subject: [PATCH 1/2] Adds support for propshaft (#2) --- lib/roadie/rails.rb | 1 + lib/roadie/rails/asset_propshaft_provider.rb | 41 +++++++ lib/roadie/rails/railtie.rb | 7 +- spec/integration_spec.rb | 86 ++++++++++++- .../railsapps/rails_71_with_propshaft/Gemfile | 11 ++ .../rails_71_with_propshaft/Rakefile | 6 + .../app/assets/builds/.gitkeep | 0 .../app/assets/images/rails.png | Bin 0 -> 6646 bytes .../app/assets/stylesheets/email.css | 2 + .../app/mailers/auto_mailer.rb | 30 +++++ .../app/mailers/mailer.rb | 20 +++ .../views/auto_mailer/normal_email.html.erb | 11 ++ .../app/views/auto_mailer/normal_email.text | 1 + .../app/views/mailer/normal_email.html.erb | 11 ++ .../app/views/mailer/normal_email.text | 1 + .../rails_71_with_propshaft/bin/bundle | 114 ++++++++++++++++++ .../rails_71_with_propshaft/bin/rails | 4 + .../rails_71_with_propshaft/bin/rake | 4 + .../rails_71_with_propshaft/bin/setup | 25 ++++ .../rails_71_with_propshaft/config.ru | 6 + .../config/application.rb | 37 ++++++ .../rails_71_with_propshaft/config/boot.rb | 4 + .../config/environment.rb | 5 + .../config/environments/development.rb | 58 +++++++++ .../initializers/backtrace_silencers.rb | 8 ++ .../initializers/content_security_policy.rb | 27 +++++ .../initializers/filter_parameter_logging.rb | 6 + .../config/initializers/inflections.rb | 16 +++ .../config/initializers/mime_types.rb | 4 + .../config/initializers/permissions_policy.rb | 11 ++ .../config/initializers/wrap_parameters.rb | 9 ++ .../rails_71_with_propshaft/config/routes.rb | 6 + spec/support/rails_app.rb | 12 +- 33 files changed, 578 insertions(+), 6 deletions(-) create mode 100644 lib/roadie/rails/asset_propshaft_provider.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/Gemfile create mode 100644 spec/railsapps/rails_71_with_propshaft/Rakefile create mode 100644 spec/railsapps/rails_71_with_propshaft/app/assets/builds/.gitkeep create mode 100644 spec/railsapps/rails_71_with_propshaft/app/assets/images/rails.png create mode 100644 spec/railsapps/rails_71_with_propshaft/app/assets/stylesheets/email.css create mode 100644 spec/railsapps/rails_71_with_propshaft/app/mailers/auto_mailer.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/app/mailers/mailer.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.html.erb create mode 100644 spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.text create mode 100644 spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.html.erb create mode 100644 spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.text create mode 100755 spec/railsapps/rails_71_with_propshaft/bin/bundle create mode 100755 spec/railsapps/rails_71_with_propshaft/bin/rails create mode 100755 spec/railsapps/rails_71_with_propshaft/bin/rake create mode 100755 spec/railsapps/rails_71_with_propshaft/bin/setup create mode 100644 spec/railsapps/rails_71_with_propshaft/config.ru create mode 100644 spec/railsapps/rails_71_with_propshaft/config/application.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/boot.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/environment.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/environments/development.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/backtrace_silencers.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/content_security_policy.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/filter_parameter_logging.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/inflections.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/mime_types.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/permissions_policy.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/initializers/wrap_parameters.rb create mode 100644 spec/railsapps/rails_71_with_propshaft/config/routes.rb diff --git a/lib/roadie/rails.rb b/lib/roadie/rails.rb index 0373623..58326d4 100644 --- a/lib/roadie/rails.rb +++ b/lib/roadie/rails.rb @@ -15,6 +15,7 @@ module Rails require "roadie/rails/mail_inliner" require "roadie/rails/asset_pipeline_provider" +require "roadie/rails/asset_propshaft_provider" require "roadie/rails/mailer" diff --git a/lib/roadie/rails/asset_propshaft_provider.rb b/lib/roadie/rails/asset_propshaft_provider.rb new file mode 100644 index 0000000..57e3dc3 --- /dev/null +++ b/lib/roadie/rails/asset_propshaft_provider.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module Roadie + module Rails + class AssetPropshaftProvider + include Roadie::AssetProvider + + def initialize(assembly) + @assembly = assembly + @stylesheets = {} + end + + def find_stylesheet(stylesheet_asset_path) + stylesheet = @stylesheets[stylesheet_asset_path] + return stylesheet if stylesheet.present? + + path, digest = extract_path_and_digest(stylesheet_asset_path) + + asset = @assembly.load_path.find(path) + if asset.present? && asset.fresh?(digest) + compiled_content = @assembly.compilers.compile(asset) + + stylesheet = Stylesheet.new(stylesheet_asset_path, compiled_content.force_encoding("UTF-8")) + @stylesheets[stylesheet_asset_path] = stylesheet + end + + stylesheet + end + + private + + def extract_path_and_digest(stylesheet_asset_path) + full_path = stylesheet_asset_path.sub(%r{#{::Rails.configuration.assets.prefix}/}, "") + digest = full_path[/-([0-9a-zA-Z]{7,128})\.(?!digested)[^.]+\z/, 1] + path = digest ? full_path.sub("-#{digest}", "") : full_path + + [path, digest] + end + end + end +end diff --git a/lib/roadie/rails/railtie.rb b/lib/roadie/rails/railtie.rb index b40877a..45e546c 100644 --- a/lib/roadie/rails/railtie.rb +++ b/lib/roadie/rails/railtie.rb @@ -14,8 +14,11 @@ class Railtie < ::Rails::Railtie if app.config.respond_to?(:assets) && app.config.assets if app.assets - config.roadie.asset_providers << - AssetPipelineProvider.new(app.assets) + config.roadie.asset_providers << AssetPipelineProvider.new(app.assets) + elsif defined?(Propshaft) + config.after_initialize do |app| + config.roadie.asset_providers << AssetPropshaftProvider.new(app.assets) + end else app.config.assets.configure do |env| config.roadie.asset_providers << diff --git a/spec/integration_spec.rb b/spec/integration_spec.rb index d685a67..6f0ac0a 100644 --- a/spec/integration_spec.rb +++ b/spec/integration_spec.rb @@ -15,7 +15,8 @@ def parse_html_in_email(mail) RailsApp.new("Rails 6.0", "rails_60", max_ruby_version: "3.0"), RailsApp.new("Rails 6.1", "rails_61", max_ruby_version: "3.0"), RailsApp.new("Rails 7.0", "rails_70", min_ruby_version: "2.7"), - RailsApp.new("Rails 7.1", "rails_71", min_ruby_version: "2.7") + RailsApp.new("Rails 7.1 with sprockets", "rails_71", min_ruby_version: "2.7"), + RailsApp.new("Rails 7.1 with propshaft", "rails_71_with_propshaft", min_ruby_version: "2.7", asset_pipeline: :propshaft) ] shared_examples "generates valid email" do |message| @@ -47,7 +48,7 @@ def parse_html_in_email(mail) end end - rails_apps.select(&:supported?).each do |app| + rails_apps.select(&:supported?).select(&:with_sprockets?).each do |app| describe "with #{app}" do before { app.reset } @@ -94,4 +95,85 @@ def parse_html_in_email(mail) end end end + + rails_apps.select(&:supported?).select(&:with_propshaft?).each do |app| + describe "with #{app}" do + before { app.reset } + + it "inlines styles for multipart emails" do + email = app.read_email(:normal_email) + + expect(email.to).to eq(["example@example.org"]) + expect(email.from).to eq(["john@example.com"]) + expect(email).to have(2).parts + + expect(email.text_part.body.decoded).not_to match(/<.*>/) + + html = email.html_part.body.decoded + expect(html).to include " "green" + ).at_selector("body") + + expected_image_url = + "https://example.app.org/assets/rails-fbe4356d4aa42b95f211236439f3e675a5f9a7e6.png" + + expect(document).to have_styling( + "background" => "url(\"#{expected_image_url}\")" + ).at_selector(".image") + + # If we deliver mails we can catch weird problems with headers being + # invalid + email.delivery_method :test + email.deliver + end + + it "inlines styles with automatic mailer" do + email = app.read_delivered_email(:normal_email) + + expect(email.to).to eq(["example@example.org"]) + expect(email.from).to eq(["john@example.com"]) + expect(email).to have(2).parts + + expect(email.text_part.body.decoded).not_to match(/<.*>/) + + html = email.html_part.body.decoded + expect(html).to include " "green" + ).at_selector("body") + + expected_image_url = + "https://example.app.org/assets/rails-fbe4356d4aa42b95f211236439f3e675a5f9a7e6.png" + + expect(document).to have_styling( + "background" => "url(\"#{expected_image_url}\")" + ).at_selector(".image") + + # If we deliver mails we can catch weird problems with headers being + # invalid + email.delivery_method :test + email.deliver + end + + it "has a AssetPropshaftProvider together with a FilesystemProvider" do + expect(app.read_providers).to eq( + %w[ + Roadie::FilesystemProvider + Roadie::Rails::AssetPropshaftProvider + ] + ) + end + end + end end diff --git a/spec/railsapps/rails_71_with_propshaft/Gemfile b/spec/railsapps/rails_71_with_propshaft/Gemfile new file mode 100644 index 0000000..9aa12cf --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/Gemfile @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +source "https://rubygems.org" + +# Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" +gem "rails", "~> 7.1.0" + +# Reduces boot times through caching; required in config/boot.rb +gem "bootsnap", ">= 1.4.4", require: false +gem "propshaft" +gem "roadie-rails", path: "../../.." diff --git a/spec/railsapps/rails_71_with_propshaft/Rakefile b/spec/railsapps/rails_71_with_propshaft/Rakefile new file mode 100644 index 0000000..9a5ea73 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/Rakefile @@ -0,0 +1,6 @@ +# Add your own tasks in files placed in lib/tasks ending in .rake, +# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake. + +require_relative "config/application" + +Rails.application.load_tasks diff --git a/spec/railsapps/rails_71_with_propshaft/app/assets/builds/.gitkeep b/spec/railsapps/rails_71_with_propshaft/app/assets/builds/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/spec/railsapps/rails_71_with_propshaft/app/assets/images/rails.png b/spec/railsapps/rails_71_with_propshaft/app/assets/images/rails.png new file mode 100644 index 0000000000000000000000000000000000000000..d5edc04e65f555e3ba4dcdaad39dc352e75b575e GIT binary patch literal 6646 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 AQ~&?~ literal 0 HcmV?d00001 diff --git a/spec/railsapps/rails_71_with_propshaft/app/assets/stylesheets/email.css b/spec/railsapps/rails_71_with_propshaft/app/assets/stylesheets/email.css new file mode 100644 index 0000000..e561fb3 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/assets/stylesheets/email.css @@ -0,0 +1,2 @@ +body { background-color: green; } +.image { background: url("/rails.png"); } diff --git a/spec/railsapps/rails_71_with_propshaft/app/mailers/auto_mailer.rb b/spec/railsapps/rails_71_with_propshaft/app/mailers/auto_mailer.rb new file mode 100644 index 0000000..50256c1 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/mailers/auto_mailer.rb @@ -0,0 +1,30 @@ +# frozen_string_literal: true + +class AutoMailer < ActionMailer::Base + include Roadie::Rails::Automatic + + default from: "john@example.com" + + def normal_email + generate_email + end + + def disabled_email + generate_email + end + + private + + def roadie_options + unless /disabled/.match?(action_name) + super.combine(url_options: {protocol: "https"}) + end + end + + def generate_email + mail(to: "example@example.org", subject: "Notification for you") do |format| + format.html { render :normal_email } + format.text { render :normal_email } + end + end +end diff --git a/spec/railsapps/rails_71_with_propshaft/app/mailers/mailer.rb b/spec/railsapps/rails_71_with_propshaft/app/mailers/mailer.rb new file mode 100644 index 0000000..88e243b --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/mailers/mailer.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +class Mailer < ActionMailer::Base + include Roadie::Rails::Mailer + + default from: "john@example.com" + + def normal_email + roadie_mail(to: "example@example.org", subject: "Notification for you") do |format| + format.html + format.text + end + end + + private + + def roadie_options + super.combine(url_options: {protocol: "https"}) + end +end diff --git a/spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.html.erb b/spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.html.erb new file mode 100644 index 0000000..cf672b4 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.html.erb @@ -0,0 +1,11 @@ + + + + + <%= stylesheet_link_tag "email" %> + + +

Normal email

+
+ + diff --git a/spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.text b/spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.text new file mode 100644 index 0000000..302fdf4 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/views/auto_mailer/normal_email.text @@ -0,0 +1 @@ +Normal email diff --git a/spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.html.erb b/spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.html.erb new file mode 100644 index 0000000..cf672b4 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.html.erb @@ -0,0 +1,11 @@ + + + + + <%= stylesheet_link_tag "email" %> + + +

Normal email

+
+ + diff --git a/spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.text b/spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.text new file mode 100644 index 0000000..302fdf4 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/app/views/mailer/normal_email.text @@ -0,0 +1 @@ +Normal email diff --git a/spec/railsapps/rails_71_with_propshaft/bin/bundle b/spec/railsapps/rails_71_with_propshaft/bin/bundle new file mode 100755 index 0000000..61e4358 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/bin/bundle @@ -0,0 +1,114 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +# +# This file was generated by Bundler. +# +# The application 'bundle' is installed as part of a gem, and +# this file is here to facilitate running it. +# + +require "rubygems" + +m = Module.new do + module_function + + def invoked_as_script? + File.expand_path($0) == File.expand_path(__FILE__) + end + + def env_var_version + ENV["BUNDLER_VERSION"] + end + + def cli_arg_version + return unless invoked_as_script? # don't want to hijack other binstubs + return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update` + bundler_version = nil + update_index = nil + ARGV.each_with_index do |a, i| + if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN + bundler_version = a + end + next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/o + bundler_version = $1 + update_index = i + end + bundler_version + end + + def gemfile + gemfile = ENV["BUNDLE_GEMFILE"] + return gemfile if gemfile && !gemfile.empty? + + File.expand_path("../../Gemfile", __FILE__) + end + + def lockfile + lockfile = + case File.basename(gemfile) + when "gems.rb" then gemfile.sub(/\.rb$/, gemfile) + else "#{gemfile}.lock" + end + File.expand_path(lockfile) + end + + def lockfile_version + return unless File.file?(lockfile) + lockfile_contents = File.read(lockfile) + return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/o + Regexp.last_match(1) + end + + def bundler_requirement + @bundler_requirement ||= + env_var_version || cli_arg_version || + bundler_requirement_for(lockfile_version) + end + + def bundler_requirement_for(version) + return "#{Gem::Requirement.default}.a" unless version + + bundler_gem_version = Gem::Version.new(version) + + requirement = bundler_gem_version.approximate_recommendation + + return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0") + + requirement += ".a" if bundler_gem_version.prerelease? + + requirement + end + + def load_bundler! + ENV["BUNDLE_GEMFILE"] ||= gemfile + + activate_bundler + end + + def activate_bundler + gem_error = activation_error_handling do + gem "bundler", bundler_requirement + end + return if gem_error.nil? + require_error = activation_error_handling do + require "bundler/version" + end + return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION)) + warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`" + exit 42 + end + + def activation_error_handling + yield + nil + rescue StandardError, LoadError => e + e + end +end + +m.load_bundler! + +if m.invoked_as_script? + load Gem.bin_path("bundler", "bundle") +end diff --git a/spec/railsapps/rails_71_with_propshaft/bin/rails b/spec/railsapps/rails_71_with_propshaft/bin/rails new file mode 100755 index 0000000..efc0377 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/bin/rails @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +APP_PATH = File.expand_path("../config/application", __dir__) +require_relative "../config/boot" +require "rails/commands" diff --git a/spec/railsapps/rails_71_with_propshaft/bin/rake b/spec/railsapps/rails_71_with_propshaft/bin/rake new file mode 100755 index 0000000..4fbf10b --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/bin/rake @@ -0,0 +1,4 @@ +#!/usr/bin/env ruby +require_relative "../config/boot" +require "rake" +Rake.application.run diff --git a/spec/railsapps/rails_71_with_propshaft/bin/setup b/spec/railsapps/rails_71_with_propshaft/bin/setup new file mode 100755 index 0000000..57b65c8 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/bin/setup @@ -0,0 +1,25 @@ +#!/usr/bin/env ruby +require "fileutils" + +# path to your application root. +APP_ROOT = File.expand_path("..", __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +FileUtils.chdir APP_ROOT do + # This script is a way to set up or update your development environment automatically. + # This script is idempotent, so that you can run it at any time and get an expectable outcome. + # Add necessary setup steps to this file. + + puts "== Installing dependencies ==" + system! "gem install bundler --conservative" + system("bundle check") || system!("bundle install") + + puts "\n== Removing old logs and tempfiles ==" + system! "bin/rails log:clear tmp:clear" + + puts "\n== Restarting application server ==" + system! "bin/rails restart" +end diff --git a/spec/railsapps/rails_71_with_propshaft/config.ru b/spec/railsapps/rails_71_with_propshaft/config.ru new file mode 100644 index 0000000..4a3c09a --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config.ru @@ -0,0 +1,6 @@ +# This file is used by Rack-based servers to start the application. + +require_relative "config/environment" + +run Rails.application +Rails.application.load_server diff --git a/spec/railsapps/rails_71_with_propshaft/config/application.rb b/spec/railsapps/rails_71_with_propshaft/config/application.rb new file mode 100644 index 0000000..b1b2abc --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/application.rb @@ -0,0 +1,37 @@ +require_relative "boot" + +require "rails" +# Pick the frameworks you want: +# require "active_model/railtie" +# require "active_job/railtie" +# require "active_record/railtie" +# require "active_storage/engine" +require "action_controller/railtie" +require "action_mailer/railtie" +# require "action_mailbox/engine" +# require "action_text/engine" +require "action_view/railtie" +# require "action_cable/engine" +# require "rails/test_unit/railtie" + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) +require "propshaft" + +module Rails70 + class Application < Rails::Application + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 7.1 + + # Configuration for the application, engines, and railties goes here. + # + # These settings can be overridden in specific environments using the files + # in config/environments, which are processed later. + # + # config.time_zone = "Central Time (US & Canada)" + # config.eager_load_paths << Rails.root.join("extras") + config.roadie.url_options = {host: "example.app.org"} + config.action_view.preload_links_header = false + end +end diff --git a/spec/railsapps/rails_71_with_propshaft/config/boot.rb b/spec/railsapps/rails_71_with_propshaft/config/boot.rb new file mode 100644 index 0000000..988a5dd --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/boot.rb @@ -0,0 +1,4 @@ +ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../Gemfile", __dir__) + +require "bundler/setup" # Set up gems listed in the Gemfile. +require "bootsnap/setup" # Speed up boot time by caching expensive operations. diff --git a/spec/railsapps/rails_71_with_propshaft/config/environment.rb b/spec/railsapps/rails_71_with_propshaft/config/environment.rb new file mode 100644 index 0000000..cac5315 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/environment.rb @@ -0,0 +1,5 @@ +# Load the Rails application. +require_relative "application" + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/spec/railsapps/rails_71_with_propshaft/config/environments/development.rb b/spec/railsapps/rails_71_with_propshaft/config/environments/development.rb new file mode 100644 index 0000000..af4af7f --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/environments/development.rb @@ -0,0 +1,58 @@ +require "active_support/core_ext/integer/time" + +Rails.application.configure do + # Settings specified here will take precedence over those in config/application.rb. + + # In the development environment your application's code is reloaded any time + # it changes. This slows down response time but is perfect for development + # since you don't have to restart the web server when you make code changes. + config.cache_classes = false + + # Do not eager load code on boot. + config.eager_load = false + + # Show full error reports. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join("tmp/caching-dev.txt").exist? + config.action_controller.perform_caching = true + config.action_controller.enable_fragment_cache_logging = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + "Cache-Control" => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = false + + # Print deprecation notices to the Rails logger. + config.active_support.deprecation = :log + + # Raise exceptions for disallowed deprecations. + config.active_support.disallowed_deprecation = :raise + + # Tell Active Support which deprecation messages to disallow. + config.active_support.disallowed_deprecation_warnings = [] + + # Suppress logger output for asset requests. + config.assets.quiet = true + + # Raises error for missing translations. + # config.i18n.raise_on_missing_translations = true + + # Annotate rendered view with file names. + # config.action_view.annotate_rendered_view_with_filenames = true + + # Uncomment if you wish to allow Action Cable access from any origin. + # config.action_cable.disable_request_forgery_protection = true +end diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/backtrace_silencers.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/backtrace_silencers.rb new file mode 100644 index 0000000..33699c3 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/backtrace_silencers.rb @@ -0,0 +1,8 @@ +# Be sure to restart your server when you modify this file. + +# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces. +# Rails.backtrace_cleaner.add_silencer { |line| /my_noisy_library/.match?(line) } + +# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code +# by setting BACKTRACE=1 before calling your invocation, like "BACKTRACE=1 ./bin/rails runner 'MyClass.perform'". +Rails.backtrace_cleaner.remove_silencers! if ENV["BACKTRACE"] diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/content_security_policy.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/content_security_policy.rb new file mode 100644 index 0000000..d988237 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/content_security_policy.rb @@ -0,0 +1,27 @@ +# Be sure to restart your server when you modify this file. + +# Define an application-wide content security policy +# For further information see the following documentation +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy + +# Rails.application.config.content_security_policy do |policy| +# policy.default_src :self, :https +# policy.font_src :self, :https, :data +# policy.img_src :self, :https, :data +# policy.object_src :none +# policy.script_src :self, :https +# policy.style_src :self, :https +# # Specify URI for violation reports +# # policy.report_uri "/csp-violation-report-endpoint" +# end + +# If you are using UJS then enable automatic nonce generation +# Rails.application.config.content_security_policy_nonce_generator = -> request { SecureRandom.base64(16) } + +# Set the nonce only to specific directives +# Rails.application.config.content_security_policy_nonce_directives = %w(script-src) + +# Report CSP violations to a specified URI +# For further information see the following documentation: +# https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy-Report-Only +# Rails.application.config.content_security_policy_report_only = true diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/filter_parameter_logging.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/filter_parameter_logging.rb new file mode 100644 index 0000000..4b34a03 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/filter_parameter_logging.rb @@ -0,0 +1,6 @@ +# Be sure to restart your server when you modify this file. + +# Configure sensitive parameters which will be filtered from the log file. +Rails.application.config.filter_parameters += [ + :passw, :secret, :token, :_key, :crypt, :salt, :certificate, :otp, :ssn +] diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/inflections.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/inflections.rb new file mode 100644 index 0000000..3860f65 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/inflections.rb @@ -0,0 +1,16 @@ +# Be sure to restart your server when you modify this file. + +# Add new inflection rules using the following format. Inflections +# are locale specific, and you may define rules for as many different +# locales as you wish. All of these examples are active by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.plural /^(ox)$/i, "\\1en" +# inflect.singular /^(ox)en/i, "\\1" +# inflect.irregular "person", "people" +# inflect.uncountable %w( fish sheep ) +# end + +# These inflection rules are supported but not enabled by default: +# ActiveSupport::Inflector.inflections(:en) do |inflect| +# inflect.acronym "RESTful" +# end diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/mime_types.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/mime_types.rb new file mode 100644 index 0000000..dc18996 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/mime_types.rb @@ -0,0 +1,4 @@ +# Be sure to restart your server when you modify this file. + +# Add new mime types for use in respond_to blocks: +# Mime::Type.register "text/richtext", :rtf diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/permissions_policy.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/permissions_policy.rb new file mode 100644 index 0000000..00f64d7 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/permissions_policy.rb @@ -0,0 +1,11 @@ +# Define an application-wide HTTP permissions policy. For further +# information see https://developers.google.com/web/updates/2018/06/feature-policy +# +# Rails.application.config.permissions_policy do |f| +# f.camera :none +# f.gyroscope :none +# f.microphone :none +# f.usb :none +# f.fullscreen :self +# f.payment :self, "https://secure.example.com" +# end diff --git a/spec/railsapps/rails_71_with_propshaft/config/initializers/wrap_parameters.rb b/spec/railsapps/rails_71_with_propshaft/config/initializers/wrap_parameters.rb new file mode 100644 index 0000000..633c1c8 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/initializers/wrap_parameters.rb @@ -0,0 +1,9 @@ +# Be sure to restart your server when you modify this file. + +# This file contains settings for ActionController::ParamsWrapper which +# is enabled by default. + +# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array. +ActiveSupport.on_load(:action_controller) do + wrap_parameters format: [:json] +end diff --git a/spec/railsapps/rails_71_with_propshaft/config/routes.rb b/spec/railsapps/rails_71_with_propshaft/config/routes.rb new file mode 100644 index 0000000..c3cb692 --- /dev/null +++ b/spec/railsapps/rails_71_with_propshaft/config/routes.rb @@ -0,0 +1,6 @@ +Rails.application.routes.draw do + # For details on the DSL available within this file, see https://guides.rubyonrails.org/routing.html + + # Almost every application defines a route for the root path ("/") at the top of this file. + # root "articles#index" +end diff --git a/spec/support/rails_app.rb b/spec/support/rails_app.rb index b4f6d78..5548f6d 100644 --- a/spec/support/rails_app.rb +++ b/spec/support/rails_app.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true class RailsApp - def initialize(name, path, min_ruby_version: nil, max_ruby_version: nil) + def initialize(name, path, min_ruby_version: nil, max_ruby_version: nil, asset_pipeline: :sprockets) @name = name @path = File.expand_path("../../railsapps/#{path}", __FILE__) @max_ruby_version = max_ruby_version && Gem::Version.new(max_ruby_version) @min_ruby_version = min_ruby_version && Gem::Version.new(min_ruby_version) - reset + @asset_pipeline = asset_pipeline end def supported? @@ -17,6 +17,14 @@ def supported? version >= minimum && version <= maximum end + def with_propshaft? + @asset_pipeline == :propshaft + end + + def with_sprockets? + @asset_pipeline == :sprockets + end + def to_s @name end From b6d8de1930dd439b33411fd7ef5b3009a6996c0b Mon Sep 17 00:00:00 2001 From: jvillarejo Date: Fri, 10 May 2024 15:35:50 -0300 Subject: [PATCH 2/2] Adds .standard.yml to ignore lint errors --- .standard.yml | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 .standard.yml diff --git a/.standard.yml b/.standard.yml new file mode 100644 index 0000000..2a19f15 --- /dev/null +++ b/.standard.yml @@ -0,0 +1,5 @@ +ignore: + - 'lib/roadie/rails/mailer.rb': + - Style/ArgumentsForwarding + - 'lib/roadie/rails/options.rb': + - Performance/StringIdentifierArgument \ No newline at end of file