通过编写Ruby on RailsONLY来编写简单的HTML轮询。
如果你做过Rails,你可能在过去的日子里编写过一到两个投票机制。在写到一半的时候,当你在服务器上编码完Rails部分后,一种恼人的感觉开始悄然而至,你必须写出额外的JavaScript。如果你有这种感觉,(即使你没有),现在有一种方法可以在不实际写任何JS代码的情况下做到这一点。首先,让我们深入了解以下轮询的概念。
什么是民意调查?
轮询是一个过程,当客户端(这里是指我们的浏览器)不断向服务器发送请求以检查是否有更新。轮询就是所谓的拉动技术。它经常被用来模拟推送技术。在我们继续之前,让我们描述一下这些术语。
拉动技术
定义:对数据的初始请求来自于客户端,然后被响应。 例如。一个网络浏览器请求一个网页。
推送技术(也称为推送通知)
定义:一个服务器发布数据,而被订阅的客户端正在接收数据。 例子。一个电子邮件服务器向一个电子邮件客户端发送电子邮件。
所以,我们不是做发布/订阅机制,即服务器发送数据更新,我们监听这些更新,而是要反复询问服务器是否真的发生了变化。
如何在Rails中进行轮询?
好了,现在我们解释了什么是轮询,让我们进入正题。为了在Rails中进行轮询,你需要写两件事:
- 将被轮询的控制器动作和它返回的响应/视图
- 定期检查控制器动作的变化并在UI中进行必要的更新的JavaScript。
第一部分是非常简单的:比方说,我们有一个网站,显示电影和它们的评级。电影的评级不断变化,我们想让用户了解任何评级变化的情况。在这种情况下,我们将在Movies控制器中创建一个评级动作。
# app/controllers/movies_controller.rb
class MoviesController < ApplicationController
# somewhere inside Movies controller
def rating
@rating = @movie.rating
render partial: 'movie_rating'
end
end
然后,我们可以像这样为电影评级创建一个局部,这样我们就可以很好地向用户展示它:
<!-- app/views/movies/_movie_rating.html.erb -->
Movie rating: <%= @rating %>
第二部分有时会有点烦人:我们需要在我们的前端编写JavaScript,它将不断查询我们定义的服务器动作。但是,它也需要更新页面,这样才能反映出变化:
<!-- app/views/movies/show.html.erb -->
<div id="rating">Loading rating...</div>
<script>
const checkRating = () => {
fetch("<%= movie_rating_path(@movie) %>")
.then((response) => response.text())
.then((response) => {
document.getElementById("rating").innerHTML = response
})
}
setInterval(checkRating, 2000)
</script>
在这里,我们定义了一个checkRating(第6行)函数,它将被第14行的setInterval每2秒调用一次。在第7行,我们告诉它通过在请求的URL中指定一个电影的ID来获取它的评分。
🎉,如果你进入你的电影页面并在浏览器中打开网络标签,你应该看到每隔2秒就会发出一次评级请求。
但没有JavaScript,如何做轮询?
别着急,我们就要成功了。你可以用新版本的render_asyncgem做简单的轮询。为了做到这一点,你需要在你的Rails应用程序中安装该宝石,并在application.html.erb文件中放入这个片段:
<%= content_for :render_async %>
这个片段将为我们加载JavaScript代码,这样我们就不必自己编写代码了。所以,并不是完全没有,只是我们不用自己写。
我们将保留前面例子中的movies_controller.rb和*_movie_rating.html.erb文件,我们只需编辑show.html.erb,使其看起来像这样:
<!-- app/views/movies/show.html.erb -->
<%= render_async movie_rating_path(@movie), interval: 2000 %>
等等,就是这样吗?是的,就是这样,恭喜你 🎉!这段代码将生成JavaScript,每2秒获取一次电影评分。多么整洁和令人敬畏啊!😌。如果你现在访问你的电影页面,它的评分应该显示出来,并且应该不断地通过投票来更新。
奖励回合
这还不是你能用它做的全部。你也可以在其中加入一些错误处理,也不需要写任何JS代码:
<!-- app/views/movies/show.html.erb -->
<%= render_async movie_rating_path(@movie), interval: 2000, error_message:
"Couldn't load rating :(" %>
你在读这个的时候会有什么反应?哇,我也能让错误信息显示出来了🤯?我在哪里可以试一试这个工具?
就在这里,我的朋友,不客气❤️
投票功能最近在2.1.0版本的gem中发布了,它已经可以被社区使用了。如果你在你的应用程序中使用轮询,你可以试试这个功能的宝石。
render_async已经存在了很长时间,它被用于像Codetriage这样的产品中(见GitHub上 Richard Schneeman的issue,它还被Nate Berkopec在Twitter上称赞过:
我认为render_async看起来是 "html-over-the-wire "工具包中另一个潜在的有价值的部分,与PJAX和Turbolinks一样。
- Nate Berkopec(@nateberkopec)2017年6月8日
你还可以在Semaphore CI博客上阅读使render_async出名的原始博文,并看到他的原始用例。
如果你喜欢你所看到的,请👏并传播这个消息。另外,请查看我的网站并关注我。我将会发布更多与Rails和JavaScript相关的文章,请点击 "关注 "并保持关注📹。
另外,转发这篇文章也是帮助你的朋友们传播信息的一个好方法:
我刚刚发布了 "无需JavaScript的Rails HTML投票 "#rails #javascript t.co/vbO9CgStV8
- Nikola Đuza (@nikolalsvk)May 14, 2019
干杯!🍻