Skip to content

Commit 5d21838

Browse files
hsbtclaude
authored andcommitted
Resolve user paths to an ID instead of an email address
profile and owned_gems interpolate the identifier into the path, and those endpoints take a handle or a user ID, never an email address. handle_of resolves the email parameter of the owner endpoints, so an owner with no handle produced /api/v1/profiles/someone@example.com.json. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
1 parent 0c709af commit 5d21838

7 files changed

Lines changed: 48 additions & 4 deletions

File tree

‎lib/gems/api/gem_endpoints.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ def autocomplete(query)
5757
# Gems.owned_gems
5858
def owned_gems(user_handle = nil)
5959
path = if user_handle
60-
"/api/v1/owners/#{handle_of(user_handle)}/gems.json"
60+
"/api/v1/owners/#{slug_of(user_handle)}/gems.json"
6161
else
6262
"/api/v1/gems.json"
6363
end

‎lib/gems/api/profile_endpoints.rb‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ module ProfileEndpoints
1818
# @example
1919
# Gems.profile "qrush"
2020
def profile(user)
21-
Profile.new(JSON.parse(get("/api/v1/profiles/#{handle_of(user)}.json")))
21+
Profile.new(JSON.parse(get("/api/v1/profiles/#{slug_of(user)}.json")))
2222
end
2323

2424
# Returns basic information about your account

‎lib/gems/identifiers.rb‎

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,28 @@ def full_name_of(gem, version, platform = nil)
5757
::Gem::NameTuple.new(name_of(gem), number_of(version), platform || platform_of(version)).full_name
5858
end
5959

60-
# Resolve a user identifier from a handle, email address, ID, owner, or profile
60+
# Resolve the email parameter from a handle, email address, owner, or profile
6161
# @api private
6262
# @param owner [String, Integer, Owner, Profile] a handle, email address, user ID, owner, or profile
63-
# @return [String, Integer, nil] the handle or ID, or the email address when the user has no handle
63+
# @return [String, Integer, nil] the handle, or the email address when the user has no handle
6464
def handle_of(owner)
6565
case owner
6666
when Owner, Profile then owner.handle || owner.email
6767
else owner
6868
end
6969
end
7070

71+
# Resolve a user identifier for a URL path from a handle, ID, owner, or profile
72+
# @api private
73+
# @param user [String, Integer, Owner, Profile] a handle, user ID, owner, or profile
74+
# @return [String, Integer, nil] the handle, or the ID when the user has no handle
75+
def slug_of(user)
76+
case user
77+
when Owner, Profile then user.handle || user.id
78+
else user
79+
end
80+
end
81+
7182
# Resolve a URL from a URL or a web hook
7283
# @api private
7384
# @param web_hook [String, WebHook] a URL or web hook

‎sig/gems.rbs‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -302,6 +302,7 @@ module Gems
302302
def platform_of: (version_identifier? version) -> String?
303303
def full_name_of: (gem_identifier gem, version_identifier version, ?String? platform) -> String
304304
def handle_of: (user_identifier owner) -> (String | Integer)?
305+
def slug_of: (user_identifier user) -> (String | Integer)?
305306
def url_of: (web_hook_identifier web_hook) -> String?
306307
def key_of: (api_key_identifier? api_key) -> String?
307308
def timestamp_of: ((Time | String)? time) -> String?

‎spec/gems/api/gem_endpoints_spec.rb‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,13 @@
8888
expect(a_get("/api/v1/owners/1/gems.json")).to have_been_made
8989
end
9090

91+
it "falls back to the ID of an owner without a handle" do
92+
stub_get("/api/v1/owners/1/gems.json").to_return(body: fixture("gems.json"))
93+
client.owned_gems(Gems::Owner.new("id" => 1, "email" => "sferik@gmail.com"))
94+
95+
expect(a_get("/api/v1/owners/1/gems.json")).to have_been_made
96+
end
97+
9198
context "without a user handle" do
9299
before { stub_get("/api/v1/gems.json").to_return(body: fixture("gems.json")) }
93100

‎spec/gems/api/profile_endpoints_spec.rb‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,13 @@
1717
expect(a_get("/api/v1/profiles/1.json")).to have_been_made
1818
end
1919

20+
it "falls back to the ID of an owner without a handle" do
21+
stub_get("/api/v1/profiles/1.json").to_return(body: fixture("profile.json"))
22+
client.profile(Gems::Owner.new("id" => 1, "email" => "nick@quaran.to"))
23+
24+
expect(a_get("/api/v1/profiles/1.json")).to have_been_made
25+
end
26+
2027
it "gets the correct resource" do
2128
client.profile("qrush")
2229

‎spec/gems/identifiers_spec.rb‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,24 @@
8787
end
8888
end
8989

90+
describe "#slug_of" do
91+
it "returns a handle unchanged" do
92+
expect(client.send(:slug_of, "sferik")).to eq("sferik")
93+
end
94+
95+
it "returns the handle of an owner" do
96+
expect(client.send(:slug_of, Gems::Owner.new("id" => 1, "handle" => "sferik"))).to eq("sferik")
97+
end
98+
99+
it "falls back to the ID of an owner without a handle" do
100+
expect(client.send(:slug_of, Gems::Owner.new("id" => 1, "email" => "sferik@gmail.com"))).to eq(1)
101+
end
102+
103+
it "returns the handle of a profile" do
104+
expect(client.send(:slug_of, Gems::Profile.new("id" => 1, "handle" => "sferik"))).to eq("sferik")
105+
end
106+
end
107+
90108
describe "#url_of" do
91109
it "returns a URL unchanged" do
92110
expect(client.send(:url_of, "http://example.com")).to eq("http://example.com")

0 commit comments

Comments
 (0)