Skip to content

Commit 953c69f

Browse files
authored
Merge branch 'main' into seya/saml-relay-state
2 parents c15d50d + 253a5ce commit 953c69f

69 files changed

Lines changed: 1191 additions & 151 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.claude/skills/pr/SKILL.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ The workflow below (steps 0–3) always runs and creates or updates the PR. When
2626

2727
Invoke the `/simplify` command to review the changed code for reuse, simplification, and efficiency cleanups and apply them. Do this first, before writing the PR up, so the body describes the diff's final shape rather than a first draft. It's quality-only — it won't touch correctness — so it's safe to run unattended here; if it reports nothing to clean up, move on.
2828

29-
Then run `bin/lint` to auto-format the code (it also picks up whatever `/simplify` just changed). Always use `bin/lint`, never another formatter or `standardrb` directly. Scope it to the branch's files rather than walking the whole repo — `bin/lint $(git diff --name-only --diff-filter=d "origin/$BASE"...HEAD)`; `--diff-filter=d` drops deleted paths so they don't show up as "Not found". Files with no linter (`.haml`, `.scss`, `.md`) are skipped, so a branch that touches none of the lintable types exits cleanly rather than looking like a lint failure. It takes directories too, so `bin/lint app/components/foo` works while you're still iterating.
29+
Then run `bin/lint` to auto-format the code (it also picks up whatever `/simplify` just changed). Always use `bin/lint`, never another formatter or `standardrb` directly. Scope it to the branch's files rather than walking the whole repo — `bin/lint $(git diff --name-only --diff-filter=d "origin/$BASE"...HEAD)`; `--diff-filter=d` drops deleted paths so they don't show up as "Not found". Files with no linter (`.haml`, `.scss`, `.md`) are skipped, so a branch that touches none of the lintable types exits cleanly rather than looking like a lint failure. It takes directories too, so `bin/lint app/components/foo` works while you're still iterating. Never revert what the linter wrote — if a too-broad run reformats files outside the branch, those fixes stay in the diff.
3030

3131
Scope specs the same way — the ones covering what the branch changed, never a bare `bundle exec rspec` or a whole top-level directory (see the `rspec-testing` skill). CI runs the full suite; a green PR isn't your job to prove locally.
3232

AGENTS.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ Run `bin/lint` to automatically format the code. Always use `bin/lint`, don't us
1212

1313
**Pass it the files or directories you changed**`bin/lint app/components/ui/table app/models/bike.rb`. A bare `bin/lint` walks the whole repo, which is slow and reformats files you aren't working on. Save it for a final check before pushing.
1414

15+
**Never revert what the linter wrote.** If a too-broad `bin/lint` reformats files outside your change, leave those fixes in the diff — don't `git checkout` them away. Scope the next run more tightly instead.
16+
1517
### Code guidelines:
1618

1719
- Code in a functional way. Avoid mutation (side effects) when you can.
@@ -21,8 +23,10 @@ Run `bin/lint` to automatically format the code. Always use `bin/lint`, don't us
2123
- Omit named arguments' values from hashes (ie prefer `{x:, y:}` instead of `{x: x, y: y}`)
2224
- Prefer less code, by character count (excluding whitespace and comments). Use `bin/char_count {FILE OR FOLDER}` to get the non-whitespace character count
2325
- prefer un-abbreviated variable names
26+
- Use full class/module names everywhere — `UI::Forms::Combobox::Component`, not the `Combobox::Component` that lexical scope also resolves from inside `UI::Forms`
2427
- Keep comments pithy — often they aren't necessary. Explain *why* only where a reader would otherwise get it wrong; don't narrate the change that introduced the code, and don't defend a choice against an edit nobody would make — a failing test already defends it
25-
- **Service objects** (`app/services/`): a stateless service is a `module` with `extend Functionable` (see the `functionable` gem) — inputs passed as args, no instance state, private methods via `conceal` + a `# private below here` block. Reach for a `class` only when the object genuinely holds instance state across methods (e.g. a multi-step builder/updater). Don't write a stateless service as a `class` with `def self.` methods.
28+
- **Prefer composition over inheritance and `include`.** Share behavior by calling an object that owns it, not by mixing a module into several classes or adding a base class. A `module` extracted only to be `include`d in two classes is usually one of those classes with a parameter — pass the difference in as an argument instead. Rails' own extension points (`ApplicationRecord`, `ApplicationJob`, `ActiveSupport::Concern` for controller filters) are fine; new mixins of our own are what to avoid.
29+
- **Service objects** (`app/services/`): a stateless service is a `module` with `extend Functionable` (see the `functionable` gem) — inputs passed as args, no instance state, private methods via `conceal` + a `# private below here` block. Don't write a stateless service as a `class` with `def self.` methods.
2630

2731
## Subagents
2832

