Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,11 @@ Do not introduce a new framework, database, job runner, or test library without
- Add database indexes for foreign keys and any column used for timeline ordering.
- Use strong parameters, and scope queries through associations rather than
`Model.find(params[:id])` on user-owned records.
- **A render-only action has no method.** Rails renders the matching template
whether or not the action is defined, so `def new; end` is inert. The route,
and the `only:` list of any filter that applies to it, already declare that
the action exists. Four such methods were deleted on 2026-09-01 (issue #79);
do not reintroduce them, and do not read their absence as an oversight.

**Views**

Expand Down
14 changes: 14 additions & 0 deletions sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,17 @@ sonar.ruby.file.suffixes=.rb,.rake
# to the SonarQube job as an artifact. This is the only coverage format the
# Ruby analyser accepts — it does not read LCOV.
sonar.ruby.coverage.reportPaths=web/coverage/coverage.json

# Coverage describes the Ruby, because the Ruby is what SimpleCov can
# instrument. Without these two lines the dashboard read 76.8% while the suite
# covered ~99% of the Ruby: Sonar counts a source file with no coverage data as
# uncovered, and sonar.sources also holds Stimulus controllers and ERB
# templates, which SimpleCov cannot instrument at all.
#
# Both numbers were honest; they measured different things, and the headline was
# the one that understated the suite — which is how a metric stops being read.
#
# This narrows one metric, not the scan: every file below is still analysed for
# bugs, smells and vulnerabilities. It is also the prerequisite for making the
# quality gate blocking, since a gate on a number nobody believes is theatre.
sonar.coverage.exclusions=web/app/javascript/**,web/app/views/**
6 changes: 0 additions & 6 deletions web/app/controllers/passwords_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ class PasswordsController < ApplicationController
before_action :set_user_by_token, only: %i[ edit update ]
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_password_path, alert: "Try again later." }

def new
end

def create
if user = User.find_by(email_address: params[:email_address])
PasswordsMailer.reset(user).deliver_later
Expand All @@ -14,9 +11,6 @@ def create
redirect_to new_session_path, notice: "Password reset instructions sent (if user with that email address exists)."
end

def edit
end

def update
if @user.update(params.permit(:password, :password_confirmation))
@user.sessions.destroy_all
Expand Down
3 changes: 0 additions & 3 deletions web/app/controllers/posts_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,6 @@ def create
end
end

def edit
end

def update
if @post.update(post_params)
redirect_to posts_path
Expand Down
3 changes: 0 additions & 3 deletions web/app/controllers/sessions_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,6 @@ class SessionsController < ApplicationController
before_action :redirect_if_authenticated, only: %i[ new create ]
rate_limit to: 10, within: 3.minutes, only: :create, with: -> { redirect_to new_session_path, alert: "Try again later." }

def new
end

def create
if user = User.authenticate_by(params.permit(:email_address, :password))
start_new_session_for user
Expand Down
6 changes: 6 additions & 0 deletions web/config/initializers/opentelemetry.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
tracing_requested = ENV["OTEL_TRACES_EXPORTER"] != "none"

if tracing_requested || Rails.env.test?
# These requires stay here rather than at the top of the file, and Sonar's
# rubydre:S7816 is right that this is unusual — it is also the whole point of
# ADR 0009. Loading the SDK is what starts it; requiring it unconditionally
# would mean every rails command paid for instrumentation nobody asked for,
# which is a behaviour change rather than a tidy-up. The rule is refused here
# deliberately, with the reason in the file rather than only on a dashboard.
require "opentelemetry/sdk"
require "opentelemetry/instrumentation/rails"

Expand Down
4 changes: 4 additions & 0 deletions web/spec/rails_helper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,10 @@
rescue ActiveRecord::PendingMigrationError => e
abort e.to_s.strip
end
# Support files are required after the Rails environment, not at the top of
# the file, because they reference application constants and RSpec config.
# Also refusing rubydre:S7816, for a different reason than the initializer:
# this is a glob, so there is no static require to hoist.
Rails.root.glob('spec/support/**/*.rb').sort.each { |file| require file }

RSpec.configure do |config|
Expand Down
Loading