Skip to content

Commit 1dd959a

Browse files
iHiDampcode-com
andauthored
Amp Improvemnts (#8186)
* Amp Improvemnts * Fix glossary entry proposal command signatures - Update Approve and Reject commands to accept proposal directly instead of glossary_entry - Fix controller to pass @proposal to Approve/Reject commands - Update test expectations to match corrected command signatures - Resolves logical inconsistency where commands tried to find proposals through glossary entries Co-authored-by: Amp <amp@ampcode.com> Amp-Thread-ID: https://ampcode.com/threads/T-b0f4fc46-b5d8-47f8-899f-b9cab8f38b5f --------- Co-authored-by: Amp <amp@ampcode.com>
1 parent 3fe0426 commit 1dd959a

18 files changed

Lines changed: 250 additions & 32 deletions

AGENTS.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,11 @@ rm -rf .built-assets/ # Clear asset cache if needed
116116
4. Add appropriate tests (see testing docs)
117117
5. Run pre-commit validation commands
118118

119+
**Code Style:**
120+
121+
- **Always use symbol key syntax (`key:`) in hashes** - Use `{ name: "value" }` not `{ "name" => "value" }` unless there's a specific reason to use string keys (like when the key contains special characters or spaces)
122+
- This applies to serializers, API responses, and all Ruby hash structures
123+
119124
## Reference Documentation
120125

121126
- `docs/context/overview.md` - Complete codebase documentation and setup guide
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
class AssembleLocalizationGlossaryEntries
2+
include Mandate
3+
4+
initialize_with :user, :params
5+
6+
def self.keys
7+
%i[criteria status page]
8+
end
9+
10+
def call
11+
SerializePaginatedCollection.(
12+
glossary_entries,
13+
serializer: SerializeLocalizationGlossaryEntries,
14+
serializer_args: user,
15+
meta: {
16+
unscoped_total: Localization::GlossaryEntry.count
17+
}
18+
)
19+
end
20+
21+
memoize
22+
def glossary_entries
23+
Localization::GlossaryEntry::Search.(
24+
user,
25+
criteria: params[:criteria],
26+
status: params[:status],
27+
page: params[:page]
28+
)
29+
end
30+
end
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
class Localization::GlossaryEntry::Search
2+
include Mandate
3+
4+
DEFAULT_PAGE = 1
5+
DEFAULT_PER = 24
6+
7+
def self.default_per
8+
DEFAULT_PER
9+
end
10+
11+
def initialize(user, page: nil, per: nil, criteria: nil, status: nil)
12+
@user = user
13+
14+
@criteria = criteria
15+
@status = status
16+
@page = page.present? && page.to_i.positive? ? page.to_i : DEFAULT_PAGE
17+
@per = per.present? && per.to_i.positive? ? per.to_i : self.class.default_per
18+
end
19+
20+
def call
21+
@glossary_entries = Localization::GlossaryEntry.where(locale: locales)
22+
23+
filter_criteria!
24+
filter_status!
25+
26+
paginated_glossary_entries = @glossary_entries.page(page).per(per)
27+
28+
Kaminari.paginate_array(
29+
paginated_glossary_entries,
30+
total_count: @glossary_entries.count
31+
).page(page).per(per)
32+
end
33+
34+
memoize
35+
def locales = user.translator_locales - [:en]
36+
37+
private
38+
attr_reader :user, :per, :page, :criteria, :status
39+
40+
def filter_criteria!
41+
return if criteria.blank?
42+
43+
@glossary_entries = @glossary_entries.where(
44+
"localization_glossary_entries.term LIKE ? OR localization_glossary_entries.translation LIKE ?",
45+
"%#{criteria}%", "%#{criteria}%"
46+
)
47+
end
48+
49+
def filter_status!
50+
return if status.blank?
51+
52+
@glossary_entries = @glossary_entries.where("localization_glossary_entries.status": status)
53+
end
54+
end

app/commands/localization/glossary_entry_proposal/approve.rb

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,16 @@ def handle_addition!
3030
end
3131

3232
def handle_modification!
33-
raise "No glossary entry to modify" if glossary_entry.nil?
33+
raise "No glossary entry to modify" if proposal.glossary_entry.nil?
3434

35-
glossary_entry.update!(
35+
proposal.glossary_entry.update!(
3636
translation: proposal.translation,
3737
llm_instructions: proposal.llm_instructions
3838
)
3939
end
4040

4141
def handle_deletion!
42-
raise "No glossary entry to delete" if glossary_entry.nil?
42+
raise "No glossary entry to delete" if proposal.glossary_entry.nil?
4343

4444
# Retrieve this before destroying else we have a race
4545
glossary_entry = proposal.glossary_entry
@@ -48,6 +48,4 @@ def handle_deletion!
4848
proposal.update!(glossary_entry: nil)
4949
glossary_entry.destroy!
5050
end
51-
52-
delegate :glossary_entry, to: :proposal
5351
end
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
class Localization::GlossaryEntryProposal
2+
class Create
3+
include Mandate
4+
5+
initialize_with :glossary_entry, :user, :value
6+
7+
def call
8+
# For existing glossary entries, create a modification proposal
9+
CreateModification.(glossary_entry, user, value, "")
10+
end
11+
end
12+
end

app/commands/localization/glossary_entry_proposal/reject.rb

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,4 @@ def call
1111
)
1212
end
1313
end
14-
15-
delegate :glossary_entry, to: :proposal
1614
end

app/controllers/api/localization/glossary_entry_proposals_controller.rb

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,23 @@ def create
66
Localization::GlossaryEntryProposal::Create.(@glossary_entry, current_user, params[:value])
77

88
render json: {
9-
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry)
10-
9+
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry, current_user)
1110
}, status: :created
1211
end
1312