Gemfile.lock

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ GEM
137137
bcrypt (3.1.22)
138138
benchmark (0.5.0)
139139
bigdecimal (4.1.2)
140-
binxtils (0.5.2)
140+
binxtils (0.6.0)
141141
functionable
142142
loofah
143143
rails
@@ -244,7 +244,7 @@ GEM
244244
dry-logic (~> 1.4)
245245
zeitwerk (~> 2.6)
246246
equalizer (0.0.11)
247-
erb (6.0.6)
247+
erb (6.0.7)
248248
erubi (1.13.1)
249249
excon (0.76.0)
250250
execjs (2.7.0)
@@ -438,7 +438,7 @@ GEM
438438
rdoc (>= 4.0.0)
439439
reline (>= 0.4.2)
440440
jmespath (1.6.2)
441-
json (2.21.1)
441+
json (2.21.2)
442442
jwt (3.2.0)
443443
base64
444444
knapsack_pro (10.0.1)
@@ -674,7 +674,7 @@ GEM
674674
rb-fsevent (0.11.2)
675675
rb-inotify (0.11.1)
676676
ffi (~> 1.0)
677-
rbs (4.1.0)
677+
rbs (4.1.2)
678678
logger
679679
prism (>= 1.6.0)
680680
tsort
@@ -900,7 +900,7 @@ GEM
900900
nokogiri (~> 1.8)
901901
yaml (0.4.0)
902902
yard (0.9.44)
903-
zeitwerk (2.8.2)
903+
zeitwerk (2.8.3)
904904

905905
PLATFORMS
906906
arm64-darwin
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
---
2+
en:
3+
components:
4+
emails:
5+
partial_register_confirmation:
6+
click_below_to_pick_up_where_you_left_off: Click below to confirm this email
7+
address and pick up where you left off.
8+
confirm_and_continue: Confirm my email
9+
confirm_your_email: Confirm your email
10+
link_signs_you_in: >-
11+
This link signs you in to Bike Index, so don't forward it. It works for
12+
%{days} days.
13+
we_saved_your_registration_html: >-
14+
We saved your registration for a <strong>%{color_and_brand}</strong> on
15+
the world's most comprehensive bike registry.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
<h1><%= translation("confirm_your_email") %></h1>
2+
3+
<p>
4+
<%= translation("we_saved_your_registration_html", color_and_brand: @b_param.color_and_brand) %>
5+
</p>
6+
7+
<p><%= translation("click_below_to_pick_up_where_you_left_off") %></p>
8+
9+
<%= link_to translation("confirm_and_continue"), tokenized_url, "data-pm-no-track" => true, class: "binx-button" %>
10+
11+
<p><%= translation("link_signs_you_in", days: expiration_days) %></p>
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# frozen_string_literal: true
2+
3+
module Emails
4+
module PartialRegisterConfirmation
5+
class Component < ApplicationComponent
6+
def initialize(b_param:)
7+
@b_param = b_param
8+
end
9+
10+
private
11+
12+
def expiration_days
13+
BParam::TOKEN_EXPIRATION.in_days.to_i
14+
end
15+
16+
def tokenized_url
17+
confirm_register_url(b_param_token: @b_param.id_token,
18+
confirmation_token: @b_param.email_confirmation_token)
19+
end
20+
end
21+
end
22+
end

app/components/emails/partial_registration/component.html.erb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<h1><%= translation("youre_almost_done") %></h1>
22

33
<p>
4-
<%= translation("just_a_few_steps_away_html", color_and_brand: color_and_brand) %>
4+
<%= translation("just_a_few_steps_away_html", color_and_brand: @b_param.color_and_brand) %>
55
</p>
66

77
<% if organization_snippet_body.present? %>

app/components/emails/partial_registration/component.rb

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,6 @@ def organization
1818
@b_param.creation_organization
1919
end
2020

21-
def color_and_brand
22-
[@b_param.primary_frame_color.presence, @b_param.mnfg_name].compact.join(" ")
23-
end
24-
2521
def tokenized_url
2622
@email_preview ? OrganizedServices::EmailPreview::TOKEN_PATH : new_bike_url(b_param_token: @b_param.id_token)
2723
end
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
en:
3+
components:
4+
register:
5+
confirm:
6+
confirming_your_email: Confirming your email
7+
continue: Continue
8+
this_only_takes_a_moment: Hang on, we're picking up where you left off.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<%= render Register::Page::Component.new do %>
2+
<div class="tw:px-1 tw:py-6 tw:text-center">
3+
<%= render UI::Header::Component.new(text: translation(".confirming_your_email"),
4+
subtitle: translation(".this_only_takes_a_moment")) %>
5+
6+
<%= form_with(url: confirm_email_register_path, method: :post,
7+
data: {controller: "auto-submit"}) do %>
8+
<%= hidden_field_tag :b_param_token, @b_param.id_token %>
9+
<%= hidden_field_tag :confirmation_token, @token %>
10+
11+
<%= render UI::Button::Component.new(text: translation(".continue"), color: :primary, size: :lg,
12+
kind: :submit, spinner: true, html_class: "tw:w-full") %>
13+
<% end %>
14+
</div>
15+
<% end %>

0 commit comments

Comments
 (0)