Rails response_with: bagaimana cara kerjanya?

128

Saya sudah membaca di sana-sini tentang betapa kerennya respond_withmetode ini di Rails 3. Tapi saya bahkan tidak bisa menemukan referensi untuk itu baik di Rails APIs atau dengan mencari sumbernya. Adakah yang bisa menjelaskan kepada saya bagaimana cara kerjanya (opsi apa yang dapat Anda gunakan, dll) atau mengarahkan saya ke tempat itu sebenarnya dilaksanakan sehingga saya dapat membaca kode sendiri?

jaydel
sumber

Jawaban:

128

Pembaruan untuk Rails 4.2+

#respond_withdan ::respond_to( metode kelas nb ) tidak lagi menjadi bagian dari Rails . Mereka dimigrasikan ke permata responden pihak ketiga pada Rails 4.2 ( catatan rilis / komitmen tanggal Agustus 2014). Walaupun responden tidak termasuk dalam Rails secara default, itu adalah ketergantungan dari Rancangan, dan dengan demikian tersedia di banyak aplikasi Rails.

The #respond_to contoh metode, bagaimanapun, adalah masih bagian dari Rails (5.2rc1 sebagai tulisan ini).

Dokumentasi Rails API resmi untuk ActionController::MimeRespondsmenjelaskan cara #respond_tokerjanya. Dokumentasi Rails Guides yang asli memberikan komentar untuk #respond_withdan ::respond_tomasih dapat ditemukan dalam kode sumber gem responden .


Jawaban Asli

Kode untuk responden didasarkan pada kelas dan modul. MimeResponds yang dimasukkan ke dalam ActionController :: Base , kelas tempat ApplicationControllerasal Anda. Lalu ada ActionController :: Responder yang menyediakan perilaku default saat menggunakan response_with.


Secara default, satu-satunya rel perilaku yang disediakan dalam respons adalah upaya implisit untuk merender template dengan nama yang cocok dengan tindakan. Apa pun di luar itu memerlukan lebih banyak instruksi dalam aksi, atau panggilan response_to kustom dengan blok untuk menangani beberapa respons format.

Karena sebagian besar pengontrol menggunakan pola penyesuaian yang cukup umum, responden memberikan tingkat abstraksi ekstra dengan memperkenalkan lebih banyak perilaku default. Baca tindakan yang memanggil to_xml / to_json untuk format tertentu, dan tindakan mutator menyediakan hal yang sama serta pengalihan untuk tindakan mutator yang berhasil.


Ada beberapa peluang untuk menyesuaikan bagaimana perilaku responden, mulai dari penyesuaian halus hingga sepenuhnya mengesampingkan atau memperluas perilaku.

Tingkat kelas: respond_to

Di sini Anda menentukan format yang harus ditangani Responder. Format dapat disesuaikan untuk tindakan yang akan mereka terapkan. Setiap format dapat ditentukan dengan panggilan terpisah, memungkinkan penyesuaian tindakan untuk setiap format.

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

Tingkat kelas: responder

Ini adalah atribut kelas yang menampung responden. Ini bisa berupa apa saja yang merespons panggilan, yang berarti Anda bisa menggunakan proc / lambda atau kelas yang merespons panggilan. Alternatif lain adalah dengan menggabungkan satu atau modul ke responden yang ada untuk membebani metode yang ada, menambah perilaku default.

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

Meskipun mungkin ada beberapa kasus penggunaan tepi yang menarik, kemungkinan memperluas atau mencampur modul ke dalam responder default akan menjadi pola yang lebih umum. Dalam kasus apa pun, opsi yang relevan adalah sumber daya dan opsi, karena dilewatkan dari dari response_with.

Tingkat Mesin Virtual: respond_with

Opsi di sini adalah opsi yang akan diteruskan ke render atau redirect_to di controller Anda, tetapi mereka hanya disertakan untuk skenario sukses. Untuk tindakan GET ini akan menjadi panggilan render, untuk tindakan lain ini akan menjadi opsi untuk redirect. Mungkin yang paling berguna dari ini adalah :locationopsi, yang dapat digunakan untuk mengganti jalur redirect jika argumen untuk response_with tidak cukup untuk membangun URL yang tepat.

# 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'))

Sebagai alternatif, permata responden tidak hanya menyediakan beberapa modul untuk mengesampingkan beberapa perilaku default. Itu menimpa responden default dengan kelas anonim yang memperluas responden default, dan menyediakan metode tingkat kelas untuk pencampuran modul khusus ke kelas ini. Yang paling berguna di sini adalah flash responder, yang menyediakan set default flash, mendelegasikan kustomisasi ke sistem I18n, config/locales/en.ymlsecara default.

Beberapa contoh responden khusus yang saya gunakan dalam proyek-proyek sebelumnya termasuk responden yang secara otomatis menghiasi sumber saya, dan memberikan satu set judul halaman standar dengan sebuah antarmuka untuk dengan mudah menyesuaikan atau mengganti judul halaman.

Gugus
sumber
1
Saya pikir maksud Anda (di badan kelas) self.responder =hanya responder =akan menugaskan ke lokal
horseyguy
Terima kasih! Keberadaan locationopsi adalah informasi yang saya butuhkan!
JellicleCat
1
Apakah penjelasan itu masih relevan untuk Rails 4/5? Saya pernah mendengar bahwa respond_withitu akan ditinggalkan, tetapi saya tidak berhasil mencari tahu mengapa.
Arnlen
1
@Arnlen, respond_with diekstraksi sebagai permata terpisah ' penanggap '
Nick Roz
Perhatikan bahwa agar blitz dalam config/locales/en.ymlbekerja, Anda perlu responders :flashdi bagian atas pengontrol Anda.
bjnord