我对RoR场景有点新鲜......我现在才开始连接点。在你的发展生涯中,你们能给我一些更明确的指导和指导吗?
我无法理解路由,控制器和视图之间的相关性(以及它们如何相互连接)。
所以,我的控制器包含index
,show
,new
,create
,destroy
方法。和相应的
GET /entries(.:format) entries#index
POST /entries(.:format) entries#create
GET /entries/new(.:format) entries#new
GET /entries/:id/edit(.:format) entries#edit
GET /entries/:id(.:format) entries#show
PUT /entries/:id(.:format) entries#update
DELETE /entries/:id(.:format) entries#destroy
例如,如果我添加新方法vote_up
或vote_down
以及具有匹配操作名称的视图,它怎么会起作用。
1)添加新操作并将其连接到视图的正确方法是什么? 2) Bonus 使这些方法与ajax兼容的正确方法是什么(用ajax渲染部分)?如果用户没有启用js会发生什么?
我可以根据我得到的答案扩展/发展这个问题。
我已经厌倦了搜索自定义动作路线之类的东西来躲避我的应用程序。它正在流失和糟糕的形式,我终于达到理解语言的水平 - 我已经100%自学了...所以请尽量理解你是否可以为一个年轻的padawan。
答案 0 :(得分:6)
以下是从头开始思考的方法:
1)您的应用所做的唯一事情是响应HTTP请求。
最典型的请求是:
GET - 用户在浏览器的网址栏中输入内容并点击输入。
POST - 用户提交表单。
还有其他类型的HTTP请求,最重要的是PUT,PATCH和DELETE。 Rails遵循REST模式,这意味着它为这些HTTP谓词指定了特定的含义。
2)当任何请求进入您的应用时,必须将其路由到控制器操作。
您的routes.rb
文件是Rails路由器(ActionDispatch)的一组说明,告诉路由器将请求发送到何处。 "标准" rails资源是一个快捷方式,如下所示:
resources :things
这意味着以下内容:
GET /things => things#index
GET /things/:id => things#show
GET /things/new => things#new
GET /things/edit/:id => things#edit
POST /things => things#create
PUT /things/:id => things#update
DELETE /things/:id => things#destroy
这些被认为是标准的RESTful操作 - 您的resources :things
声明没有设置任何其他操作。因此,如果您希望控制器执行其他非标准操作,则必须手动添加它们。
如果要对特定记录执行操作,最好的方法是使用:
resources :things do
member do
get 'vote_up'
end
end
这告诉路由器,如果有人向/things/123/vote_up
发出GET请求,则应该触发ThingsController
vote_up
操作。
所有这些都在Rails Guide中详细阐述,你应该阅读整篇文章。
3)您的控制人员的工作是发送对请求的回复。
通常这意味着从数据库加载记录并渲染该记录的视图。
每个控制器操作都通过将响应发送回传入请求而结束。此响应可以是render
调用 - 这意味着以某种格式发回一些数据 - 或redirect
调用 - 这基本上会为您发出新请求,因此您可以获得该其他请求的响应
在Rails中,重定向实际上是将请求发送到不同的控制器操作。
渲染调用将数据作为对请求的响应发送。
当您致电render :new
时,这是render :template => :new
的快捷方式,它会加载app/views/things/new.html.erb
(或其他)模板,从控制器发送数据(通常是您的实例变量)并使用模板语言(erb,haml等)对此进行评估。这会生成一大串HTML,然后控制器将其传递给浏览器。
想亲眼看看这是什么?尝试使用render :text => 'Hello World'
或甚至:
render :inline => '<!DOCTYPE html><head><title>Inline Wow!</title></head><body>Mind blown.</body></html>'
看看会发生什么。
在回复(渲染)时,您可以发送&#34;正常&#34; HTML模板,其中包含整页信息(头部,正文等),或者是Ajax使用的部分信息。您还可以发送原始数据,如JSON或XML。它实际上只是文本,并且取决于该文本的内容(以及随其附带的HTTP标头),浏览器,脚本或客户端应用程序会相应地处理它。
再次,请参阅Rails Guide。
4)当浏览器发出请求时,您可能希望发回HTML。如果请求是由Ajax发出的,那么您可能希望发送回JSON。
对于像vote_up
这样的自定义操作,您可能根本不想显示模板,只是重定向。所以,你可能会有这样的事情:
ThingsController < ApplicationController
def vote_up
@thing = Thing.find(params[:id])
@thing.vote_up
redirect_to @thing
end
end
现在,路由器的一个好处是它将为您提供URL帮助程序。如果你已经创建了如前所示的路线和动作,那就在你的&#34;展示事物&#34;页面你可以有这样的URL:
link_to 'Vote up this thing!', vote_up_thing_path(@thing)
这会创建一个指向things/123/vote_up
的链接,如果有人点击它,它会在vote_up
上的ThingsController
操作中运行代码,然后重定向回显示内容图。
5)您的模板使用链接和表单向控制器发送消息。链接发出GET请求,表单发出POST请求。
如果您想开始使用AJAX请求,那很好。在这种情况下,您只需要在Javascript中发出请求,并处理响应。因此,例如,您可以在模板中添加这样的内容:
= link_to 'Vote up this thing', vote_up_thing_path(@thing), :id => 'vote-up-button'
然后在Javascript(使用jQuery)中你可以有这样的函数:
$(function(){
$('a#vote-up-button').click( function(event){
event.preventDefault();
$.ajax({
url: this.attr('href'),
type: 'GET',
success: function(){...},
error: function(){...}
});
});
});
在这种情况下,jQuery Ajax方法只是发出一个get请求,然后根据它得到的响应运行一个回调函数。
6)您的控制器/路由的结构不会影响您可以提出的请求类型,只会影响哪种操作会响应什么URL上的HTTP方法。
你做什么INSIDE你的控制器动作决定你是否准备好响应javascript或html请求等。
虽然rails肯定能够在单个控制器动作中处理多种请求格式,但是使用respond_to
块,作为一个实际问题,我发现当你选择路由只响应一个时,事情会更顺利格式或其他。
IE:我会让你的正常页面加载请求(索引,显示,新建,编辑)只是HTML请求,然后我会让你想要添加的任何其他AJAX操作只是Javascript - 即。他们用JSON而不是HTML回应。当然,你不必这样做,但如果你这样做,你的生活会更容易。
我希望这能让您更清楚地了解应用中发生的情况。欢迎来到Rails,您加入了一个伟大的社区!
答案 1 :(得分:2)
欢迎来到ROR世界。 :)
路由,控制器和视图协同工作,将HTTP请求转换为某种响应(无论是HTML,JSON还是XML)。每个人都会攻击不同的问题。
从最后开始,views
是rails世界中的模板,通常为ERB。 ERB只是一个模板系统,其他也可以使用,如haml。他们的工作是获取控制器提供给他们的一些数据并生成格式化输出,通常也是HTML,JSON或XML。
但是,您如何知道为特定请求呈现哪个视图?如何将数据输入到您的视图中,以便它可以完成您需要的所有花哨的动态内容?这是控制器进来的地方。Controllers
是ruby类,其工作是检查解析的 HTTP请求和任何相关参数,从数据库(或任何地方)获取数据,然后传递数据到视图。控制器通常具有若干不同的方法,每个方法对应于不同的任务(例如,创建,显示,更新等)。
最后,Routes
是用于解析HTTP请求并将解析的HTTP请求分派给特定控制器方法的DSL。它们是Rails用于将URL路由到方法的粘合剂,因此名称为routes
。
关于您的具体问题:
1)要创建新操作,您必须添加路径,控制器方法和视图。因此,例如,如果您想获得条目的计数,您可以添加如下路线:
get '/entries/count' => "entries#count"
这告诉ROR在收到该URL时调用count
控制器中的entries
方法。在这种情况下,您的控制器方法将是简单的:
def count
@cnt = Entries.count
end
然后,你会在app/views/entries/count.html.erb
中创建一个类似于:
<p>Count: <%= @cnt %></p>
2)Ajax兼容代码实际上只是一种问“如果请求的请求格式是JSON会怎样?”的方法。为此,您需要使用respond_to
方法。在某种程度上,respond_to是指定不同视图以处理请求格式的正式方式。要继续上面的示例,您可以执行以下操作:
def count
@cnt = Entries.count
respond_to do |fmt|
fmt.html # This just renders the default template
fmt.json { render json: { count: @cnt } }
end
end
N.b。 - 以上所有代码都是免费的。 :)
答案 2 :(得分:0)
如果你有RESTful控制器:
resources :entries do
collection do
get :vote_down
get :vote_up
end
end
这将产生另外两条路线:
GET /entries/:id/vote_up(.:format) entries#vote_up
GET /entries/:id/vote_down(.:format) entries#vote_down
您可以轻松地将HTTP方法更改为GET,POST,PUT和DELETE。
另外,请检查路线文档中的“Adding More RESTful Actions”。