From 280e8b986801d93079d253525a95dfce95402580 Mon Sep 17 00:00:00 2001 From: Roman Samoilov <2270393+rsamoilov@users.noreply.github.com> Date: Tue, 7 May 2024 19:41:33 +0100 Subject: [PATCH 1/3] Add the `member` route helper --- lib/rage/router/dsl.rb | 21 +++++++++++++++++++++ spec/router/dsl_spec.rb | 30 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) diff --git a/lib/rage/router/dsl.rb b/lib/rage/router/dsl.rb index 9433bfb8..072aa21e 100644 --- a/lib/rage/router/dsl.rb +++ b/lib/rage/router/dsl.rb @@ -267,6 +267,27 @@ def collection(&block) @path_prefixes = orig_path_prefixes end + # Add a member route. + # + # @example Add a `photos/:id/preview` path instead of `photos/:photo_id/preview` + # resources :photos do + # member do + # get "preview" + # end + # end + def member(&block) + orig_path_prefixes = @path_prefixes + + if (param_prefix = @path_prefixes.last)&.start_with?(":") && @controllers.any? + member_prefix = param_prefix.delete_prefix(":#{to_singular(@controllers.last)}_") + @path_prefixes = [*@path_prefixes[0...-1], ":#{member_prefix}"] + end + + instance_eval &block + + @path_prefixes = orig_path_prefixes + end + # Automatically create REST routes for a resource. # # @example Create five REST routes, all mapping to the `Photos` controller: diff --git a/spec/router/dsl_spec.rb b/spec/router/dsl_spec.rb index ec25a3bb..b3a42b74 100644 --- a/spec/router/dsl_spec.rb +++ b/spec/router/dsl_spec.rb @@ -575,6 +575,31 @@ def call(env) end end + it "correctly creates nested routes on member" do + expect(router).to receive(:on).with("GET", "/photos/:id", "photos#show", instance_of(Hash)) + expect(router).to receive(:on).with("POST", "/photos/:id/like", "photos#like", instance_of(Hash)) + + dsl.draw do + resources :photos, only: :show do + member do + post :like + end + end + end + end + + it "correctly creates nested routes on member with a custom param" do + expect(router).to receive(:on).with("POST", "/photos/:photo_uuid/like", "photos#like", instance_of(Hash)) + + dsl.draw do + resources :photos, only: [], param: :photo_uuid do + member do + post :like + end + end + end + end + it "correctly creates nested resources" do expect(router).to receive(:on).with("GET", "/albums", "albums#index", instance_of(Hash)) expect(router).to receive(:on).with("POST", "/albums", "albums#create", instance_of(Hash)) @@ -606,6 +631,7 @@ def call(env) expect(router).to receive(:on).with("DELETE", "/albums/:album_slug/my_photos/:id", "photos#destroy", instance_of(Hash)) expect(router).to receive(:on).with("POST", "/albums/:album_slug/my_photos/:photo_id/add_to_album", "photos#add_to_album", instance_of(Hash)) expect(router).to receive(:on).with("POST", "/albums/:album_slug/my_photos/like_all", "photo_likes#create", instance_of(Hash)) + expect(router).to receive(:on).with("GET", "/albums/:album_slug/my_photos/:id/keywords", "photos#keywords", instance_of(Hash)) expect(router).to receive(:on).with("POST", "/albums/sort", "albums#sort", instance_of(Hash)) expect(router).to receive(:on).with("PATCH", "/albums/:album_slug/tag", "albums#tag", instance_of(Hash)) @@ -618,6 +644,10 @@ def call(env) collection do post "like_all", to: "photo_likes#create" end + + member do + get :keywords + end end collection do From 25ef70b32b34e3209e226b1bc193a5a726bf222a Mon Sep 17 00:00:00 2001 From: Roman Samoilov <2270393+rsamoilov@users.noreply.github.com> Date: Wed, 8 May 2024 10:00:56 +0100 Subject: [PATCH 2/3] Document the `controller` option --- lib/rage/router/dsl.rb | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/lib/rage/router/dsl.rb b/lib/rage/router/dsl.rb index 072aa21e..7874bccf 100644 --- a/lib/rage/router/dsl.rb +++ b/lib/rage/router/dsl.rb @@ -209,6 +209,7 @@ def namespace(path, **options, &block) # @param [Hash] opts scope options. # @option opts [String] :module module option # @option opts [String] :path path option + # @option opts [String] :controller controller option # @example Route `/photos` to `Api::PhotosController` # scope module: "api" do # get "photos", to: "photos#index" @@ -217,6 +218,11 @@ def namespace(path, **options, &block) # scope path: "admin" do # get "photos", to: "photos#index" # end + # @example Route `/like` to `photos#like` and `/dislike` to `photos#dislike` + # scope controller: "photos" do + # post "like" + # post "dislike" + # end # @example Nested calls # scope module: "admin" do # get "photos", to: "photos#index" From 298a18f73d89de0c82511ac5d8c1f7832d97da66 Mon Sep 17 00:00:00 2001 From: Roman Samoilov <2270393+rsamoilov@users.noreply.github.com> Date: Wed, 8 May 2024 10:01:29 +0100 Subject: [PATCH 3/3] Add the `controller` helper --- lib/rage/router/dsl.rb | 13 +++++++++++++ spec/router/dsl_spec.rb | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/lib/rage/router/dsl.rb b/lib/rage/router/dsl.rb index 7874bccf..f78f2ea8 100644 --- a/lib/rage/router/dsl.rb +++ b/lib/rage/router/dsl.rb @@ -258,6 +258,19 @@ def defaults(defaults, &block) @defaults.pop end + # Scopes routes to a specific controller. + # + # @example + # controller "photos" do + # post "like" + # post "dislike" + # end + def controller(controller, &block) + @controllers << controller + instance_eval &block + @controllers.pop + end + # Add a route to the collection. # # @example Add a `photos/search` path instead of `photos/:photo_id/search` diff --git a/spec/router/dsl_spec.rb b/spec/router/dsl_spec.rb index b3a42b74..787682be 100644 --- a/spec/router/dsl_spec.rb +++ b/spec/router/dsl_spec.rb @@ -118,6 +118,27 @@ end end + context "with controller scope" do + it "correctly adds handlers" do + expect(router).to receive(:on).with("POST", "/api/v1/like", "api/v1/photos#like", instance_of(Hash)) + expect(router).to receive(:on).with("POST", "/api/v1/dislike", "api/v1/photos#dislike", instance_of(Hash)) + expect(router).to receive(:on).with("GET", "/api/v1/index", "api/v1/all_photos#index", instance_of(Hash)) + + dsl.draw do + namespace "api/v1" do + scope controller: "photos" do + post "like" + post "dislike" + end + + controller "all_photos" do + get "index" + end + end + end + end + end + context "with root helper inside a scope" do it "correctly adds handlers" do expect(router).to receive(:on).with("GET", "/api/v1/internal", "api/test#index", a_hash_including(constraints: {}))