Raylar: response_to bloğu nasıl çalışır?


211

Rails ile Başlarken rehberinden geçiyorum ve bölüm 6.7 ile karıştırıldım. Bir iskele oluşturduktan sonra denetleyicimde aşağıdaki otomatik oluşturulan bloğu buluyorum:

def index
  @posts = Post.all

  respond_to do |format|
    format.html  # index.html.erb
    format.json  { render :json => @posts }
  end
end

Response_to bloğunun gerçekten nasıl çalıştığını anlamak istiyorum. Format nedir? Biçim nesnesinin .html ve .json yöntemleri var mı? dokümantasyon için

ActionController::MimeResponds::ClassMethods::respond_to

soruyu cevaplamıyor.


ActionController :: MimeResponds :: ClassMethods :: response_to belgelerine bağlanabilirsem güzel olurdu ama api.rubyonrails.org doğrudan köprülere benzemiyor ...
Cole

answer_to çağrının sonunu alır (örn. blah.html, blah.json, vb.) ve belirtilen görünümle eşleşir. Diğer yanıtlar, uygulamaya bağlı olarak XML, CSV ve daha pek çok şey olabilir.
ScottJShea

5
"Belirtilen görünümle nasıl eşleşiyor?"
Cole

Ben uzantı (xml, html, vb) bir görünüm eşler sanmıyorum. Varsayılan oluşturmayı ( format.html- bağımsız değişken yok) seçerseniz, bir görünüm (HTML olması bekleniyor) seçmek için kurallar (URL ve HTTP fiiline dayalı olarak) kullanılır. Burada yanıtlayıcıya (biçim), görünümleri ve kuralları kullanmak yerine .json ile biten URL'leri json'a serileştirerek oluşturma talimatı verilir .
Craig Celeste

Yanıtlar:


189

Ruby için yeniyim ve aynı koda takılı kaldım. Asıldığım parçalar, burada bulduğum bazı cevaplardan biraz daha temeldi. Bu birine yardım edebilir veya etmeyebilir.

  • respond_toüst sınıfta bir yöntemdir ActionController.
  • bir delege gibi bir blok alır. Blok ila dokadar endolan, |format|bloğun bir bağımsız değişken olarak.
  • response_to bloğunuzu yürütür ve bir Yanıtlayıcıyı formatbağımsız değişkene geçirir .

http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html

  • Responderİçin bir yöntem İÇERMEZ .htmlya .json, ama biz bu yöntemleri neyse diyoruz! Bu kısım beni bir döngü için attı.
  • Ruby adlı bir özelliği var method_missing. Var olmayan bir yöntemi ( jsonveya gibi html) çağırırsanız, Ruby method_missingbunun yerine yöntemi çağırır .

http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html

  • ResponderSınıfın onun kullandığı method_missingtescil bir çeşit. 'Json' dediğimizde, json'a serileştirerek .json uzantılı isteklere yanıt vermesini söylüyoruz. Biz çağırmanız gerekir html(kuralları ve görünümleri kullanarak) varsayılan şekilde .html istekleri işlemek için bunu söylemek için hiçbir argümanlarla.

Bu şekilde yazılabilir (JS benzeri sahte kod kullanılarak):

// get an instance to a responder from the base class
var format = get_responder()

// register html to render in the default way
// (by way of the views and conventions)
format.register('html')

// register json as well. the argument to .json is the second
// argument to method_missing ('json' is the first), which contains
// optional ways to configure the response. In this case, serialize as json.
format.register('json', renderOptions)

Bu kısım beni şaşırttı. Hala kasıtsız buluyorum. Ruby bu tekniği biraz kullanıyor gibi görünüyor. Tüm class ( responder) yöntemi uygulama haline gelir. Kaldıraç method_missingiçin sınıfın bir örneğine ihtiyacımız var, bu yüzden yöntem benzeri nesneyi geçtikleri bir geri çağrıyı iletmek zorundayız. Birkaç yıl boyunca C benzeri dillerde kod yazmış biri için, bu benim için çok geriye dönük ve sezgisel değil. Kötü olduğu için değil! Ama bu tür bir arka plana sahip birçok insanın başını döndürmesi gereken bir şey ve bence OP'nin peşinde olduğu şey olabilir.

ps RoR 4.2 yanıtlayanlar mücevher respond_toekstrakte edildi unutmayın .


Teşekkürler Craig, bu bağlantı aslında bir ton yararlı bilgiye sahipti method_missing, argümanları ve bir bloğu aktarabileceğinizi düşünerek ne kadar mümkün olduğunu fark etmedim !
Aditya MP

2
Responder sınıfında bir kayıt mekanizması olarak method_missing () kullanımını açıklamanın en iyi yanıtı! Ayrıca bu kodla çok karıştım.
Alan Evangelista

