You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
For the recordless dropdown used by the index view (record: nil), this calls Time.zone.now; Rails applications may not configure Time.zone (the dummy app leaves it unset), so rendering a multi-action index raises NoMethodError. Use a zone-independent Rails clock here.
The index page passes record: nil, so a single generic action reaches button_render with no record; the base implementation immediately calls record.id and raises. This also affects any record-dependent action configured for index, not just the built-in Edit action. Make the single-action path support nil/header actions or require and supply a record before calling button_render.
Unlike the show and edit templates, this unconditionally registers a page-header action slot even when actions_for(:index) is empty. PageHeader checks whether slots exist, not whether their rendered content is nonempty, so repositories with no index actions get an empty action container in the header.
<% header.with_action do %>
<%= render(Uchi::Ui::Actions::Dropdown.new(
actions: @repository.actions_for(Uchi::View::INDEX),
record: nil,
repository: @repository
)) %>
<% end %>
lib/uchi/action.rb:123
The index view passes record: nil, and the base action's default on includes :index. A single custom action that inherits this method therefore calls nil.id before it can render. Make the id field conditional and compact the fields as #render already does.
view.hidden_field_tag(:id, record.id),
lib/uchi/action.rb:3
Configuration#initialize now calls default_on, which references Uchi::View, but this file does not load the view definitions. A direct require "uchi/action" followed by Uchi::Action.new therefore raises NameError; load the view dependency here as the field configuration does.
require_relative "action/configuration"
lib/uchi/action/edit.rb:30
Like New#perform, this method is reachable through the generic action execution endpoint, but repository is not defined on Action. Invoking the registered default Edit action directly therefore raises NoMethodError and returns a 500 response.
This standalone button also uses Action#name rather than repository.translate.link_to_edit(record), so localized Edit labels are ignored when Edit is the only action. Use the repository translation here as well.
name,
lib/uchi/action/new.rb:32
This standalone button also uses Action#name rather than the repository-specific repository.translate.link_to_new lookup, so localized link_to_new values are ignored when New is the only action. Use the repository translation here as well.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unresolved action rendering and built-in action execution defects block approval.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (6)
lib/uchi/action.rb:123
The index template passes record: nil, and a single collection-scoped custom action uses this default button_render; unlike render, this line unconditionally calls record.id, so an action that does not require a specific record still crashes when it is the only index action. Make the id field conditional (and compact the fields) as the regular renderer already does.
view.hidden_field_tag(:id, record.id),
lib/uchi/action/edit.rb:13
Using the generic action name here drops the repository-specific label that the previous edit link used. For example, da.yml defines uchi.repository.author.button.link_to_edit, but this path now falls back to the generic "Edit"; use repository.translate.link_to_edit(record) instead.
name,
lib/uchi/action/edit.rb:37
Using the generic action name here drops the repository-specific label that the previous edit link used. For example, da.yml defines uchi.repository.author.button.link_to_edit, but this path now falls back to the generic "Edit"; use repository.translate.link_to_edit(record) instead.
name,
lib/uchi/action/new.rb:15
perform is part of the action contract and the executions controller will call it for any posted action_name, but repository is not a local or method on Uchi::Action (only the rendering methods receive it). Invoking the built-in New action through the execution endpoint therefore raises NameError instead of redirecting; either make the action non-executable or provide it with a repository before calling perform.
Using the generic action name here drops the repository-specific label that the previous new link used. For example, da.yml defines uchi.repository.author.button.link_to_new, but this path now displays the generic "New"; use repository.translate.link_to_new instead.
name,
lib/uchi/action/new.rb:32
Using the generic action name here drops the repository-specific label that the previous new link used. For example, da.yml defines uchi.repository.author.button.link_to_new, but this path now displays the generic "New"; use repository.translate.link_to_new instead.
The reason will be displayed to describe this comment to others. Learn more.
🔵 Needs a closer look
New and Edit actions must preserve repository-specific localized labels.
Review details
Suppressed comments (4)
lib/uchi/action/edit.rb:13
This replaces the previous repository-localized edit label with the generic action name. repository.translate.link_to_edit(record) is the established API for this text and supports per-model translations (for example, “Rediger bog”); use it here instead of name.
name,
lib/uchi/action/edit.rb:37
The edit link in the dropdown likewise bypasses repository.translate.link_to_edit(record), so localized and repository-specific labels are lost. Use that translation helper here rather than the generic action name.
name,
lib/uchi/action/new.rb:22
This uses the generic action name instead of the repository-localized label. The existing translation contract is repository.translate.link_to_new (see lib/uchi/repository/translate.rb:215), so locales such as the dummy Danish locale lose labels like “Ny forfatter” and fall back to “New”. Use the repository translation here.
name,
lib/uchi/action/new.rb:32
The standalone New button also bypasses the repository-specific button.link_to_new translation and displays the generic action name. Use repository.translate.link_to_new so this extracted action preserves the localization behavior of the previous index header link.
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
Unresolved moderate action-rendering, context, identifier, and API visibility issues remain.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
app/components/uchi/ui/actions/dropdown.rb:51
Using Time.current.to_i as the identifier for a collection-level dropdown makes every such component rendered in the same second share the same button/menu IDs. If a page renders more than one index action component, Stimulus and aria-labelledby can target the wrong menu; use a per-component unique value (for example the component's object_id) for the nil-record case.
@record_id ||= record&.id || Time.current.to_i
lib/uchi/action/new.rb:50
Because this method is defined after protected, Uchi::Action::New.new.name is now protected even though Action#name is a public API and the actions documentation tells consumers to override/call #name. This also breaks callers that inspect or label the built-in New action directly. Keep name public by moving it above protected or adding public :name.
def name
return super unless repository
repository.translate.link_to_new
The reason will be displayed to describe this comment to others. Learn more.
🟡 Changes recommended
One critical and two moderate unresolved issues remain in action context handling, action visibility, and repository title behavior.
Get a fresh assessment by requesting another Copilot review.
Review details
Suppressed comments (2)
lib/uchi/action/new.rb:50
Action#name is public, but the protected declaration above this method makes Uchi::Action::New#name protected. This breaks the base action API for callers that inspect or customize the built-in action (Uchi::Action::New.new.name raises NoMethodError); expose this override publicly like the inherited method.
def name
return super unless repository
repository.translate.link_to_new
test/dummy/app/uchi/repositories/book.rb:23
Repository#title explicitly returns nil for a nil record, but this override now returns the Book repository class instead. Any caller that asks for a title without a record will receive a Class object, which is not a display title and can leak into translation/interpolation code. Preserve the base contract by returning nil when model is absent.
The Delete action could go pretty much everywhere; index, row, edit,
show. However, placing it in the Edit view makes it more contextually
relevant and reduces the risk of accidental deletions.
In order to preserve backwards compatibility with actions already
defining `#render`, the call site (Dropdown's template) must keep
calling `.render(...)`, not `.render_as_dropdown_item(...)`.
- Uchi::Action#render (the old override point) was renamed to
render_as_dropdown_item — this is now the officially documented method
to override.
- A new render was added that just delegates:
render_as_dropdown_item(record:, view:).
- Uchi::Ui::Actions::Dropdown's template still calls action.render(...)
(unchanged) — this is what makes both old and new host-app subclasses
work correctly:
- A host app that overrides render_as_dropdown_item (new style) gets
invoked via polymorphism when the base render delegates.
- A host app that already overrides render directly (old style,
pre-existing) still works, since Ruby dispatches to their override
before ever reaching the base class's delegation logic — the base
render_as_dropdown_item method is simply never called in that case.
- Updated Edit, New, and Delete (Uchi's own built-in actions) to
override render_as_dropdown_item instead of render, since they're not
"host apps" needing the compat shim — they should model the new
official pattern.
When Edit is pushed into the dropdown, this link omits the _top Turbo target that render_as_button sets. Consequently, merely changing action ordering or the dropdown threshold changes whether Edit performs full-page navigation or targets an enclosing Turbo Frame. Keep both render modes behaviorally equivalent.
Dropdown New link omits the _top Turbo target
lib/uchi/action/new.rb:46
When New is pushed into the dropdown (for example, by lowering the repository threshold or placing earlier actions first), this link loses the _top Turbo target used by render_as_button. If the repository page is itself rendered in a Turbo Frame, the same action then navigates only that frame depending on its dropdown placement. Preserve the target in both render paths.
Not that we have any, but the action buttons may appear inside some and
for consistency we should behave the same way regardless of the action
being rendered as a button or as a dropdown item.
Custom action rendering raises NoMethodError without route helpers
lib/uchi/action.rb:83
view is the underlying ActionView context, but uchi_path_to is only mixed into the dropdown component. Applications with config.action_controller.include_all_helpers = false (including the dummy app at test/dummy/config/application.rb:14) therefore raise NoMethodError when a normal custom action is rendered outside the dropdown. Build the execution URL through an API available to the view context, or pass a rendering object that includes Uchi::RoutesHelper.
This issue also appears on line 106 of the same file.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.