Estou examinando o guia Introdução ao Rails e fiquei confuso com a seção 6.7. Depois de gerar um andaime, encontro o seguinte bloco gerado automaticamente no meu controlador:
def index
@posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @posts }
end
end
Eu gostaria de entender como o bloco respond_to realmente funciona. Que tipo de variável é formato? Os métodos .html e .json do objeto de formato? A documentação para
ActionController::MimeResponds::ClassMethods::respond_to
não responde a pergunta.
ruby-on-rails
Cole
fonte
fonte
format.html
- sem argumento), ele usará convenções (com base no URL e no verbo HTTP) para escolher uma exibição (que se espera seja HTML). O respondedor (formato) é instruído aqui para renderizar URLs que terminam em .json serializando para json, em vez de usar visualizações e convenções.Respostas:
Eu sou novo no Ruby e fiquei preso nesse mesmo código. As partes nas quais eu desliguei foram um pouco mais fundamentais do que algumas das respostas que encontrei aqui. Isso pode ou não ajudar alguém.
respond_to
é um método na superclasseActionController
.do
atéend
, com|format|
como argumento para o bloco.format
argumento.http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html
Responder
não contém um método para.html
ou.json
, mas nós chamamos esses métodos de qualquer maneira! Esta parte me jogou para um loop.method_missing
. Se você chamar um método que não existe (comojson
ouhtml
), Ruby chama omethod_missing
método.http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html
Responder
classe usa issomethod_missing
como um tipo de registro. Quando chamamos 'json', dizemos para responder a solicitações com a extensão .json serializando para json. Precisamos chamarhtml
sem argumentos para instruí-lo a lidar com solicitações .html da maneira padrão (usando convenções e visualizações).Poderia ser escrito assim (usando pseudocódigo do tipo JS):
Esta parte me confundiu. Ainda acho isso pouco intuitivo. Ruby parece usar bastante essa técnica. A classe inteira (
responder
) se torna a implementação do método. Para alavancarmethod_missing
, precisamos de uma instância da classe, por isso somos obrigados a passar um retorno de chamada para o qual eles passam o objeto semelhante ao método. Para alguém que codifica em idiomas C há 20 anos, isso é muito retroativo e pouco intuitivo para mim. Não que isso seja ruim! Mas é algo que muitas pessoas com esse tipo de experiência precisam entender, e acho que pode ser o que o OP estava procurando.ps note que no RoR 4.2
respond_to
foi extraído na gema dos respondedores .fonte
method_missing
, considerando que você pode passar argumentos e um bloco!respond_to
nos controladores, sem a gema dos respondedores presente no Gemfile. Talvez o pouco sobrerespond_to
ser extraído na gema de resposta tenha sido alterado?Este é um bloco de código Ruby que tira proveito de um método auxiliar do Rails. Se você ainda não conhece os blocos, os verá bastante em Ruby.
respond_to
é um método auxiliar do Rails anexado à classe Controller (ou melhor, sua superclasse). Ele está referenciando a resposta que será enviada para o View (que está indo para o navegador).O bloco no seu exemplo está formatando dados - passando um paramater 'format' no bloco - a ser enviado do controlador para a visualização sempre que um navegador faz uma solicitação de dados html ou json.
Se você estiver em sua máquina local e tiver seu andaime Post configurado, poderá acessar
http://localhost:3000/posts
e verá todas as suas postagens no formato html. Mas, se você digitar istohttp://localhost:3000/posts.json
:, verá todas as suas postagens em um objeto json enviado do servidor.Isso é muito útil para criar aplicativos pesados em javascript que precisam passar o json para frente e para trás a partir do servidor. Se você quisesse, poderia criar facilmente uma json api no seu back-end de trilhos e passar apenas uma visualização - como a visualização de índice do seu controlador Post. Em seguida, você pode usar uma biblioteca javascript como Jquery ou Backbone (ou ambos) para manipular dados e criar sua própria interface. Essas são chamadas de interfaces de usuário assíncronas e estão se tornando realmente populares (o Gmail é um). Eles são muito rápidos e proporcionam ao usuário final uma experiência mais semelhante à da área de trabalho na web. Obviamente, essa é apenas uma vantagem de formatar seus dados.
O jeito do Rails 3 de escrever isso seria o seguinte:
Ao colocar
respond_to :html, :xml, :json
no topo da classe, você pode declarar todos os formatos que deseja que seu controlador envie para seus pontos de vista.Em seguida, no método do controlador, tudo o que você precisa fazer é responder_com (@whatever_object_you_have)
Apenas simplifica seu código um pouco mais do que o que o Rails gera automaticamente.
Se você quer saber sobre o funcionamento interno deste ...
Pelo que entendi, o Rails introspecta os objetos para determinar qual será o formato real. O valor das variáveis 'format' é baseado nessa introspecção. O Rails pode fazer muito com um pouco de informação. Você ficaria surpreso com o quão longe um simples @post ou: post vai.
Por exemplo, se eu tivesse um arquivo parcial _user.html.erb parecido com este:
_user.html.erb
Então, isso sozinho na minha exibição de índice informaria ao Rails que ele precisava encontrar os 'usuários' parciais e iterar por todos os objetos 'usuários':
index.html.erb
permitiria ao Rails saber que precisava encontrar o 'usuário' parcial e iterar através de todos os objetos 'usuários':
Você pode achar útil este post do blog: http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with
Você também pode ler a fonte: https://github.com/rails/rails
fonte
respond_to
erespond_with
introduzido? Estou usando rails 2.3.5 e estou recebendoNoMethodError (undefined method respond_to)
Pelo que sei, respon_to é um método anexado ao ActionController, para que você possa usá-lo em todos os controladores, porque todos eles herdam do ActionController. Aqui está o método respond_to do Rails:
Você está passando um bloco , como eu mostro aqui:
O formato | parte é o argumento que o bloco está esperando; portanto, dentro do método respond_to, podemos usá-lo. Quão?
Bem, se você perceber que passamos o bloco com um prefixo & no método respond_to, e fazemos isso para tratá-lo como um Proc. Como o argumento tem o ".xml", ".html", podemos usá-lo como métodos a serem chamados.
O que basicamente fazemos na classe respond_to é chamar métodos ".html, .xml, .json" para uma instância de uma classe Respondente.
fonte
Para entender o que
format
é, você pode primeiro procurar a fonterespond_to
, mas rapidamente descobrirá que realmente precisa ver o código de retrieve_response_from_mimes .A partir daqui, você verá que o bloco que foi passado para
respond_to
(no seu código) é realmente chamado e passado com uma instância do Collector (que dentro do bloco é referenciada comoformat
). O Collector basicamente gera métodos (acredito na inicialização do Rails) com base no que os tipos mime conhecem o rails.Portanto, sim, os métodos
.html
e.json
são definidos (em tempo de execução) naformat
classe Collector (aka ).fonte
A metaprogramação por trás do registro do respondedor (consulte a resposta do Parched Squid) também permite que você faça coisas bacanas como esta:
A linha csv fará com que to_csv seja chamado em cada postagem quando você visitar /posts.csv. Isso facilita a exportação de dados como CSV (ou qualquer outro formato) do seu site de trilhos.
A linha js fará com que um arquivo javascript /posts.js (ou /posts.js.coffee) seja renderizado / executado. Descobri que essa é uma maneira leve de criar um site habilitado para Ajax usando pop-ups da UI do jQuery.
fonte
De um POV java, o formato é uma implementação de uma interface anônima. Essa interface possui um método nomeado para cada tipo MIME. Quando você invoca um desses métodos (passando um bloco para ele), se o Rails achar que o usuário deseja esse tipo de conteúdo, ele invocará seu bloco.
A reviravolta, é claro, é que esse objeto de cola anônimo não implementa realmente uma interface - ele captura as chamadas do método dinamicamente e funciona se é o nome de um tipo mime que ele conhece.
Pessoalmente, acho estranho: o bloco que você passa é executado . Faria mais sentido passar um hash de rótulos e blocos de formato. Mas - é assim que é feito no RoR, ao que parece.
fonte
Isso está um pouco desatualizado, por Ryan Bigg faz um ótimo trabalho explicando isso aqui:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to
De fato, pode ser um pouco mais detalhado do que você estava procurando. Acontece que há muita coisa acontecendo nos bastidores, incluindo a necessidade de entender como os tipos MIME são carregados.
fonte
"Formato" é o seu tipo de resposta. Pode ser json ou html, por exemplo. É o formato da saída que seu visitante receberá.
fonte
Há mais uma coisa que você deve estar ciente - MIME.
Se você precisar usar um tipo MIME e não for suportado por padrão, poderá registrar seus próprios manipuladores em config / initializers / mime_types.rb:
Mime::Type.register "text/markdown", :markdown
fonte