Я новичок в Ruby-on-Rails, и мне трудно найти маршруты, соответствующие моему сервису API.
Я разработал свои собственные маршруты для ресурсов, следуя Google AIP-136.
Например, для следующих маршрутов
/books/{book_id}:doSomething
/books/{book_id}:doSomeOtherThing
В config/routes.rb я ожидал, что будет работать следующее:
post '/books/:id/\:doSomething', to: 'books#do_something_handler'
post '/books/:id/\:doSomeOtherThing', to: 'books#do_some_other_thing_handler'
Но это не работает.
Я получаю ActionController::RoutingError (No route matches [POST] "/books/1234:doSomething"):
Я пробовал и другие вещи, но не получил очень удовлетворительного результата.
Может ли кто-нибудь помочь мне, как это сделать правильно.
С использованием -
Привет @max, да, ты прав, конечно, лучше использовать стандартные методы, чем собственные. У меня просто очень конкретное требование. Кроме того, лично я считаю, что Google AIP предоставляет четко определенный набор рекомендаций по проектированию API. Однако, когда дело доходит до дизайна API, я не думаю, что есть какие-то последние слова. Самое главное, чтобы все стороны согласились на это.
Использование ограничений:
# POST /books/1:doSomething
post "/books/:id::custom_method",
to: "books#do_something_handler",
constraint: {custom_method: "doSomething"}
# POST /books/1:doSomethingElse
post "/books/:id::custom_method",
to: "books#do_something_else",
constraints: {custom_method: "doSomethingElse"}
Используя параметр action
рельсов, в этом случае пользовательский метод должен соответствовать имени действия:
# POST /books/1:doSomething
# routes to `doSomething` controller action
post "/books/:id::action", controller: :books
Тестировать:
<%= form_with url: "books/1:doSomething" do |f| %>
<%= f.submit %>
<% end %>
<%= form_with url: "books/1:doSomethingElse" do |f| %>
<%= f.submit %>
<% end %>
маршрут с ограничениями:
Started POST "/books/1:doSomething" for 127.0.0.1 at 2024-07-26 15:36:50 -0400
Processing by BooksController#do_something as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "commit"=>"Save ", "id"=>"1", "custom_method"=>"doSomething"}
Completed 200 OK in 3ms (ActiveRecord: 2.3ms | Allocations: 1332)
Started POST "/books/1:doSomethingElse" for 127.0.0.1 at 2024-07-26 15:36:52 -0400
Processing by BooksController#do_something_else as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "commit"=>"Save ", "id"=>"1", "custom_method"=>"doSomethingElse"}
Completed 200 OK in 2ms (ActiveRecord: 0.1ms | Allocations: 892)
маршрут с параметром action
:
Started POST "/books/1:doSomething" for 127.0.0.1 at 2024-07-26 15:11:22 -0400
Processing by BooksController#doSomething as TURBO_STREAM
Parameters: {"authenticity_token"=>"[FILTERED]", "commit"=>"Save ", "id"=>"1"}
Completed 200 OK in 2ms (ActiveRecord: 0.1ms | Allocations: 1008)
Я все еще получаю ту же ошибку с этими изменениями
@SauravDas, я добавил свой тест. кажется, работает в обоих случаях.
Привет @Alex, когда я добавляю оба маршрута для doSomething
и doSomeOtherThing
, они больше не передаются двум разным обработчикам.
Привет @Алекс, да, ты прав. Я по ошибке написал constraint
без s
, и рельсы вообще не жаловались, а просто продолжали неправильно маршрутизировать меня. Спасибо. Также увидел, что это тоже работает - '/books/:id::custom_method'
без выхода из :
. Принятие ответа.
Вам это действительно нужно? «Пользовательские методы следует использовать только для функций, которые невозможно легко выразить с помощью стандартных методов; по возможности отдавайте предпочтение стандартным методам из-за их последовательной семантики». Я бы, насколько это возможно, старался придерживаться стандартных маршрутов CRUD Rails. Также сомнительно, зачем вам применять набор рекомендаций для собственных API Google к своим собственным. Они, как обычно, чертовски странные.