Rails response_with: как это работает?

128

Я тут и там читал о том, насколько хорош этот respond_withметод в Rails 3. Но я даже не могу найти ссылку на него ни в Rails API, ни в поиске источника. Может ли кто-нибудь объяснить мне, как это работает (какие параметры вы можете использовать и т. Д.), Или указать мне место, где он фактически реализован, чтобы я мог самостоятельно просмотреть код?

jaydel
источник

Ответы:

128

Обновление для Rails 4.2+

#respond_withи ::respond_to( метод класса nb ) больше не являются частью Rails . Они были перенесены в гем сторонних респондентов начиная с Rails 4.2 ( примечания к выпуску / фиксация от августа 2014 г.). Хотя респонденты не включены в Rails по умолчанию, они зависят от Devise и, следовательно, доступны во многих приложениях Rails.

#respond_to Метод экземпляра, однако, по- прежнему является частью Rails (5.2rc1 с этого письма).

Официальная документация по Rails API ActionController::MimeRespondsобъясняет, как #respond_toработает. Оригинал документации Rails Guides комментарии для #respond_withи до ::respond_toсих пор можно найти в ответчики исходного кода драгоценный камень .


Оригинальный ответ

Код для респондентов основан на классе и модуле. MimeResponds, который входит в класс ActionController :: Base , от которого вы ApplicationControllerнаследуете. Затем есть ActionController :: Responder, который обеспечивает поведение по умолчанию при использовании response_with.


По умолчанию единственное поведение, которое предоставляет в ответе, - это неявная попытка визуализировать шаблон с именем, соответствующим действию. Для всего, что выходит за рамки этого действия, требуются дополнительные инструкции в действии или настраиваемый вызов response_to с блоком для обработки ответов в нескольких форматах.

Поскольку большинство контроллеров используют довольно распространенный шаблон настройки, респонденты обеспечивают дополнительный уровень абстракции, вводя больше поведения по умолчанию. Действия чтения, вызывающие to_xml / to_json для определенных форматов, и действия мутатора, обеспечивающие то же самое, а также перенаправления для успешных действий мутатора.


Есть несколько возможностей настроить поведение респондентов, от тонких настроек до полного переопределения или расширения поведения.

Уровень класса: respond_to

Здесь вы указываете форматы, которые должен обрабатывать Responder. Форматы можно настроить в зависимости от того, к каким действиям они будут применяться. Каждый формат может быть указан с отдельными вызовами, что позволяет полностью настроить действия для каждого формата.

# Responds to html and json on all actions
respond_to :html, :json

# Responds to html and json on index and show actions only.
respond_to :html, :json, :only => [:index,:show]

# Responds to html for everything except show, and json only for index, create and update
respond_to :html, :except => [:show]
respond_to :json, :only => [:index, :create, :update]

Уровень класса: responder

Это атрибут класса, который содержит ответчик. Это может быть все, что отвечает на вызов, что означает, что вы можете использовать proc / lambda или класс, который отвечает на вызов. Другой альтернативой является добавление одного или нескольких модулей к существующему респонденту для перегрузки существующих методов, улучшая поведение по умолчанию.

class SomeController < ApplicationController
  respond_to :json

  self.responder = proc do |controller, resources, options|
    resource = resources.last
    request = controller.request
    if request.get?
      controller.render json: resource
    elsif request.post? or request.put?
      if resource.errors.any?
        render json: {:status => 'failed', :errors => resource.errors}
      else
        render json: {:status => 'created', :object => resource}
      end
    end
  end
end

Хотя могут быть некоторые интересные варианты использования на границе, более вероятно, что расширение или смешивание модулей в ответчике по умолчанию будет более распространенным шаблоном. В любом случае релевантные параметры - это ресурсы и параметры, поскольку они передаются из файла response_with.

Уровень экземпляра: respond_with

Параметры здесь - это те, которые будут переданы в render или redirect_to в вашем контроллере, но они включены только для сценариев успеха. Для действий GET это будут вызовы рендеринга, для других действий - варианты перенаправления. Вероятно, наиболее полезной из них является :locationопция, которая может использоваться для переопределения этого пути перенаправления в случае, если аргументов для response_with недостаточно для создания правильного URL-адреса.

# These two are essentially equal
respond_with(:admin, @user, @post)
respond_with(@post, :location => admin_user_post(@user, @post)

# Respond with a 201 instead of a 200 HTTP status code, and also
# redirect to the collection path instead of the resource path
respond_with(@post, :status => :created, :location => posts_path)

# Note that if you want to pass a URL with a query string
# then the location option would be needed.
# /users?scope=active
respond_with(@user, :location => users_path(:scope => 'active'))

В качестве альтернативы гем респондентов не только предоставляет некоторые модули для переопределения некоторого поведения по умолчанию. Он заменяет ответчик по умолчанию анонимным классом, который расширяет ответчик по умолчанию и предоставляет метод уровня класса для смешивания пользовательских модулей с этим классом. Наиболее полезным здесь является флэш-ответчик, который предоставляет набор вспышек config/locales/en.ymlпо умолчанию , по умолчанию делегируя настройку системе I18n .

Некоторые примеры настраиваемых респондентов, которые я использовал в предыдущих проектах, включают ответчик, который автоматически украшает мои ресурсы и предоставляет набор заголовков страниц по умолчанию с интерфейсом для легкой настройки или переопределения заголовка страницы.

кластер
источник
1
Я думаю, вы имеете в виду (в теле класса) self.responder =как просто responder =назначить местному
horseyguy
Спасибо! Наличие locationопции было той информацией, которая мне была нужна!
JellicleCat
1
Это объяснение все еще актуально для Rails 4/5? Я слышал, что respond_withэто будет устаревшим, но я не могу понять, почему.
Арнлен
1
@Arnlen, response_with был выделен как отдельный драгоценный камень « респонденты »
Ник Роз,
Обратите внимание, что для работы вспышек в вашем контроллере config/locales/en.ymlнеобходимо, чтобы они находились responders :flashв верхней части.
bjnord