1413
def approve
15-
Localization::GlossaryEntryProposal::Approve.(@glossary_entry, current_user)
14+
Localization::GlossaryEntryProposal::Approve.(@proposal, current_user)
1615

1716
render json: {
18-
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry)
17+
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry, current_user)
1918
}
2019
end
2120

2221
def reject
23-
Localization::GlossaryEntryProposal::Reject.(@glossary_entry, current_user)
22+
Localization::GlossaryEntryProposal::Reject.(@proposal, current_user)
2423

2524
render json: {
26-
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry)
25+
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry, current_user)
2726
}
2827
end
2928

@@ -36,7 +35,7 @@ def update
3635
end
3736

3837
render json: {
39-
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry)
38+
glossary_entry: SerializeLocalizationGlossaryEntry.(@glossary_entry, current_user)
4039
}
4140
end
4241

app/controllers/localization/glossary_entries_controller.rb

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
class Localization::Controller < ApplicationController
1+
class Localization::GlossaryEntriesController < ApplicationController
22
def index
33
@glossary_entries = AssembleLocalizationGlossaryEntries.(current_user, params)[:results]
44
@glossary_entries_params = params.permit(:criteria, :status, :page)
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
11
class Localization::GlossaryEntry < ApplicationRecord
2+
enum :status, {
3+
generating: 0,
4+
unchecked: 1,
5+
proposed: 2,
6+
checked: 3
7+
}
8+
29
has_many :proposals, class_name: "Localization::GlossaryEntryProposal", dependent: :destroy
10+
11+
before_create do
12+
self.uuid = SecureRandom.uuid if uuid.blank?
13+
self.status = :unchecked if status.blank?
14+
end
15+
16+
def to_param = uuid
17+
def status = super.to_sym
318
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
class SerializeLocalizationGlossaryEntries
2+
include Mandate
3+
4+
initialize_with :glossary_entries, :user
5+
6+
def call
7+
glossary_entries_with_includes.map do |glossary_entry|
8+
{
9+
uuid: glossary_entry.uuid,
10+
locale: glossary_entry.locale,
11+
term: glossary_entry.term,
12+
translation: glossary_entry.translation,
13+
status: glossary_entry.status.to_s,
14+
llm_instructions: glossary_entry.llm_instructions,
15+
proposals_count: proposals[glossary_entry.id]&.length || 0
16+
}
17+
end
18+
end
19+
20+
def glossary_entries_with_includes
21+
glossary_entries.to_active_relation
22+
end
23+
24+
memoize
25+
def proposals
26+
Localization::GlossaryEntryProposal.
27+
where(glossary_entry: glossary_entries).
28+
where.not(status: :rejected).
29+
group_by(&:glossary_entry_id)
30+
end
31+
end

0 commit comments

Comments
 (0)