Можно ли отключить стандартный маршрут PUT в Rails 4?

Rails 4 представила PATCH запросы как метод запроса по умолчанию при выполнении (общих) частичных обновлений объектов. Это соответствует стандартам HTTP, и хороший (более старый) пост, обсуждающий это решение, можно найти здесь:

http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/

Когда вы определяете ресурс в config/routes.rb, например

    resources :books

то по умолчанию в рельсах создаются следующие маршруты:

    GET     /books       books#index
    GET     /books/:id   books#show
    POST    /books       books#create
    DELETE  /books/:id   books#destroy
    PATCH   /books/:id   books#update
    PUT     /books/:id   books#update

Поскольку я разрабатываю новое приложение и не нуждаюсь в обратной совместимости, я хотел бы удалить устаревший маршрут PUT.

Есть ли простой способ выполнить это в config/routes.rb?


Объяснение, почему этот трафик PUT меня беспокоит: Я использую драгоценный камень swagger-docs для автоматического создания документация для моего API. Из-за описанного поведения у меня всегда есть два определения конечных точек для запросов на обновление (PUT и PATCH) для каждого ресурса. Плюс, поскольку это потенциально опасный маршрут, я бы хотел, чтобы мой API не поддерживал его с сегодняшнего дня.


ОБНОВЛЕНИЕ из-за первого ответа заголовка в неправильном направлении, я хотел бы уточнить: я не хочу удалять действие 'update', но только устаревший маршрут PUT при сохранении маршрута PATCH.

Ответ 1

Чтобы ответить на мой собственный вопрос: нет, в настоящее время невозможно отключить генерацию PUT/PATCH по умолчанию в rails 4, что можно четко увидеть при просмотре источника ActionDispatch:: Routing at https://github.com/rails/rails/blob/master/actionpack/lib/action_dispatch/routing/mapper.rb и особенно эти строки:

      def set_member_mappings_for_resource
        member do
          get :edit if parent_resource.actions.include?(:edit)
          get :show if parent_resource.actions.include?(:show)
          if parent_resource.actions.include?(:update)
            patch :update
            put :update
          end
          delete :destroy if parent_resource.actions.include?(:destroy)
        end
      end

Очевидно, что нет (условно) исключения для маршрута PUT. Я подготовлю вопрос или вытащу запрос на это и вернусь позже с результатом.

До тех пор лучшим решением было бы то, что предложил Хорхе де лос Сантос, хотя это в значительной степени загрязнило бы config/routes.rb.

Ответ 2

Да, проверьте документы:

http://guides.rubyonrails.org/routing.html#restricting-the-routes-created

resources :photos, except: :update

PATCH и PUT предназначены для разных целей. Пока обновление является частичным, вы должны использовать PATCH, но если вы обновляете все, вы должны использовать PUT. Это может показаться запутанным, но, допустим, предположим, что вы обновляете связанную модель, это может считаться действием put вместо патча, если вы не изменяете частичную информацию, вы обновляете все отношение.

Также PUT используется для обновления или создания, возможно, соя может быть полезна при добавлении вложенных ресурсов.

http://weblog.rubyonrails.org/2012/2/25/edge-rails-patch-is-the-new-primary-http-method-for-updates/

--------------- EDIT с решением:

Чтобы переопределить puts ad:

PATCH 'route', to: 'books#update'
resources :books, except: :update

Rails поймает патч перед ресурсами и отключит put и patch для обновления.

Ссылка:

Переопределить "show" ресурс в Rails

Ответ 3

Спустя пару лет и большая версия Rails позже, похоже, не было никакого прогресса в этой проблеме.

Это помогло мне в верхней части routes.rb:

Rails.application.routes.draw do
  def put(*) end
  ...

Поскольку метод set_member_mappings_for_resource, упомянутый в ответе OP, вызывает put, это просто делает его не-op.

Если вам нужны маршруты put, вы можете поместить их выше этой строки. Если вы хотите быть фантазией, вы можете определить метод without_verbs(*verbs, &block), который временно заменяет различные методы глаголов, дает, а затем возвращает их.

Ответ 4

другое решение для переопределения PATCH следующее:

resources :some_resources do
  member { patch action: :event }
end

Это вызовет вызов метода event в SomeResourceController, когда мы назовем этот маршрут PATCH /some_resources/:id

или отключить его:

resources :some_resource, except: :update do
  member { put action: :update }
end