1
Raylar 6 iskele jeneratörleri respond_to, Gemfile'da yanıt veren mücevher olmadan kontrol cihazlarında kod üretiyor gibi görünüyor . Belki de respond_tocevap veren mücevher çıkarılan hakkında biraz değişti?
Qasim

106

Bu, Rails yardımcı yönteminden yararlanan bir Ruby kodu bloğudur. Henüz bloklara aşina değilseniz, Ruby'de çok şey göreceksiniz.

respond_toController sınıfına (veya daha doğrusu süper sınıfına) eklenen bir Rails yardımcı yöntemidir. Görünüme (tarayıcıya gidecek olan) gönderilecek yanıta başvuruyor.

Örneğinizdeki blok, bir tarayıcı html veya json verileri için her istekte bulunduğunda denetleyiciden görünüme gönderilecek verileri - blokta bir 'format' parametresini geçirerek - biçimlendirmektir.

Yerel makinenizdeyseniz ve Post iskele kurulumunuz varsa, gidebilirsiniz http://localhost:3000/postsve tüm yayınlarınızı html formatında görürsünüz. Ancak, şunu yazarsanız:, http://localhost:3000/posts.jsontüm gönderilerinizi sunucudan gönderilen bir json nesnesinde görürsünüz.

Bu, sunucudan json ileri ve geri geçmesi gereken javascript ağır uygulamalar yapmak için çok kullanışlıdır. İsterseniz, raylarınızın arka ucunda kolayca bir json api oluşturabilir ve yalnızca bir görünüm geçirebilirsiniz - Post denetleyicinizin dizin görünümü gibi. Ardından, verileri işlemek ve kendi arayüzünüzü oluşturmak için Jquery veya Omurga (veya her ikisi) gibi bir javascript kütüphanesi kullanabilirsiniz . Bunlara eşzamansız kullanıcı arayüzleri denir ve gerçekten popüler hale gelirler (Gmail birdir). Çok hızlıdırlar ve son kullanıcıya web'de daha masaüstü benzeri bir deneyim sunarlar. Elbette, bu verilerinizi biçimlendirmenin sadece bir avantajıdır.

Rails 3 yazmanın yolu şöyle olurdu:

    class PostsController < ApplicationController
      # GET /posts
      # GET /posts.xml


      respond_to :html, :xml, :json

      def index
        @posts = Post.all

        respond_with(@posts)
      end

#
# All your other REST methods
#

end

respond_to :html, :xml, :jsonSınıfın en üstüne koyarak , denetleyicinizin görünümlerinize göndermesini istediğiniz tüm formatları bildirebilirsiniz.

Ardından, denetleyici yönteminde tek yapmanız gereken yanıt_with (@whatever_object_you_have)

Kodunuzu Rails'in otomatik olarak oluşturduğundan biraz daha basitleştirir.

Bunun iç işleyişini bilmek istiyorsanız ...

Anladığım kadarıyla, Rails, gerçek formatın ne olacağını belirlemek için nesneleri iç içe geçirir. 'Format' değişkenleri değeri bu içgözlemi temel alır. Raylar biraz bilgi ile çok şey yapabilir. Basit bir @ post veya: yazısının ne kadar ilerleyeceğine şaşıracaksınız.

Örneğin, şöyle görünen bir _user.html.erb kısmi dosyası vardı:

_user.html.erb

<li>    
    <%= link_to user.name, user %>
</li>

Daha sonra, dizin görünümümde bu tek başına Rails 'kullanıcıları' kısmi bulmak ve tüm 'kullanıcılar' nesneleri üzerinden yineleme gerektiğini bildirir:

index.html.erb

 <ul class="users">
   <%= render @users %>     
 </ul>

Rails 'kullanıcı' kısmi bulmak ve tüm 'kullanıcılar' nesneleri üzerinden yineleme gerektiğini bilmek:

Bu blog gönderisini faydalı bulabilirsiniz: http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with

Ayrıca kaynağı inceleyebilirsiniz: https://github.com/rails/rails


1
Rails3 yolda güzel ipucu. Hala response_to bloğunun en altına almaya çalışıyorum ve ne blok argümanı | format | geçer.
Cole

4
İyi cevap ama bloğa geçirilen biçim değişkeni hakkında özel bir şey söylemiyor. Verilen örnekte format.html ve format.json var - bunların her ikisi de response_to'ya geçiyor ve daha sonra response_to onlarla ne yapacağına karar veriyor mu?
Anthony

ne zaman oldu respond_tove respond_withtanıtılan? 2.3.5 rayları kullanıyorum ve alıyorumNoMethodError (undefined method respond_to)
abbood

