Je suis en train de parcourir le guide Mise en route avec Rails et je me suis confondu avec la section 6.7. Après avoir généré un échafaudage, je trouve le bloc généré automatiquement suivant dans mon contrôleur:
def index
@posts = Post.all
respond_to do |format|
format.html # index.html.erb
format.json { render :json => @posts }
end
end
Je voudrais comprendre comment fonctionne réellement le bloc respond_to. Quel type de variable est format? Les méthodes .html et .json sont-elles de l'objet format? La documentation pour
ActionController::MimeResponds::ClassMethods::respond_to
ne répond pas à la question.
ruby-on-rails
Cole
la source
la source
format.html
- pas d'argument), il utilisera des conventions (basées sur l'URL et le verbe HTTP) pour choisir une vue (qui devrait être HTML). Le répondeur (format) est chargé ici de rendre les URL se terminant par .json en sérialisant en json, au lieu d'utiliser des vues et des conventions.Réponses:
Je suis nouveau sur Ruby et je suis resté bloqué sur ce même code. Les parties sur lesquelles j'ai raccroché étaient un peu plus fondamentales que certaines des réponses que j'ai trouvées ici. Cela peut ou non aider quelqu'un.
respond_to
est une méthode sur la superclasseActionController
.do
jusqu'àend
, avec|format|
comme argument pour le bloc.format
argument.http://api.rubyonrails.org/v4.1/classes/ActionController/Responder.html
Responder
ne contient PAS de méthode pour.html
ou.json
, mais nous appelons ces méthodes quand même! Cette partie m'a jeté pour une boucle.method_missing
. Si vous appelez une méthode qui n'existe pas (commejson
ouhtml
), Ruby appelle lamethod_missing
méthode à la place.http://ruby-metaprogramming.rubylearning.com/html/ruby_metaprogramming_2.html
Responder
classe utilise sonmethod_missing
comme une sorte d'enregistrement. Lorsque nous appelons «json», nous lui disons de répondre aux demandes avec l'extension .json en sérialisant vers json. Nous devons appelerhtml
sans argument pour lui dire de gérer les requêtes .html par défaut (en utilisant les conventions et les vues).Il pourrait être écrit comme ceci (en utilisant un pseudocode de type JS):
Cette partie a confondu le diable hors de moi. Je trouve toujours cela peu intuitif. Ruby semble utiliser un peu cette technique. La classe entière (
responder
) devient l'implémentation de la méthode. Afin de tirer partimethod_missing
, nous avons besoin d'une instance de la classe, nous sommes donc obligés de passer un rappel dans lequel ils passent l'objet de type méthode. Pour quelqu'un qui a codé en langage C depuis 20 ans, c'est très arriéré et peu intuitif pour moi. Pas que ce soit mauvais! Mais c'est quelque chose que beaucoup de gens avec ce genre d'expérience ont besoin de trouver la tête, et je pense que c'est peut-être ce que le PO recherchait.ps noter que dans RoR 4.2 a
respond_to
été extrait dans la gemme répondeurs .la source
method_missing
, étant donné que vous pouvez lui passer des arguments et un bloc!respond_to
les contrôleurs, sans la gemme des répondeurs présente dans le Gemfile. Peut-être que le fait d'respond_to
être extrait dans la gemme du répondant a été changé?Il s'agit d'un bloc de code Ruby qui tire parti d'une méthode d'assistance Rails. Si vous n'êtes pas encore familier avec les blocs, vous les verrez beaucoup dans Ruby.
respond_to
est une méthode d'assistance Rails attachée à la classe Controller (ou plutôt à sa super classe). Il fait référence à la réponse qui sera envoyée à la vue (qui va au navigateur).Le bloc dans votre exemple est le formatage des données - en passant un paramètre "format" dans le bloc - à envoyer du contrôleur à la vue chaque fois qu'un navigateur fait une demande de données html ou json.
Si vous êtes sur votre ordinateur local et que votre échafaudage Post est configuré, vous pouvez aller à
http://localhost:3000/posts
et vous verrez tous vos messages au format html. Mais, si vous tapez ceci:,http://localhost:3000/posts.json
alors vous verrez tous vos messages dans un objet json envoyé par le serveur.C'est très pratique pour créer des applications lourdes javascript qui doivent passer json dans les deux sens depuis le serveur. Si vous le souhaitez, vous pouvez facilement créer une API json sur le back-end de vos rails et ne transmettre qu'une seule vue, comme la vue d'index de votre contrôleur Post. Ensuite, vous pouvez utiliser une bibliothèque javascript comme Jquery ou Backbone (ou les deux) pour manipuler les données et créer votre propre interface. On les appelle des interfaces utilisateur asynchrones et elles deviennent très populaires (Gmail en est un). Ils sont très rapides et offrent à l'utilisateur final une expérience plus semblable à celle d'un ordinateur de bureau sur le Web. Bien sûr, ce n'est qu'un avantage du formatage de vos données.
La façon d'écrire ceci de Rails 3 serait la suivante:
En plaçant
respond_to :html, :xml, :json
en haut de la classe, vous pouvez déclarer tous les formats que vous souhaitez que votre contrôleur envoie à vos vues.Ensuite, dans la méthode du contrôleur, tout ce que vous avez à faire est de répondre_ avec (@wthing_object_you_have)
Il simplifie simplement votre code un peu plus que ce que Rails génère automatiquement.
Si vous voulez en savoir plus sur le fonctionnement interne de cette ...
D'après ce que je comprends, Rails introspecte les objets pour déterminer quel sera le format réel. La valeur des variables «format» est basée sur cette introspection. Les rails peuvent faire beaucoup de choses avec un peu d'informations. Vous seriez surpris de voir jusqu'où irait un simple @post ou: post.
Par exemple, si j'avais un fichier partiel _user.html.erb qui ressemblait à ceci:
_user.html.erb
Ensuite, cela seul dans ma vue d'index permettrait à Rails de savoir qu'il devait trouver le partiel "utilisateurs" et parcourir tous les objets "utilisateurs":
index.html.erb
permettrait à Rails de savoir qu'il avait besoin de trouver le partiel «utilisateur» et de parcourir tous les objets «utilisateurs»:
Vous pouvez trouver cet article de blog utile: http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with
Vous pouvez également consulter la source: https://github.com/rails/rails
la source
respond_to
etrespond_with
introduit? J'utilise les rails 2.3.5 et je reçoisNoMethodError (undefined method respond_to)
D'après ce que je sais, respond_to est une méthode attachée à l'ActionController, vous pouvez donc l'utiliser dans chaque contrôleur, car tous héritent de l'ActionController. Voici la méthode respond_to de Rails:
Vous passez un bloc , comme je le montre ici:
Le | format | partie est l'argument que le bloc attend, donc à l'intérieur de la méthode respond_to nous pouvons l'utiliser. Comment?
Eh bien, si vous remarquez que nous passons le bloc avec un préfixe & dans la méthode respond_to, et nous le faisons pour traiter ce bloc comme un Proc. Puisque l'argument a le ".xml", ".html", nous pouvons l'utiliser comme méthode à appeler.
Ce que nous faisons essentiellement dans la classe respond_to, ce sont des méthodes d'appel ".html, .xml, .json" à une instance d'une classe Responder.
la source
Afin de comprendre ce qui
format
est, vous pouvez d'abord regarder la sourcerespond_to
, mais rapidement vous constaterez que ce que vous devez vraiment regarder est le code de retrieve_response_from_mimes .À partir d'ici, vous verrez que le bloc qui a été passé à
respond_to
(dans votre code) est en fait appelé et passé avec une instance de Collector (qui dans le bloc est référencée commeformat
). Collector génère essentiellement des méthodes (je pense au démarrage de Rails) basées sur ce que les types MIME connaissent.Donc, oui, les méthodes
.html
et.json
sont définies (au moment de l'exécution) sur laformat
classe Collector (aka ).la source
La méta-programmation derrière l'enregistrement du répondeur (voir la réponse de Parched Squid) vous permet également de faire des trucs astucieux comme ceci:
La ligne csv provoquera l'appel de to_csv sur chaque publication lorsque vous visitez /posts.csv. Cela facilite l'exportation de données au format CSV (ou tout autre format) à partir de votre site de rails.
La ligne js entraînera le rendu / l'exécution d'un fichier javascript /posts.js (ou /posts.js.coffee). J'ai trouvé que c'était un moyen léger de créer un site compatible Ajax à l'aide de fenêtres contextuelles jQuery UI.
la source
A partir d'un POV java, le format est une implémentation d'une interface anonyme. Cette interface a une méthode nommée pour chaque type MIME. Lorsque vous appelez l'une de ces méthodes (en lui passant un bloc), si rails estime que l'utilisateur souhaite ce type de contenu, il invoquera votre bloc.
La torsion, bien sûr, est que cet objet de collage anonyme n'implémente pas réellement d'interface - il intercepte les appels de méthode de manière dynamique et détermine s'il s'agit du nom d'un type MIME qu'il connaît.
Personnellement, je pense que ça a l'air bizarre: le bloc que vous passez est exécuté . Il serait plus logique pour moi de passer un hachage d'étiquettes de format et de blocs. Mais - c'est comme ça que ça se fait dans RoR, semble-t-il.
la source
C'est un peu dépassé, par Ryan Bigg fait un excellent travail en expliquant cela ici:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to
En fait, cela pourrait être un peu plus détaillé que vous ne le cherchiez. En fait, il se passe beaucoup de choses en arrière-plan, y compris un besoin de comprendre comment les types MIME sont chargés.
la source
"Format" est votre type de réponse. Peut être json ou html, par exemple. C'est le format de la sortie que votre visiteur recevra.
la source
Il y a encore une chose que vous devez savoir - MIME.
Si vous devez utiliser un type MIME et qu'il n'est pas pris en charge par défaut, vous pouvez enregistrer vos propres gestionnaires dans config / initializers / mime_types.rb:
Mime::Type.register "text/markdown", :markdown
la source