ruby-on-rails Rails:respond_to块是如何工作的?

vwkv1x7d  于 2023-11-20  发布在  Ruby
关注(0)|答案(9)|浏览(201)

我正在浏览Getting Started with Rails指南,并与第6.7节混淆。在生成一个scaffold后,我在控制器中发现以下自动生成的块:

def index
  @posts = Post.all

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

字符串
我想了解respond_to块实际上是如何工作的。什么类型的变量是format?.html和.json方法是format对象吗?
第一个月
并没有回答问题。

falq053o

falq053o1#

我是Ruby新手,也被同样的代码卡住了。我被卡住的部分比我在这里找到的一些答案更基本。这可能会帮助到别人,也可能不会。

  • respond_to是父类ActionController上的一个方法。
  • 它接受一个块,就像一个委托。块从doend|format|作为块的参数。
  • respond_to执行你的代码块,将Responder传递给format参数。

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

  • Responder不包含.html.json的方法,但我们无论如何都要调用这些方法!这部分让我陷入了一个循环。
  • Ruby有一个名为method_missing的特性。如果你调用一个不存在的方法(比如jsonhtml),Ruby会调用method_missing方法。

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

  • Responder类使用它的method_missing作为一种注册。当我们调用'json'时,我们告诉它通过序列化为json来响应扩展名为.json的请求。我们需要不带参数地调用html,告诉它以默认方式(使用约定和视图)处理.html请求。

它可以这样写(使用类似JS的伪代码):

// 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)

字符串
这一部分把我搞糊涂了。我仍然觉得它不直观。Ruby似乎经常使用这种技术。整个类(responder)成为方法实现。为了利用method_missing,我们需要类的一个示例,所以我们不得不传递一个回调函数,让它们把类方法对象传递到回调函数中。对于一个用类C语言编程20多年的人来说,这对我来说是非常落后和不直观的。不是说它不好!但这是很多有这种背景的人需要弄清楚的事情,我想这可能是OP所追求的。
注意,在RoR 4.2中,respond_to被提取到responders gem中。

yacmzcpb

yacmzcpb2#

这是一个Ruby代码块,它利用了Rails的帮助方法。如果你还不熟悉块,你会在Ruby中看到很多块。
respond_to是一个Rails辅助方法,它被附加到Controller类(或者更确切地说,它的超类)。它引用将被发送到View(将被发送到浏览器)的响应。
你的例子中的块是格式化数据-通过在块中传递一个'format'参数-每当浏览器请求html或json数据时,将从控制器发送到视图。
如果你在本地机器上,并且你已经设置了Post scaffold,你可以转到http://localhost:3000/posts,你会看到你所有的帖子都是html格式的。但是,如果你输入:http://localhost:3000/posts.json,那么你会看到你所有的帖子都是从服务器发送的JSON对象。
这对于制作需要在服务器上来回传递json的JavaScript应用程序非常方便。如果你愿意,你可以很容易地在你的rails后端创建一个json API,并且只传递一个视图--比如Post控制器的index视图。然后你可以使用JavaScript库,比如Jquery或者Backbone(或者两者都有)操作数据并创建自己的界面。这些被称为异步UI,它们非常流行(Gmail就是其中之一)。它们非常快,给予最终用户更像桌面的Web体验。当然,这只是格式化数据的一个优点。
Rails 3的写法是:

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, :json放在类的顶部,您可以声明您希望控制器发送到视图的所有格式。
然后,在控制器方法中,您所要做的就是respond_with(@whatever_object_you_have)
它只是比Rails自动生成的代码更简化一点。

如果你想知道这件事的内幕

据我所知,Rails会对对象进行内省,以确定实际的格式。“format”变量的值就是基于这种内省。Rails可以用一点点信息做很多事情。你会惊讶于一个简单的@post或:post会走多远。
例如,如果我有一个_user.html.erb部分文件,它看起来像这样:

_user.html.erb

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


然后,在我的索引视图中,这一点会让Rails知道它需要找到'users' partial,并遍历所有'users'对象:

index.html.erb

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


会让Rails知道它需要找到'user' partial并遍历所有'users'对象:
你可能会发现这篇博客文章很有用:http://archives.ryandaigle.com/articles/2009/8/6/what-s-new-in-edge-rails-cleaner-restful-controllers-w-respond_with
你也可以阅读源代码:https://github.com/rails/rails

3phpmpom

3phpmpom3#

据我所知,respond_to是一个附加到Rails Controller的方法,所以你可以在每个控制器中使用它,因为它们都继承自Rails Controller。下面是Rails的respond_to方法:

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

字符串
你传递给它一个block,就像我在这里展示的那样:

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

**| 格式|**part是块所期望的参数,所以在respond_to方法中我们可以使用它。如何使用?

好吧,如果你注意到我们在respond_to方法中传递了带前缀&的块,我们这样做是为了将该块视为Proc。由于参数有“.xml”,“.html”,我们可以将其用作要调用的方法。
我们在respond_to类中基本上做的是调用方法“.html,.xml,.json”到Responder类的示例。

lmvvr0a8

lmvvr0a84#

我想了解respond_to块实际上是如何工作的。什么类型的变量是format?.html和.json方法是format对象的方法吗?
为了理解format是什么,您可以首先查看respond_to的源代码,但很快您就会发现真正需要查看的是retrieve_response_from_mimes的代码。
从这里,你会看到传递给respond_to的块(在你的代码中),实际上是用Collector的一个示例(在块中被引用为format)来调用和传递的。Collector基本上是基于mime types rails所知道的来生成方法的(我相信在Rails启动时)。
所以,是的,.html.json是在Collector(又名format)类上定义的(在运行时)方法。

xzlaal3s

xzlaal3s5#

响应者注册背后的元编程(请参阅Parched Squid的回答)也允许您做这样的漂亮事情:

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

字符串
当你访问/posts. csv时,csv行会在每个post上调用to_csv。这使得从你的rails站点导出数据为CSV(或任何其他格式)变得很容易。
js行将导致JavaScript文件/posts. js(或/posts.js.coffee)被渲染/执行。我发现这是一种使用jQuery UI弹出窗口创建Ajax启用站点的轻量级方法。

6yjfywim

6yjfywim6#

这是一个有点过时,由瑞安比格做了一个伟大的工作解释这一点在这里:
http://ryanbigg.com/2009/04/how-rails-works-2-mime-types-respond_to
事实上,它可能比您所期望的要详细一些,因为在幕后有很多工作要做,包括需要了解MIME类型是如何加载的。

50pmv0ei

50pmv0ei7#

什么类型的变量是format?
在java POV中,format是匿名界面的实作。此界面有一个方法,其名称为每个mime类型。当您叫用其中一个方法(传递区块给它)时,如果Rails认为使用者需要该内容类型,则会叫用您的区块。
当然,这个匿名的粘合对象实际上并不实现一个接口--它动态地捕获方法调用,并判断它是否是它所知道的mime类型的名称。
就我个人而言,我认为这看起来很奇怪:你传入的块是 executed。对我来说传入一个格式标签和块的散列会更有意义。但是--这似乎是RoR中的做法。

q8l4jmvw

q8l4jmvw8#

“格式”是您的响应类型。例如,可以是json或html。它是您的访问者将收到的输出格式。

7nbnzgx9

7nbnzgx99#

还有一件事你应该知道- MIME。
如果你需要使用MIME类型,而默认情况下它不受支持,你可以在config/initializers/mime_types.rb中注册自己的处理程序:
第一个月

相关问题