Files
sure/app/controllers/goal_pledges_controller.rb
Guillem Arias eb7ef50eed fix(goals): CI green — schema, brakeman, pledge modal, error class
Regenerate schema.rb after the three v2 migrations so CI's db:schema:load
picks up goal_pledges, the dropped goal_contributions, and the partial
unique pledge_id index.

Brakeman:
- Drop :account_id and :kind from goal_pledge permit; look the account
  up via @goal.linked_accounts.find_by(id:) instead and set kind
  server-side from goal.any_connected_account?.
- Rename goals.show.projection.on_track to .on_track_html so I18n
  marks the result html_safe automatically; drop the unconditional
  .html_safe call in show.html.erb.

Pledge modal: rewrite app/views/goal_pledges/new.html.erb to use
DS::Dialog (the Sure convention for create modals — matches
categories/transfers).

Error handling: replace `raise ActiveRecord::RecordInvalid, "string"`
in GoalPledge#extend!/cancel! with a dedicated GoalPledge::NotOpenError;
the controller rescues that specifically.

Tests: rewrite the "pace is zero" test to create a fresh account with
no entries (the fixture's depository accounts carry transaction history
that produces a non-zero pace). All goal tests now green (73 runs,
157 assertions, 0 failures).
2026-05-14 17:54:08 +02:00

73 lines
1.8 KiB
Ruby

class GoalPledgesController < ApplicationController
before_action :set_goal
before_action :set_pledge, only: %i[extend destroy]
rescue_from ActiveRecord::RecordNotFound, with: :record_not_found
def new
@pledge = @goal.goal_pledges.new(
currency: @goal.currency,
kind: default_kind_for(@goal),
amount: params[:amount].presence
)
end
def create
@pledge = @goal.goal_pledges.new(pledge_params)
@pledge.account = lookup_account(params.dig(:goal_pledge, :account_id))
@pledge.kind = default_kind_for(@goal)
@pledge.currency = @goal.currency
if @pledge.save
flash[:notice] = t(".success")
respond_to do |format|
format.html { redirect_to goal_path(@goal) }
format.turbo_stream do
render turbo_stream: turbo_stream.action(:redirect, goal_path(@goal))
end
end
else
render :new, status: :unprocessable_entity
end
end
def extend
@pledge.extend!
redirect_to goal_path(@goal), notice: t(".success")
rescue GoalPledge::NotOpenError
redirect_to goal_path(@goal), alert: t(".not_open")
end
def destroy
@pledge.cancel!
redirect_to goal_path(@goal), notice: t(".success")
rescue GoalPledge::NotOpenError
redirect_to goal_path(@goal), alert: t(".not_open")
end
private
def set_goal
@goal = Current.family.goals.find(params[:goal_id])
end
def set_pledge
@pledge = @goal.goal_pledges.find(params[:id])
end
def pledge_params
params.require(:goal_pledge).permit(:amount)
end
def lookup_account(id)
return nil if id.blank?
@goal.linked_accounts.find_by(id: id)
end
def default_kind_for(goal)
goal.any_connected_account? ? "transfer" : "manual_save"
end
def record_not_found
redirect_to goals_path, alert: t("goals.errors.not_found")
end
end