Railsy respond_with: jak to działa?

128

Czytałem tu i ówdzie o tym, jak fajna jest ta respond_withmetoda w Railsach 3. Ale nie mogę nawet znaleźć odniesienia do niej ani w API Railsów, ani przez przeszukiwanie źródeł. Czy ktoś może mi wytłumaczyć, jak to działa (jakich opcji możesz użyć itp.) Lub wskazać miejsce, w którym jest faktycznie zaimplementowane, abym mógł samodzielnie przeczytać kod?

jaydel
źródło

Odpowiedzi:

128

Aktualizacja dla Rails 4.2+

#respond_withi ::respond_to( metoda klasy nb ) niejuż częścią Railsów . Zostały zmigrowane do klejnotu respondentów innych firm od Rails 4.2 ( informacje o wydaniu / zatwierdzenie z sierpnia 2014). Chociaż respondery nie są domyślnie zawarte w Railsach, jest to zależne od Devise, a zatem dostępne w wielu aplikacjach Railsowych.

Jednak #respond_to metoda instancji jest nadal częścią Railsów (5.2rc1 w chwili pisania tego tekstu).

Oficjalna dokumentacja Rails API ActionController::MimeRespondswyjaśnia, jak to #respond_todziała. Oryginalna dokumentacja Rails Guides zawiera komentarze #respond_withi ::respond_tonadal można ją znaleźć w kodzie źródłowym gemów responderów .


Oryginalna odpowiedź

Kod odpowiadający jest oparty na klasie i module. MimeResponds, która jest zawarta w ActionController :: Base , klasie, z której ApplicationControllerdziedziczy. Następnie jest ActionController :: Responder, który zapewnia domyślne zachowanie podczas korzystania z respond_with.


Domyślnie jedyne zachowanie, które szyny dostarcza w odpowiedzi, to niejawna próba renderowania szablonu o nazwie pasującej do akcji. Cokolwiek poza tym wymaga więcej instrukcji w akcji lub niestandardowego wywołania respond_to z blokiem do obsługi odpowiedzi w wielu formatach.

Ponieważ większość kontrolerów używa dość powszechnego wzorca dostosowywania, respondenci zapewniają dodatkowy poziom abstrakcji, wprowadzając bardziej domyślne zachowanie. Przeczytaj akcje wywołujące to_xml / to_json dla określonych formatów i akcje mutatora zapewniające to samo, a także przekierowania dla udanych akcji mutatora.


Istnieje kilka możliwości dostosowania zachowania respondentów, od subtelnych poprawek po całkowite zastąpienie lub rozszerzenie zachowania.

Poziom klasy: respond_to

Tutaj określasz formaty, które powinien obsługiwać obiekt odpowiadający. Formaty można dostosować do czynności, do których będą się odnosić. Każdy format można określić za pomocą oddzielnych wywołań, co umożliwia pełne dostosowanie działań dla każdego formatu.

# 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]

Poziom klasy: responder

To jest atrybut klasy, który zawiera odpowiadającego. Może to być wszystko, co odpowiada na wywołanie, co oznacza, że ​​możesz użyć proc / lambda lub klasy, która odpowiada na wywołanie. Inną alternatywą jest połączenie jednego lub modułów z istniejącym responderem w celu przeciążenia istniejących metod, zwiększając domyślne zachowanie.

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

Chociaż mogą istnieć interesujące przypadki użycia krawędzi, bardziej prawdopodobne jest, że rozszerzanie lub mieszanie modułów do domyślnego respondera byłoby bardziej powszechnymi wzorcami. W każdym razie opcje, które są istotne, to zasoby i opcje, ponieważ są one przekazywane z pliku from respond_with.

Poziom instancji: respond_with

Opcje tutaj to te, które zostaną przekazane do renderowania lub przekierowania w kontrolerze, ale są one uwzględnione tylko w scenariuszach sukcesu. W przypadku akcji GET byłyby to wywołania renderowania, w przypadku innych akcji byłyby to opcje przekierowania. Prawdopodobnie najbardziej użyteczną z nich jest :locationopcja, której można użyć do zastąpienia ścieżki przekierowania w przypadku, gdy argumenty funkcji respond_with nie są wystarczające do zbudowania właściwego adresu 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'))

Alternatywnie, reagujący gem nie tylko udostępnia niektóre moduły do ​​nadpisywania niektórych domyślnych zachowań. Zastępuje domyślny responder anonimową klasą, która rozszerza domyślny responder i zapewnia metodę na poziomie klasy do mieszania niestandardowych modułów do tej klasy. Najbardziej przydatny jest tutaj moduł odpowiadający na flash, który zapewnia domyślny zestaw błysków, domyślnie delegując dostosowywanie do systemu I18n config/locales/en.yml.

Niektóre przykłady niestandardowych respondentów, których użyłem w poprzednich projektach, obejmują respondera, który automatycznie dekorował moje zasoby i zapewniał domyślny zestaw tytułów stron z interfejsem do łatwego dostosowywania lub zastępowania tytułu strony.

Grupa
źródło
1
Myślę, że masz na myśli (w ciele klasy), self.responder =jak tylko responder =przypiszesz do lokalnego
horseyguy
Dziękuję Ci! Istnienie locationopcji było potrzebną mi informacją!
JellicleCat
1
Czy to wyjaśnienie jest nadal aktualne dla Rails 4/5? Słyszałem, że respond_withbyłoby to przestarzałe, ale nie udaje mi się dowiedzieć, dlaczego.
Arnlen,
1
@Arnlen, respond_with został wyodrębniony jako oddzielny klejnot „ responders
Nick Roz
Zwróć uwagę, że aby lampy błyskowe config/locales/en.ymldziałały, potrzebujesz responders :flashna górze kontrolera.
bjnord