1

我现在已经使用 Ruby on Rails 创建了一些应用程序,但是有一些概念我还没有完全理解。

其中之一是“路由”过程如何工作?我的意思是,用户输入一个 URL 字符串,Rails 提供相关资产以响应 URL。

这是我认为正在发生的事情:

  1. 用户使用浏览器浏览服务器:

    http://0.0.0.0:3000
    
  2. 然后他们在 URL 前面加上一个字符串:

    http://0.0.0.0:3000/entries/view_all
    
  3. Rails 的 'routes.rb' 文件通过指令指定字符串应该与什么实际相关:

    match "/entries/view_all" => "entries#view_all"
    
  4. 上述指令表示,当字符串“/entries/view_all”附加到 URL 时,执行view_all在文件 'entries_controller.rb' 中找到的方法。

  5. view_all方法执行:

    def view_all
      @entries = Entry.all(:order => 'created_at DESC')
    end
    

    它将表 'Entry' 中的所有条目@entries按降序分配给常量。

  6. 然后,Rails神奇地知道为用户提供“view_all.html.erb”。

  7. each'view_all.html.erb' 内的循环显示来自 'Entry' 表的相关信息:

    <% @entries.each do |entry| %>
    <h1><%= entry.title %></h1> 
    <p><%= entry.content %></p>
    <p><em>Posted at <%= entry.created_at %></em></p>
    <% end %>
    

我的问题如下:

  1. 我对事物运作方式的概念有多错误?
  2. 在上面的第 3 步中,Rails 是如何知道view_all在 'entries_controller.rb' 中找到的方法的?该指令是entries#view_all,不是entries#view_all。Rails 是否会自动匹配“控制器”目录中控制器文件名的开头,并忽略“_controller.rb”?
  3. 在上面的第 6 步中,Rails 是如何“神奇地”知道服务于“view_all.html.erb”视图的?它是否类似于我认为它在问题 #2 中的工作方式?Rails 是否将文件名的“view_all”部分与“entries_controller.rb”中的方法名匹配?
  4. object/constant@entries及其所有方法是如何从“entries_controller.rb”“传递”到“view_all.html.erb”的?
4

3 回答 3

3

针对 (2) 和 (3) - Rails 强调约定优于配置,这导致路由器、控制器和视图模板之间看似神奇的耦合。例如,路由器知道它entries指的是一个EntriesController类,因为在 中有一行ActionDispatch::Routing::RouteSet

def controller_reference(controller_param)
  controller_name = "#{controller_param.camelize}Controller"
  ...

这不是魔术——“控制器”这个词是硬编码的。鉴于您的输入,这正是 Rails 编程所期望的。到处都是这样,当你开始使用它时,理解它可能有点令人生畏(看看 Ember.js,了解更多像这样令人生畏的魔法)。

针对 (4):Rails 将您的各个实例变量复制到一个ActionView实例中。社区中关于它是否真的应该这样做存在相当大的争论,但现在它是这样工作的,在编写控制器操作时应该牢记这一点。您不希望在复制视图中不需要的大量或臃肿对象时产生大量开销。

于 2013-05-08T23:42:12.607 回答
2

事实上,你明白了。都是名副其实的。Entry模型与entries_controllerentries视图匹配的模型匹配。特定视图的名称与控制器操作相关。

@entries是一个实例变量(称为,例如它是整个模型的一个实例),任何以 . 开头的变量也是如此@。控制器中的那些变量是相应视图可用的变量。

一个巧妙的技巧是_enrty局部。

_entry.html.erb

<h1><%= entry.title %></h1> 
<p><%= entry.content %></p>
<p><em>Posted at <%= entry.created_at %></em></p>

然后在你想调用的地方index(你view_all通常被标记为index),或者那里的一部分,你可以<%= render @entries %>

但是,是的,rails 的许多魔力在于匹配匹配的命名约定。有一些方法可以解决这个问题,因为一切都是可定制的,但这就是总结。干杯!

于 2013-05-08T23:41:54.523 回答
1

1)我对事物运作方式的概念有多错误?

这是思考流程如何运作的好方法

2) 在步骤 (3) 中,rails 是如何知道在 'entries_controller.rb' 中找到了 'view_all' 方法的?该指令是“entries#view_all”,而不是“entries#view_all”。rails 是否自动匹配“控制器”目录中控制器文件名的开头,并忽略“_controller.rb”?

Rails 遵守一个称为“约定优于配置”的指令,这意味着 Rails 会以某种方式运行,只要你按照它期望的方式给出指令。因此,在上面的查询中,因为您指定了控制器的“条目”部分,它知道要在“条目控制器”中查找“视图全部”操作

3) 在步骤 (6) 中,rails 如何“神奇地”知道为“view_all.html.erb”视图提供服务?它是否类似于我认为它在问题 2 中的工作方式?rails 是否将文件名的“view_all”部分与“entries_controller.rb”中的方法名称匹配?

约定优于配置又名“魔术”。一旦 Rails 执行了一个动作,它就会根据你的请求寻找匹配的模板来执行。如果您向 json 页面发出请求(例如,通过更改请求标头),它将查找 view.json.erb。如果您遗漏了该模板,它将引发错误,除非在操作结束时您使用渲染调用告诉它执行其他操作

4) 对象/常量“@entries”及其所有方法是如何从“entries_controller.rb”“传递”到“view_all.html.erb”的?

它只是:D,或者您是否要求查看负责该问题的 Rails 源代码?

ActionView (Views) 和 ActionController(Controllers) 都继承自 Actionpack,所以我想在两者之间共享变量并不难。

于 2013-05-08T23:49:13.760 回答