Rails 4:如何使用AJAX更新索引页面

我无法相信我没有找到其他问题来回答这个问题,但我已经搜索过高低,找不到真正回答我问题的任何问题。

基本上,我有一个费用页面,我想在表格中显示给定月份内的所有费用。 我有一个月份和年份选择,现在我通过向url添加月份和年份参数并使用一些小的javascript转到该href。 我想避免页面刷新,只是在更改选择框值时更新表。 据我了解,因为我没有使用表单,我不能使用:remote => true ,因此必须使用AJAX。 我的研究让我设置如下。

这是我的JQuery与AJAX调用:

 $(document).ready(function() { $('#monthSelect').change(function() { // alert("yay"); var m = $(this).val(); var y = $("#yearSelect").val(); $.ajax({ type: "GET", url: "/expenses", data: { month : m, year : y } , success: function(data) { }, dataType: "json" }); }); }); 

#monthSelect#yearSelect是我的两个选择框的ID。 这部分似乎有效。 当我更改月份选择框的值时,它会在params中将正确的月份和年份的GET请求发送到"/expenses"

/expenses自然地路由到我的index操作。 这是我困惑的部分。

 def index @expenses = # Code that gets the expenses that correspond to the month and year in the params. # This part works. I've tested it and @expenses are all the records I want respond_to do |format| format.html format.json { render json: @expenses, status: :ok } #????? end end 

所以我想我的主要问题是json部分是如何工作的,以及我是否应该在AJAX中使用json。 我看过的教程和video似乎都暗示在json中获取响应是你应该这样做的方式,但我不确定“渲染json”甚至意味着什么。 我的理解是传递@expenses ,它基本上会呈现@expenses.to_json返回的内容,这只是一堆json,键值对。 我该怎么做并制作一张桌子?

我的一个朋友做了很多AJAX但没有Ruby on Rails说我可以在AJAX成功函数中编写HTML

 ... success: function(data) { $("#expenses-table").html("HTML of my Table"); } 

但这似乎不像Rails的方式,放一堆只是将HTML放入字符串的Javascript代码。 然后render: json是什么render: json如果我只是把HTML放在AJAX中呢? 我确实在Stack Overflow上看到了答案

 success: function(data) { $("#expenses-table").html(data); } 

这将是不错的,因为数据确实拥有我想要的所有json。 但显然这不仅仅是那样的工作。

因此,如果我可以对这整个混乱做一些澄清,如果我甚至用JSON接近它,或者我应该只在AJAX中编写HTML,那将非常感激。

编辑1:这是我目前的表格代码:

 
Description Amount User Date

基本上只是标准的脚手架表。 大多数变化只是css。 这是json对于一条记录的样子

[{"id":8,"description":"This is a test","amount":"35.0","user_id":1,"date":"2014-10-01","created_at":"2014-10-03T07:07:53.412Z","updated_at":"2014-10-03T07:07:53.412Z","receipt_file_name":null,"receipt_content_type":null,"receipt_file_size":null,"receipt_updated_at":null}]

我想我宁愿在ERB / ruby​​中执行代码,因为我对它更加熟悉。 虽然使用json几乎感觉有点无意义,因为@expenses是我在当前表代码中已经使用的。 但是,不会渲染:文件“expenses_table.html.erb”刷新整个页面? 或者它如何知道在哪里渲染该表并替换以前的表? 回复format.js并制作一个index.js.erb几乎听起来更容易,因为我知道我可以用我的部分取代html。 但我没有尝试过,因为我看过的所有例子都对format.json有所回应。 如果听起来我只是困惑而且不知道发生了什么事,因为我是。 我只需要澄清一下。 谢谢你的帮助!

如果我甚至应该在AJAX中使用json。

您可以使用任何类型的String。 问题是解析javascript端的字符串以提取每个数据。 例如,您可以使用String响应,例如:

 "exp1=10, exp2=20, exp3=30" 

然后你的javascript代码可以将字符串拆分为“,”,然后是“=”符号,然后使用这些部分创建一个对象,然后你可以使用该对象来引用数据。 另一方面,如果数据是作为JSON字符串发送的,那么您在javascript中所要做的就是:

 var obj = JSON.parse(data); 

…和obj将类似于ruby哈希,在那里你可以查找键来获取值。

所以我想我的主要问题是json部分如何工作……我的理解是传递@expenses,它基本上会呈现@ expenses.to_json返回的内容,这只是一堆json,键值对。 我该怎么做并制作一张桌子?

那是对的。 你使用自己的编程技巧制作表格。

我的一个朋友做了很多AJAX但没有Ruby on Rails说我可以在AJAX成功函数中编写HTML

当然,但诀窍仍然是以编程方式获取json中的数据并将其插入到html表中。 如果你想走这条路,你可以返回一个完整的表作为响应,这样你就可以在服务器端使用ERB / Nokogiri / ruby​​在表中插入数据。 然后你会写一些像:

 @expenses = .... render :file "/some/dir/expenses_table.html.erb" 

另一种方法可能是为表中的每个

提供一个id属性,该属性等于json数据中的一个键。 然后,您可以使用javascript循环json数据中的每个键,使用该id查找

,然后将该条目替换为与该键对应的json数据中的值。

如果你想要更具体的建议,你必须发布你的表的html的一个小例子以及@ expenses.to_json的样子。

顺便说一句,jQuery ajax()函数有太多的function,所以所有常见的ajax请求都有快捷函数,其中相关的选项都填入你的位置,例如getJSON() ,你只需指定url,data,和成功的function。 在这种情况下,这不会为您节省很多工作,但可能函数名称比’ajax’更具描述性。

对评论问题的回复:

我想我的困惑是这是什么JavaScript? 这是最初的AJAX通话吗?

是。 这是您需要编码的唯一JavaScript。

应该在js.erb文件中,然后让我调用一些ruby代码?

不。如果你想使用ruby创建一些js(这就是erb的用途),你会使用js.erb文件,并且你想要返回js代码作为响应。 我们已经确定您不希望返回javascript作为响应。 但是,使用rails来设置ajax是非常令人困惑的,所以我可能不理解你的问题的要点。 不使用rails生成ajax javascript更简单。

据我所知,如果你在创建一个html表单时把remote: true放在你的rails html帮助器中,那么当提交表单时,会向你的rails应用程序发送一个带有text/javascript接受标头的请求。 这意味着如果你的动作有一个带有format.js行的respond_to块,那行就会执行,你可以将一些javascript发送回浏览器,例如一个.js.erb文件,其中包含执行ajax请求的代码以获取你的费用数据。 您的浏览器将立即执行返回的js,它将向服务器发送ajax请求,询问费用数据。 请注意,rails方式效率低下:浏览器必须向服务器发送两个请求以完成一个ajax请求:一个请求被发送到服务器以获取将对费用数据发出ajax请求的js代码,然后是浏览器执行ajax代码,该代码向服务器发送另一个请求以获取费用数据。

或者我可以在响应中调用javascript文件吗?

在我看来,你想用一个全新的表替换现有的表,即你没有在现有的表中改变两个或三个

's

,这应该让事情变得非常简单。 事实上,据我所知,您可以使用与创建现有表相同的erb代码来创建新表。 但是,索引操作对ajax请求的响应应该只返回表 – 而不是整个页面。 这表明您应该将创建表的代码放入单独的模板中,部分模板:

views/shared/_table.html.erb

  <% @expenses.each do |expense| %>  <% end %> 
DescriptionAmountDate
<%= expense.description %> <%= number_to_currency expense.amount %> <%= expense.date %>

然后在views/expenses/index.html.erb包含partial:

 

Expenses#index

Find me in app/views/expenses/index.html.erb

<%= render "shared/table" %>

默认情况下,render()将在app / views目录中shared/_table.html.erb名为shared/_table.html.erb

这两个文件组合在一起(插入到应用程序布局中)构成了index.html.erb视图。 因为该表现在是一个单独的模板,所以只能呈现表以响应ajax请求:

 class ExpensesController < ApplicationController def index respond_to do |format| if request.xhr? #Is this an ajax request? target_date_str = params['target_date'] if target_date_str == "all" @expenses = Expense.all else @expenses = Expense.where(date: Date.strptime(target_date_str, "%Y-%m-%d")) end #Render just the table for the ajax request: format.html { render partial: "shared/table" } else #then not an ajax request @expenses = Expense.all format.html #By default renders index.html.erb end end end end 

respond_to()查看请求中的Accept标头,并根据它选择匹配的格式:

 format.html format.json format.xml etc. 

我检查了jQuery的.get()ajax函数发送的请求,它发送一个带有text/html的Accept标头作为最高优先级的请求,因此将在respond_to块中选择format.html。 编辑:我最初编写索引操作,认为ajax请求会有一个format.json行,非ajax请求会有一个format.html行。 但是因为索引操作现在在两种情况下都返回html,所以不需要respond_to()块:

 class ExpensesController < ApplicationController def index if request.xhr? #if an ajax request... target_date_str = params['target_date'] if target_date_str == "all" @expenses = Expense.all else @expenses = Expense.where(date: Date.strptime(target_date_str, "%Y-%m-%d")) end render partial: "shared/table" #Overrides rails default operation which renders index.html.erb else #then not an ajax request @expenses = Expense.all #rails defaults to rendering index.html.erb end end 

这是我使用的javascript:

  

Expenses#index

Find me in app/views/expenses/index.html.erb

<%= render partial: "shared/table", expenses: @expenses %>

我把javascript放在index.html.erb视图中,这应该清楚javascript是html页面的一部分。 但是,您可以从index.html.erb中删除javascript并将其放在另一个文件中 - 但最终js必须找回index.html.erb文件。 以下是一些讨论javascript备用位置的链接:

为什么rails不呈现.js.erb文件?

在Rails 3应用程序中添加页面特定javascript的最佳方法?

Rails有一个称为asset pipeline东西,它是一种通过删除所有空格将所有javascript和css塞入尽可能少的行的方法。 由于文件较小,因此您的浏览器可以更快地加载它们。 要利用这种缩小 ,您必须将您的assets (即您的javascript和css文件)放入某些目录中。 这真的不是你需要担心的事情,因为你的javascript代码不是几千页。