rolemodel-rails 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +30 -9
- data/Rakefile +3 -3
- data/lib/generators/rolemodel/all_generator.rb +1 -0
- data/lib/generators/rolemodel/core_setup/README.md +27 -0
- data/lib/generators/rolemodel/core_setup/USAGE +12 -0
- data/lib/generators/rolemodel/core_setup/core_setup_generator.rb +23 -0
- data/lib/generators/rolemodel/github/README.md +4 -0
- data/lib/generators/rolemodel/github/templates/workflows/deploy-production.yml +34 -0
- data/lib/generators/rolemodel/github/templates/workflows/deploy-staging.yml +35 -0
- data/lib/generators/rolemodel/good_job/good_job_generator.rb +7 -13
- data/lib/generators/rolemodel/heroku/README.md +20 -1
- data/lib/generators/rolemodel/heroku/heroku_generator.rb +20 -0
- data/lib/generators/rolemodel/heroku/templates/app.json.tt +5 -2
- data/lib/generators/rolemodel/heroku/templates/deploy-app/SKILL.md +202 -0
- data/lib/generators/rolemodel/linters/eslint/eslint_generator.rb +1 -0
- data/lib/generators/rolemodel/linters/rubocop/rubocop_generator.rb +5 -1
- data/lib/generators/rolemodel/lograge/README.md +1 -1
- data/lib/generators/rolemodel/lograge/templates/config/initializers/lograge.rb +1 -1
- data/lib/generators/rolemodel/optics/base/base_generator.rb +3 -2
- data/lib/generators/rolemodel/react/react_generator.rb +1 -0
- data/lib/generators/rolemodel/readme/templates/README.md.erb +2 -4
- data/lib/generators/rolemodel/saas/devise/devise_generator.rb +3 -3
- data/lib/generators/rolemodel/sentry/README.md +25 -0
- data/lib/generators/rolemodel/sentry/USAGE +13 -0
- data/lib/generators/rolemodel/sentry/sentry_generator.rb +114 -0
- data/lib/generators/rolemodel/sentry/templates/app/controllers/concerns/sentry_user.rb +13 -0
- data/lib/generators/rolemodel/sentry/templates/app/javascript/initializers/sentry.js +34 -0
- data/lib/generators/rolemodel/sentry/templates/config/initializers/sentry.rb +68 -0
- data/lib/generators/rolemodel/simple_form/README.md +6 -0
- data/lib/generators/rolemodel/simple_form/USAGE +3 -0
- data/lib/generators/rolemodel/simple_form/simple_form_generator.rb +11 -0
- data/lib/generators/rolemodel/simple_form/templates/app/inputs/switch_checkbox_input.rb +1 -1
- data/lib/generators/rolemodel/slim/templates/app/views/application/_head.html.slim.tt +0 -4
- data/lib/generators/rolemodel/tailored_select/USAGE +2 -1
- data/lib/generators/rolemodel/tailored_select/tailored_select_generator.rb +15 -0
- data/lib/generators/rolemodel/testing/factory_bot/templates/support/factory_bot.rb +2 -0
- data/lib/generators/rolemodel/testing/jasmine_playwright/jasmine_playwright_generator.rb +2 -2
- data/lib/generators/rolemodel/testing/rspec/rspec_generator.rb +8 -10
- data/lib/generators/rolemodel/testing/rspec/templates/spec/rails_helper.rb.tt +4 -1
- data/lib/generators/rolemodel/testing/rspec/templates/spec/support/capybara_drivers.rb.tt +2 -0
- data/lib/generators/rolemodel/testing/rspec/templates/spec/support/helpers/action_cable_helper.rb +2 -0
- data/lib/generators/rolemodel/testing/rspec/templates/spec/support/helpers/test_element_helper.rb +2 -0
- data/lib/generators/rolemodel/testing/rspec/templates/spec/support/helpers.rb.tt +3 -1
- data/lib/generators/rolemodel/testing/vitest/vitest_generator.rb +1 -0
- data/lib/generators/rolemodel/turbo/all/README.md +16 -0
- data/lib/generators/rolemodel/turbo/all/USAGE +5 -0
- data/lib/generators/rolemodel/turbo/all/all_generator.rb +15 -0
- data/lib/generators/rolemodel/turbo/confirm/README.md +25 -0
- data/lib/generators/rolemodel/turbo/confirm/USAGE +5 -0
- data/lib/generators/rolemodel/turbo/confirm/confirm_generator.rb +35 -0
- data/lib/generators/rolemodel/turbo/form/README.md +8 -0
- data/lib/generators/rolemodel/turbo/form/USAGE +5 -0
- data/lib/generators/rolemodel/turbo/form/form_generator.rb +29 -0
- data/lib/generators/rolemodel/turbo/form/templates/app/javascript/controllers/turbo_form_controller.js +15 -0
- data/lib/generators/rolemodel/turbo/form/templates/spec/support/helpers/turbo_form_helper.rb +8 -0
- data/lib/generators/rolemodel/{ui_components → turbo}/modals/README.md +0 -2
- data/lib/generators/rolemodel/turbo/modals/USAGE +5 -0
- data/lib/generators/rolemodel/{ui_components → turbo}/modals/modals_generator.rb +9 -22
- data/lib/generators/rolemodel/{ui_components → turbo}/modals/templates/app/helpers/turbo_frame_link_helper.rb +2 -0
- data/lib/generators/rolemodel/turbo/ready/README.md +12 -0
- data/lib/generators/rolemodel/turbo/ready/USAGE +5 -0
- data/lib/generators/rolemodel/turbo/ready/ready_generator.rb +48 -0
- data/lib/generators/rolemodel/turbo/ready/templates/app/javascript/controllers/prevent_morph_controller.js +22 -0
- data/lib/generators/rolemodel/ui_components/navbar/navbar_generator.rb +11 -14
- data/lib/generators/rolemodel/webpack/README.md +2 -1
- data/lib/generators/rolemodel/webpack/templates/postcss.config.cjs +0 -3
- data/lib/generators/rolemodel/webpack/templates/webpack.config.js +6 -14
- data/lib/generators/rolemodel/webpack/webpack_generator.rb +18 -18
- data/lib/rolemodel/generator_base.rb +15 -0
- data/lib/rolemodel/version.rb +1 -1
- data/lib/rolemodel/yarn.rb +42 -0
- data/lib/rolemodel-rails.rb +0 -1
- metadata +58 -28
- data/lib/generators/rolemodel/linters/rubocop/templates/lib/cops/form_error_response.rb +0 -54
- data/lib/generators/rolemodel/linters/rubocop/templates/lib/cops/no_chrome_tag.rb +0 -45
- data/lib/generators/rolemodel/semaphore/README.md +0 -15
- data/lib/generators/rolemodel/semaphore/USAGE +0 -11
- data/lib/generators/rolemodel/semaphore/semaphore_generator.rb +0 -25
- data/lib/generators/rolemodel/semaphore/templates/heroku-deployment-commands.sh +0 -3
- data/lib/generators/rolemodel/semaphore/templates/production-deploy.yml.erb +0 -17
- data/lib/generators/rolemodel/semaphore/templates/semaphore.yml.erb +0 -145
- data/lib/generators/rolemodel/semaphore/templates/staging-deploy.yml.erb +0 -17
- data/lib/generators/rolemodel/ui_components/modals/USAGE +0 -8
- data/lib/generators/rolemodel/ui_components/modals/templates/app/javascript/controllers/morph_controller.js +0 -23
- data/lib/generators/rolemodel/webpack/templates/app/assets/stylesheets/application.scss +0 -5
- data/lib/generators/rolemodel/webpack/templates/app/javascript/initializers/honeybadger.js +0 -26
- /data/lib/generators/rolemodel/{simple_form → tailored_select}/templates/app/inputs/tailored_select_input.rb +0 -0
- /data/lib/generators/rolemodel/{ui_components/modals/templates/app/javascript/initializers/turbo_confirm.js → turbo/confirm/templates/app/javascript/initializers/turbo_confirm.js.tt} +0 -0
- /data/lib/generators/rolemodel/{ui_components/modals/templates/app/views/application/_confirm.html.slim → turbo/confirm/templates/app/views/application/_confirm.html.slim.tt} +0 -0
- /data/lib/generators/rolemodel/{ui_components → turbo}/modals/templates/app/javascript/controllers/toggle_controller.js +0 -0
- /data/lib/generators/rolemodel/{ui_components → turbo}/modals/templates/app/javascript/initializers/frame_missing_handler.js +0 -0
- /data/lib/generators/rolemodel/{ui_components → turbo}/modals/templates/app/views/layouts/modal.html.slim.tt +0 -0
- /data/lib/generators/rolemodel/{ui_components → turbo}/modals/templates/app/views/layouts/panel.html.slim.tt +0 -0
- /data/lib/generators/rolemodel/{ui_components/modals → turbo/ready}/templates/app/javascript/initializers/before_morph_handler.js +0 -0
- /data/lib/generators/rolemodel/ui_components/navbar/templates/app/assets/stylesheets/components/shoelace/{index.scss → index.css} +0 -0
- /data/lib/generators/rolemodel/ui_components/navbar/templates/app/views/{layouts → application}/_navbar.html.slim +0 -0
|
@@ -6,15 +6,16 @@ module Rolemodel
|
|
|
6
6
|
def add_optics_package
|
|
7
7
|
say 'installing Optics package', :green
|
|
8
8
|
|
|
9
|
+
ensure_yarn
|
|
9
10
|
run 'yarn add @rolemodel/optics'
|
|
10
11
|
end
|
|
11
12
|
|
|
12
13
|
def copy_templates
|
|
13
14
|
say 'importing stylesheet', :green
|
|
14
15
|
|
|
15
|
-
prepend_to_file
|
|
16
|
+
prepend_to_file application_stylesheet_path, <<~CSS
|
|
16
17
|
@import '@rolemodel/optics/dist/css/optics';
|
|
17
|
-
|
|
18
|
+
CSS
|
|
18
19
|
end
|
|
19
20
|
end
|
|
20
21
|
end
|
|
@@ -81,12 +81,10 @@ When finished with the feature and the code has been reviewed, the commits shoul
|
|
|
81
81
|
## [Staging](http://staging.<applicationname>.com)
|
|
82
82
|
## [Production](http://app.<applicationname>.com)
|
|
83
83
|
## External services
|
|
84
|
-
* [
|
|
85
|
-
* [Skylight](http://skylight.io)
|
|
84
|
+
* [Sentry](https://sentry.io)
|
|
86
85
|
* [SendGrid](http://sendgrid.com/RoleModel)
|
|
87
86
|
* [Heroku](http://herokuapp.com)
|
|
88
87
|
|
|
89
|
-
## [CI](http://semaphoreci.com/RoleModel)
|
|
90
88
|
## [Core project presentation](http://docs.google.com)
|
|
91
89
|
## [List of contributors](http://github.com/RoleModel)
|
|
92
90
|
## [Change log](file://./docs/change_log.md)
|
|
@@ -113,4 +111,4 @@ The application is deployed to Heroku. They are also hosting the DNS. We certifi
|
|
|
113
111
|
* Larry Anderson - 919-555-1213
|
|
114
112
|
|
|
115
113
|
# Copyright & licensing
|
|
116
|
-
Copyright (c)
|
|
114
|
+
Copyright (c) 2026 Closed Source @CompanyName
|
|
@@ -161,11 +161,11 @@ module Rolemodel
|
|
|
161
161
|
say 'importing login stylesheet', :green
|
|
162
162
|
copy_file 'app/assets/stylesheets/login.css'
|
|
163
163
|
|
|
164
|
-
return unless File.exist?(
|
|
164
|
+
return unless File.exist?(application_stylesheet_path)
|
|
165
165
|
|
|
166
|
-
append_to_file
|
|
166
|
+
append_to_file application_stylesheet_path, <<~CSS
|
|
167
167
|
@import 'login';
|
|
168
|
-
|
|
168
|
+
CSS
|
|
169
169
|
end
|
|
170
170
|
end
|
|
171
171
|
end
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Sentry Generator
|
|
2
|
+
|
|
3
|
+
## What you get
|
|
4
|
+
|
|
5
|
+
Error monitoring and performance tracing via [Sentry](https://sentry.io) for both the Ruby and JavaScript sides of the app.
|
|
6
|
+
|
|
7
|
+
### Ruby
|
|
8
|
+
|
|
9
|
+
* The `sentry-rails` gem
|
|
10
|
+
* `config/initializers/sentry.rb` with sensible defaults: traces sampling, profiling, PII filtering via Rails' parameter filter, noisy-exception exclusion, and health-check transaction filtering
|
|
11
|
+
* Sentry user context wired into `app/controllers/application_controller.rb` via a `set_sentry_user` before_action (Devise-friendly, gated on `user_signed_in?`)
|
|
12
|
+
|
|
13
|
+
### JavaScript
|
|
14
|
+
|
|
15
|
+
* `@sentry/browser` and `@sentry/webpack-plugin` dependencies
|
|
16
|
+
* `app/javascript/initializers/sentry.js`, which initializes Sentry in production and staging only (avoids ad-blocker noise in development) and attaches the current user from a `current-user-id` meta tag
|
|
17
|
+
* The `sentryWebpackPlugin` wired into `webpack.config.js` to upload source maps in production
|
|
18
|
+
|
|
19
|
+
Depends on the `rolemodel:webpack` generator having already created `webpack.config.js` and `app/javascript/application.js`.
|
|
20
|
+
|
|
21
|
+
## After running
|
|
22
|
+
|
|
23
|
+
* Update the `project` and `applicationKey` in `webpack.config.js`, and the matching `filterKeys` in `app/javascript/initializers/sentry.js`, to match your Sentry project.
|
|
24
|
+
* Set the `SENTRY_DSN`, `SENTRY_ENVIRONMENT`, and `SENTRY_AUTH_TOKEN` environment variables.
|
|
25
|
+
* Render a `current-user-id` meta tag in your layout so the browser SDK can attach user context.
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
Description:
|
|
2
|
+
Sets up Sentry error monitoring for both Ruby and JavaScript
|
|
3
|
+
|
|
4
|
+
Example:
|
|
5
|
+
rails generate rolemodel:sentry
|
|
6
|
+
|
|
7
|
+
This will:
|
|
8
|
+
Add the sentry-rails gem
|
|
9
|
+
Create config/initializers/sentry.rb
|
|
10
|
+
Add Sentry user context to app/controllers/application_controller.rb
|
|
11
|
+
Add @sentry/browser and @sentry/webpack-plugin JS dependencies
|
|
12
|
+
Create app/javascript/initializers/sentry.js
|
|
13
|
+
Wire the Sentry webpack plugin into webpack.config.js
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Rolemodel
|
|
4
|
+
class SentryGenerator < GeneratorBase
|
|
5
|
+
source_root File.expand_path('templates', __dir__)
|
|
6
|
+
|
|
7
|
+
JS_DEPS = %w[
|
|
8
|
+
@sentry/browser
|
|
9
|
+
@sentry/webpack-plugin
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
def install_gem
|
|
13
|
+
say 'Adding sentry-rails gem', :green
|
|
14
|
+
|
|
15
|
+
bundle_command 'add sentry-rails'
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def install_profiler_gem
|
|
19
|
+
say 'Adding stackprof gem for Sentry profiling', :green
|
|
20
|
+
|
|
21
|
+
# config/initializers/sentry.rb sets profiles_sample_rate; without stackprof
|
|
22
|
+
# the SDK logs a warning on every boot and profiling is silently disabled.
|
|
23
|
+
# stackprof is a native MRI extension, so restrict it to compatible platforms.
|
|
24
|
+
bundle_command 'add stackprof --platform ruby'
|
|
25
|
+
run_bundle
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add_ruby_initializer
|
|
29
|
+
say 'Setting up Sentry for Ruby error reporting', :green
|
|
30
|
+
|
|
31
|
+
copy_file 'config/initializers/sentry.rb'
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def add_user_context
|
|
35
|
+
say 'Adding Sentry user context to ApplicationController', :green
|
|
36
|
+
|
|
37
|
+
directory 'app/controllers/concerns'
|
|
38
|
+
|
|
39
|
+
inject_into_class 'app/controllers/application_controller.rb', 'ApplicationController',
|
|
40
|
+
" include SentryUser\n"
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
def add_js_dependencies
|
|
44
|
+
say 'Adding Sentry JS dependencies to package.json', :green
|
|
45
|
+
|
|
46
|
+
ensure_yarn
|
|
47
|
+
run "yarn add --dev #{JS_DEPS.join(' ')}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def add_js_initializer
|
|
51
|
+
say 'Setting up Sentry for JS error reporting', :green
|
|
52
|
+
|
|
53
|
+
copy_file 'app/javascript/initializers/sentry.js'
|
|
54
|
+
append_to_file 'app/javascript/application.js', <<~JS
|
|
55
|
+
import './initializers/sentry'
|
|
56
|
+
JS
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# Wire the Sentry webpack plugin into webpack.config.js. Idempotent and a
|
|
60
|
+
# no-op if there's no webpack.config.js or it's already wired, so the
|
|
61
|
+
# webpack generator can safely invoke this generator via its --sentry option.
|
|
62
|
+
def configure_webpack
|
|
63
|
+
config = File.expand_path('webpack.config.js', destination_root)
|
|
64
|
+
return unless File.exist?(config)
|
|
65
|
+
return if File.read(config).include?('@sentry/webpack-plugin')
|
|
66
|
+
|
|
67
|
+
say 'Wiring Sentry into webpack.config.js', :green
|
|
68
|
+
|
|
69
|
+
inject_into_file 'webpack.config.js',
|
|
70
|
+
"import { sentryWebpackPlugin } from '@sentry/webpack-plugin'\n",
|
|
71
|
+
after: "import CssMinimizerPlugin from 'css-minimizer-webpack-plugin'\n"
|
|
72
|
+
|
|
73
|
+
inject_into_file 'webpack.config.js', after: "'process.env.RAILS_ENV': JSON.stringify(process.env.RAILS_ENV),\n" do
|
|
74
|
+
<<-JS
|
|
75
|
+
'process.env.SENTRY_DSN': JSON.stringify(process.env.SENTRY_DSN),
|
|
76
|
+
'process.env.SENTRY_ENVIRONMENT': JSON.stringify(process.env.SENTRY_ENVIRONMENT),
|
|
77
|
+
'process.env.SENTRY_AUTH_TOKEN': JSON.stringify(process.env.SENTRY_AUTH_TOKEN),
|
|
78
|
+
JS
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
gsub_file 'webpack.config.js', " })\n ].filter(Boolean)", <<-JS.chomp
|
|
82
|
+
}),
|
|
83
|
+
|
|
84
|
+
// Upload source maps to Sentry in production for easier debugging
|
|
85
|
+
mode === 'production' &&
|
|
86
|
+
!process.env.CI &&
|
|
87
|
+
sentryWebpackPlugin({
|
|
88
|
+
authToken: process.env.SENTRY_AUTH_TOKEN,
|
|
89
|
+
org: 'rolemodel-software',
|
|
90
|
+
project: '#{sentry_app_name}',
|
|
91
|
+
telemetry: false,
|
|
92
|
+
applicationKey: 'app-frontend'
|
|
93
|
+
})
|
|
94
|
+
].filter(Boolean)
|
|
95
|
+
JS
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def finishing_notes
|
|
99
|
+
say <<~NOTES
|
|
100
|
+
|
|
101
|
+
*** Update the sentryWebpackPlugin `project` and `applicationKey` in webpack.config.js,
|
|
102
|
+
and the matching `filterKeys` in app/javascript/initializers/sentry.js, to your Sentry project.
|
|
103
|
+
|
|
104
|
+
*** Set the SENTRY_DSN, SENTRY_ENVIRONMENT, and SENTRY_AUTH_TOKEN environment variables.
|
|
105
|
+
NOTES
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
def sentry_app_name
|
|
111
|
+
Rails.application.name.underscore
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import * as Sentry from '@sentry/browser'
|
|
2
|
+
|
|
3
|
+
// Only initialize Sentry in production and staging environments
|
|
4
|
+
// This avoids issues with ad blockers during local development
|
|
5
|
+
const environment = process.env.SENTRY_ENVIRONMENT || process.env.RAILS_ENV
|
|
6
|
+
const shouldInitialize = environment === 'production' || environment === 'staging'
|
|
7
|
+
|
|
8
|
+
if (shouldInitialize) {
|
|
9
|
+
Sentry.init({
|
|
10
|
+
dsn: process.env.SENTRY_DSN,
|
|
11
|
+
environment: environment,
|
|
12
|
+
sendDefaultPii: false,
|
|
13
|
+
tracesSampleRate: 0.1,
|
|
14
|
+
replaysOnErrorSampleRate: 1.0,
|
|
15
|
+
integrations: [
|
|
16
|
+
Sentry.thirdPartyErrorFilterIntegration({
|
|
17
|
+
// Must match the applicationKey in the sentryWebpackPlugin configuration
|
|
18
|
+
filterKeys: ['app-frontend'],
|
|
19
|
+
behaviour: 'drop-error-if-exclusively-contains-third-party-frames'
|
|
20
|
+
})
|
|
21
|
+
],
|
|
22
|
+
|
|
23
|
+
// Capture user context from meta tags rendered by Rails
|
|
24
|
+
beforeSend(event) {
|
|
25
|
+
const userId = document.querySelector('meta[name="current-user-id"]')?.content
|
|
26
|
+
|
|
27
|
+
if (userId) {
|
|
28
|
+
event.user = { id: userId }
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
return event
|
|
32
|
+
}
|
|
33
|
+
})
|
|
34
|
+
}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
Sentry.init do |config|
|
|
4
|
+
config.dsn = ENV['SENTRY_DSN']
|
|
5
|
+
config.enable_logs = true
|
|
6
|
+
config.debug = Rails.env.local?
|
|
7
|
+
|
|
8
|
+
# Traces sampling — 5% for HTTP requests, 10% for other transactions
|
|
9
|
+
config.traces_sampler = lambda do |sampling_context|
|
|
10
|
+
transaction_context = sampling_context[:transaction_context]
|
|
11
|
+
|
|
12
|
+
case transaction_context[:op]
|
|
13
|
+
when /^http/
|
|
14
|
+
0.05
|
|
15
|
+
else
|
|
16
|
+
0.10
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Enable profiling at 100% of sampled transactions
|
|
21
|
+
config.profiles_sample_rate = 1.0
|
|
22
|
+
|
|
23
|
+
# Breadcrumbs configuration
|
|
24
|
+
config.breadcrumbs_logger = [:sentry_logger, :http_logger]
|
|
25
|
+
|
|
26
|
+
# Exclude common noisy exceptions
|
|
27
|
+
config.excluded_exceptions += [
|
|
28
|
+
'ActiveRecord::RecordNotFound',
|
|
29
|
+
'ActionController::RoutingError',
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
# Include local variables for debugging
|
|
33
|
+
config.include_local_variables = true
|
|
34
|
+
|
|
35
|
+
# Filter out health check transactions
|
|
36
|
+
config.before_send_transaction = lambda do |event, _hint|
|
|
37
|
+
return nil if event.transaction&.match?(/health|ping|metrics/)
|
|
38
|
+
event
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# Filter sensitive data using Rails' parameter filter
|
|
42
|
+
filter = ActiveSupport::ParameterFilter.new(Rails.application.config.filter_parameters)
|
|
43
|
+
config.send_default_pii = false
|
|
44
|
+
|
|
45
|
+
config.before_send = lambda do |event, _hint|
|
|
46
|
+
if event.extra
|
|
47
|
+
event.extra = filter.filter(event.extra)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
if event.user
|
|
51
|
+
event.user = filter.filter(event.user)
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
if event.contexts
|
|
55
|
+
event.contexts = filter.filter(event.contexts)
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
event
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
config.enabled_patches << :logger
|
|
62
|
+
config.std_lib_logger_filter = proc do |_logger, _message, severity|
|
|
63
|
+
[:warn, :error, :fatal].include?(severity)
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
config.rails.register_error_subscriber = Rails.env.production?
|
|
67
|
+
config.rails.structured_logging.subscribers = config.rails.structured_logging.subscribers.slice(:action_controller)
|
|
68
|
+
end
|
|
@@ -8,3 +8,9 @@
|
|
|
8
8
|
* SimpleForm scaffold generation template
|
|
9
9
|
|
|
10
10
|
Adds SimpleForm for simplified and unified styling that automatically wraps inputs with classes
|
|
11
|
+
|
|
12
|
+
## Custom inputs
|
|
13
|
+
|
|
14
|
+
All standard custom inputs are included by default. The generator prompts you to
|
|
15
|
+
confirm whether to include the `tailored_select` custom input, since not every
|
|
16
|
+
project uses the tailored-select web component.
|
|
@@ -4,6 +4,9 @@ module Rolemodel
|
|
|
4
4
|
class SimpleFormGenerator < GeneratorBase
|
|
5
5
|
source_root File.expand_path('templates', __dir__)
|
|
6
6
|
|
|
7
|
+
class_option :tailored_select, type: :boolean, default: false,
|
|
8
|
+
desc: 'Install the tailored_select experimental component input'
|
|
9
|
+
|
|
7
10
|
def add_gem
|
|
8
11
|
Bundler.with_unbundled_env do
|
|
9
12
|
bundle_command 'add simple_form'
|
|
@@ -16,5 +19,13 @@ module Rolemodel
|
|
|
16
19
|
copy_file 'config/initializers/simple_form.rb'
|
|
17
20
|
copy_file 'config/locales/simple_form.en.yml'
|
|
18
21
|
end
|
|
22
|
+
|
|
23
|
+
def install_tailored_select
|
|
24
|
+
return unless options.tailored_select?
|
|
25
|
+
|
|
26
|
+
# The tailored_select generator owns the input template and installs it
|
|
27
|
+
# here because simple_form is now present.
|
|
28
|
+
generate 'rolemodel:tailored_select'
|
|
29
|
+
end
|
|
19
30
|
end
|
|
20
31
|
end
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
# <%= f.input :my_field, as: :switch_checkbox, label_after_input: true %>
|
|
15
15
|
# <%= f.input :my_field, as: :switch_checkbox, wrapper: :switch_wrapper %>
|
|
16
16
|
class SwitchCheckboxInput < SimpleForm::Inputs::BooleanInput
|
|
17
|
-
def input(wrapper_options = nil)
|
|
17
|
+
def input(wrapper_options = nil) # rubocop:disable Metrics/AbcSize, Metrics/MethodLength
|
|
18
18
|
merged_input_options = merge_wrapper_options(input_html_options, wrapper_options)
|
|
19
19
|
|
|
20
20
|
switch_group = template.content_tag(:div, class: "switch #{'switch--small' if options[:small]}") do
|
|
@@ -4,10 +4,6 @@ title <%= Rails.application.class.name.deconstantize.titleize %>
|
|
|
4
4
|
= csp_meta_tag
|
|
5
5
|
|
|
6
6
|
meta name="viewport" content="width=device-width, initial-scale=1"
|
|
7
|
-
meta name="turbo-refresh-method" content="morph"
|
|
8
|
-
meta name="turbo-refresh-scroll" content="preserve"
|
|
9
7
|
|
|
10
8
|
= stylesheet_link_tag 'application', 'data-turbo-track': 'reload'
|
|
11
9
|
= javascript_include_tag 'application', 'data-turbo-track': 'reload', defer: true
|
|
12
|
-
|
|
13
|
-
= yield :head
|
|
@@ -7,7 +7,22 @@ module Rolemodel
|
|
|
7
7
|
def add_tailored_select_package
|
|
8
8
|
say 'Installing Tailored Select package', :green
|
|
9
9
|
|
|
10
|
+
ensure_yarn
|
|
10
11
|
run 'yarn add @rolemodel/tailored-select'
|
|
11
12
|
end
|
|
13
|
+
|
|
14
|
+
def add_simple_form_input
|
|
15
|
+
return unless simple_form?
|
|
16
|
+
|
|
17
|
+
say 'Installing the Tailored Select SimpleForm input', :green
|
|
18
|
+
|
|
19
|
+
copy_file 'app/inputs/tailored_select_input.rb'
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def simple_form?
|
|
25
|
+
File.exist?(File.expand_path('config/initializers/simple_form.rb', destination_root))
|
|
26
|
+
end
|
|
12
27
|
end
|
|
13
28
|
end
|
|
@@ -18,8 +18,8 @@ module Rolemodel
|
|
|
18
18
|
raise Thor::InvocationError, 'a --github_package_token option or GITHUB_PACKAGES_TOKEN environment variable is required' if options[:github_package_token].blank?
|
|
19
19
|
end
|
|
20
20
|
|
|
21
|
-
def
|
|
22
|
-
|
|
21
|
+
def enable_corepack_and_yarn
|
|
22
|
+
ensure_yarn
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def add_browser_test_script
|
|
@@ -10,26 +10,24 @@ module Rolemodel
|
|
|
10
10
|
def install_rspec
|
|
11
11
|
say 'Installing RSpec-rails', :green
|
|
12
12
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
end
|
|
13
|
+
bundle_command('add rspec-rails --group "development, test"')
|
|
14
|
+
end
|
|
16
15
|
|
|
16
|
+
def install_system_test_driver
|
|
17
17
|
say 'Installing capybara-playwright-driver for system tests', :green
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
bundle_command('add capybara-playwright-driver --group "test"')
|
|
20
|
+
bundle_command('add marsh_grass --group "test"') if options.marsh_grass?
|
|
21
|
+
end
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
gem 'marsh_grass'
|
|
24
|
-
gem 'pry'
|
|
25
|
-
end
|
|
26
|
-
end
|
|
23
|
+
def bundle_install
|
|
27
24
|
run_bundle
|
|
28
25
|
end
|
|
29
26
|
|
|
30
27
|
def install_playwright
|
|
31
28
|
say 'Installing Playwright for system tests', :green
|
|
32
29
|
|
|
30
|
+
ensure_yarn
|
|
33
31
|
run 'yarn add --dev playwright'
|
|
34
32
|
run 'yarn run playwright install'
|
|
35
33
|
end
|
|
@@ -70,7 +70,10 @@ RSpec.configure do |config|
|
|
|
70
70
|
prep_passed = system 'rails spec:prepare'
|
|
71
71
|
ENV['ASSET_PRECOMPILE_SUCCESSFUL'] = 'true'
|
|
72
72
|
|
|
73
|
-
|
|
73
|
+
unless prep_passed
|
|
74
|
+
abort "\nYour assets didn't compile. Exiting WITHOUT running any tests. " \
|
|
75
|
+
'Review the output above to resolve any errors.'
|
|
76
|
+
end
|
|
74
77
|
end
|
|
75
78
|
end
|
|
76
79
|
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# All Generator
|
|
2
|
+
|
|
3
|
+
Runs all Turbo Generators
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
- slim
|
|
8
|
+
- webpack (if using webpack)
|
|
9
|
+
- optics
|
|
10
|
+
|
|
11
|
+
## What you get
|
|
12
|
+
|
|
13
|
+
- Turbo meta tags in HEAD
|
|
14
|
+
- TurboConfirm setup
|
|
15
|
+
- Turbo Frame Modals setup
|
|
16
|
+
- Turbo-Form stimulus controller
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
module Rolemodel
|
|
2
|
+
module Turbo
|
|
3
|
+
class AllGenerator < ::Rolemodel::GeneratorBase
|
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
|
5
|
+
|
|
6
|
+
def run_generators
|
|
7
|
+
generate 'rolemodel:turbo:ready'
|
|
8
|
+
generate 'rolemodel:turbo:confirm'
|
|
9
|
+
generate 'rolemodel:turbo:modals'
|
|
10
|
+
generate 'rolemodel:turbo:form'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Confirm Generator
|
|
2
|
+
|
|
3
|
+
Add custom dialog support to `data-turbo-confirm`
|
|
4
|
+
|
|
5
|
+
## Prerequisites
|
|
6
|
+
|
|
7
|
+
* `rolmodel:slim`
|
|
8
|
+
* `rolemodel:webpack`
|
|
9
|
+
* `rolemodel:optics:base`
|
|
10
|
+
|
|
11
|
+
## What you get
|
|
12
|
+
|
|
13
|
+
* Custom confirm dialogs via `@rolemodel/turbo-confirm` integration
|
|
14
|
+
|
|
15
|
+
## Example
|
|
16
|
+
|
|
17
|
+
```slim
|
|
18
|
+
= button_to "Test Confirm", model, method: :delete, data: { \
|
|
19
|
+
turbo_confirm: "For real?!?",
|
|
20
|
+
confirm_details: "You're about to delete #{model.name}, forever. 😱",
|
|
21
|
+
confirm_button: "YOLO!",
|
|
22
|
+
}
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
data attributes other than `turbo-confirm` are optional & customizable. See [turbo-confirm](https://github.com/RoleModel/turbo-confirm) for more details.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
module Rolemodel
|
|
2
|
+
module Turbo
|
|
3
|
+
class ConfirmGenerator < ::Rolemodel::GeneratorBase
|
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
|
5
|
+
|
|
6
|
+
def add_turbo_confirm_package
|
|
7
|
+
say 'Installing Turbo Confirm package', :green
|
|
8
|
+
|
|
9
|
+
ensure_yarn
|
|
10
|
+
run 'yarn add @rolemodel/turbo-confirm'
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def add_initializer
|
|
14
|
+
template 'app/javascript/initializers/turbo_confirm.js'
|
|
15
|
+
|
|
16
|
+
append_to_file 'app/javascript/application.js' do
|
|
17
|
+
optimize_indentation <<~JS
|
|
18
|
+
import './initializers/turbo_confirm.js'
|
|
19
|
+
JS
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def add_view_partial
|
|
24
|
+
template 'app/views/application/_confirm.html.slim'
|
|
25
|
+
|
|
26
|
+
inject_into_file 'app/views/layouts/application.html.slim', after: /\bbody.*\n/ do
|
|
27
|
+
optimize_indentation <<~SLIM, 4
|
|
28
|
+
= render 'confirm'
|
|
29
|
+
SLIM
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
|