Skip to content

Commit 6f7b3e9

Browse files
authored
Merge pull request #175 from rage-rb/route-uri-pattern
Add the `Request#route_uri_pattern` method
2 parents 807ad34 + 5f9bef7 commit 6f7b3e9

8 files changed

Lines changed: 109 additions & 2 deletions

File tree

lib/rage/controller/api.rb

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -448,7 +448,7 @@ def initialize(env, params)
448448
# Get the request object. See {Rage::Request}.
449449
# @return [Rage::Request]
450450
def request
451-
@request ||= Rage::Request.new(@__env)
451+
@request ||= Rage::Request.new(@__env, controller: self)
452452
end
453453
454454
# Get the response object. See {Rage::Response}.
@@ -635,6 +635,12 @@ def stale?(etag: nil, last_modified: nil)
635635
!still_fresh
636636
end
637637
638+
# Get the name of the currently executed action.
639+
# @return [String] the name of the currently executed action
640+
def action_name
641+
@__params[:action]
642+
end
643+
638644
# @private
639645
# for comatibility with `Rails.application.routes.recognize_path`
640646
def self.binary_params_for?(_)

lib/rage/request.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,11 @@ class Rage::Request
3636
KNOWN_HTTP_METHODS = (RFC2616 + RFC2518 + RFC3253 + RFC3648 + RFC3744 + RFC5323 + RFC4791 + RFC5789).to_set
3737

3838
# @private
39-
def initialize(env)
39+
# @param env [Hash] Rack env
40+
# @param controller [RageController::API]
41+
def initialize(env, controller: nil)
4042
@env = env
43+
@controller = controller
4144
end
4245

4346
# Check if the request was made using TLS/SSL which is if http or https protocol is used inside the URL.
@@ -203,6 +206,20 @@ def request_id
203206

204207
alias_method :uuid, :request_id
205208

209+
# Get the route URI pattern matched for this request.
210+
# @return [String] the route URI pattern
211+
# @example
212+
# # For a route defined as:
213+
# # get "/users/:id", to: "users#show"
214+
# request.route_uri_pattern # => "/users/:id"
215+
def route_uri_pattern
216+
if @controller
217+
Rage::Router::Util.route_uri_pattern(@controller.class, @controller.action_name)
218+
else
219+
path
220+
end
221+
end
222+
206223
private
207224

208225
def rack_request

lib/rage/router/util.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,14 @@ def path_to_name(str)
3131
@@names_map[str] = path_to_class(str).name
3232
end
3333
end
34+
35+
@@uri_patterns_map = Hash.new { |h, k| h[k] = {} }
36+
37+
def route_uri_pattern(controller_class, action_name)
38+
@@uri_patterns_map[controller_class][action_name] ||= Rage.__router.routes.find { |route|
39+
route[:meta][:controller_class] == controller_class && route[:meta][:action] == action_name
40+
}[:path]
41+
end
3442
end
3543

3644
# @private

spec/integration/integration_spec.rb

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,18 @@
6969
expect(response.to_s).to start_with("RuntimeError (1155 test error)")
7070
end
7171

72+
it "correctly fetches current action name" do
73+
response = HTTP.get("http://localhost:3000/get_action_name")
74+
expect(response.code).to eq(200)
75+
expect(response.to_s).to eq("get_action_name_action")
76+
end
77+
78+
it "correctly fetches route URI pattern" do
79+
response = HTTP.get("http://localhost:3000/get_route_uri_pattern/123")
80+
expect(response.code).to eq(200)
81+
expect(response.to_s).to eq("/get_route_uri_pattern/:id")
82+
end
83+
7284
it "sets correct headers" do
7385
response = HTTP.get("http://localhost:3000/get")
7486
expect(response.headers["content-type"]).to eq("text/plain; charset=utf-8")

spec/integration/test_app/app/controllers/application_controller.rb

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,12 @@ def raise_error
2929
def get_request_id
3030
render plain: request.request_id
3131
end
32+
33+
def get_action_name_action
34+
render plain: action_name
35+
end
36+
37+
def get_route_uri_pattern
38+
render plain: request.route_uri_pattern
39+
end
3240
end

spec/integration/test_app/config/routes.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
get "empty", to: "application#empty"
1010
get "raise_error", to: "application#raise_error"
1111
get "get_request_id", to: "application#get_request_id"
12+
get "get_action_name", to: "application#get_action_name_action"
13+
get "get_route_uri_pattern/:id", to: "application#get_route_uri_pattern"
1214

1315
get "params/digest", to: "params#digest"
1416
post "params/digest", to: "params#digest"

spec/rage/request_spec.rb

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,4 +252,29 @@
252252
it "returns the correct request ID" do
253253
expect(request.request_id).to eq("5zfcwiy09bary01l")
254254
end
255+
256+
context "#route_uri_pattern" do
257+
context "with no controller passed" do
258+
it "returns the request path" do
259+
expect(request.route_uri_pattern).to eq("/users")
260+
end
261+
end
262+
263+
context "with controller passed" do
264+
subject(:request) { described_class.new(env, controller:) }
265+
266+
let(:controller) { double }
267+
268+
it "calls Rage::Router::Util" do
269+
expect(controller).to receive(:class).and_return("test-class")
270+
expect(controller).to receive(:action_name).and_return("test-action")
271+
272+
expect(Rage::Router::Util).to receive(:route_uri_pattern).
273+
with("test-class", "test-action").
274+
and_return("test-uri-pattern")
275+
276+
expect(request.route_uri_pattern).to eq("test-uri-pattern")
277+
end
278+
end
279+
end
255280
end

spec/router/util_spec.rb

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,4 +73,33 @@
7373
expect(described_class.path_to_name("test")).to eq("test-name")
7474
end
7575
end
76+
77+
describe "#route_uri_pattern" do
78+
let(:users_controller) { double }
79+
80+
let(:routes) do
81+
[
82+
{
83+
method: "GET",
84+
path: "/users",
85+
meta: { controller: "users", action: "index", controller_class: users_controller }
86+
},
87+
{
88+
method: "GET",
89+
path: "/users/:id",
90+
meta: { controller: "users", action: "show", controller_class: users_controller }
91+
}
92+
]
93+
end
94+
95+
it "returns the path property" do
96+
expect(Rage.__router).to receive(:routes).and_return(routes)
97+
expect(described_class.route_uri_pattern(users_controller, "show")).to eq("/users/:id")
98+
end
99+
100+
it "caches the result" do
101+
expect(Rage.__router).to receive(:routes).and_return(routes).once
102+
2.times { described_class.route_uri_pattern(users_controller, "show") }
103+
end
104+
end
76105
end

0 commit comments

Comments
 (0)