10

Bildiğim kadarıyla, response_to, ActionController'a eklenmiş bir yöntemdir, bu nedenle, her biri tek bir denetleyicide kullanabilirsiniz, çünkü hepsi ActionController'dan devralır. İşte Rails response_to yöntemi:

def respond_to(&block)
  responder = Responder.new(self)
  block.call(responder)
  responder.respond
end

Burada gösterdiğim gibi bir blok geçiriyorsunuz:

respond_to <<**BEGINNING OF THE BLOCK**>> do |format|
  format.html
  format.xml  { render :xml => @whatever }
end <<**END OF THE BLOCK**>>

| Biçimi | bölüm, bloğun beklediği argümandır, bu nedenle answer_to yöntemi içinde bunu kullanabiliriz. Nasıl?

Peki, bloğu önekli & answer_to yönteminde geçirdiğimizi fark ederseniz ve bunu bu bloğa Proc olarak davranmak için yaparız. Argümanın ".xml", ".html" olduğundan, çağrılacak yöntemler olarak bunu kullanabiliriz.

Answer_to sınıfında temel olarak yaptığımız, bir Responder sınıfının örneğine ".html, .xml, .json" yöntemlerini çağırmaktır.


1
Api dokümanlarındaki response_to kaynağı, dahil ettiğiniz kaynaktan farklı ve beni atıyordu. Snippet'iniz bana format bloğu argümanının bir Responder nesnesinden geçtiğini daha net gösteriyor. Yanıtlayan belgeleri şu anda soruyu cevaplıyor gibi görünüyor.
Cole

7

Response_to bloğunun gerçekten nasıl çalıştığını anlamak istiyorum. Format nedir? Biçim nesnesinin .html ve .json yöntemleri var mı?

Ne formatolduğunu anlamak için önce kaynağa bakabilirsiniz respond_to, ancak hızlı bir şekilde gerçekten bakmanız gereken şeyin retrieve_response_from_mimes kodu olduğunu göreceksiniz .

Buradan, respond_to(kodunuzda) geçirilen bloğun aslında bir Toplayıcı örneği ile çağrıldığını ve geçtiğini göreceksiniz (bu blok içinde blok olarak adlandırılır format). Kollektör temelde dayalı (I Raylar balangcnda inanmak) yöntemlerini oluşturur mim türleri bilir raylar.

Evet, .htmlve .json, Collector (aka format) sınıfında (çalışma zamanında) tanımlanan yöntemlerdir .


2

Cevaplayıcı kaydının ardındaki meta-programlama (Parched Squid'in cevabına bakınız) ayrıca şöyle şık şeyler yapmanıza izin verir:

def index
  @posts = Post.all

  respond_to do |format|
    format.html  # index.html.erb
    format.json  { render :json => @posts }
    format.csv   { render :csv => @posts }
    format.js
  end
end

Csv satırı, /posts.csv adresini ziyaret ettiğinizde her yayında to_csv'nin çağrılmasına neden olur. Bu, raylar sitenizden CSV (veya başka bir biçim) olarak veri aktarmayı kolaylaştırır.

Js satırı /posts.js (veya /posts.js.coffee) bir javascript dosyasının oluşturulmasına / yürütülmesine neden olacaktır. Ben jQuery UI pop-up kullanarak Ajax etkin bir site oluşturmak için hafif bir yol olduğunu buldum.


1

Format nedir?

Java POV'dan biçim anonim bir arayüzün bir uygulamasıdır. Bu arabirimin her mime türü için bir yöntemi vardır. Bu yöntemlerden birini çağırdığınızda (bir blok geçirerek), raylar kullanıcının bu içerik türünü istediğini düşünüyorsanız, bloğunuzu çağırır.

Elbette, bu anonim tutkal nesnesi aslında bir arayüz uygulamaz - yöntem dinamik çağrıları yakalar ve onun bildiği bir mime türünün adı ise işe yarar.

Şahsen, sanırım garip görünüyor: geçtiğiniz blok yürütüldü . Biçim etiketlerinin ve bloklarının bir özetini iletmek benim için daha anlamlı olurdu. Ama - RoR'da böyle yapılır, öyle görünüyor.



0

Yanıt biçiminiz "Biçim" dir. Örneğin, json veya html olabilir. Ziyaretçinizin alacağı çıktının formatıdır.


0

Dikkat etmeniz gereken bir şey daha var - MIME.

Bir MIME türü kullanmanız gerekiyorsa ve varsayılan olarak desteklenmiyorsa, kendi işleyicilerinizi config / initializers / mime_types.rb dosyasına kaydedebilirsiniz:

Mime::Type.register "text/markdown", :markdown

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.