Rails和Backbone如何协同工作

35

我刚开始学习MVC结构,先看了一下backbone.js的工作原理,现在我刚刚完成了Code School的Rails For Zombies。我知道我对这些还没有深入了解,但我有一个问题要开始探讨。

你能同时使用这些库吗?

我已经学会了如何在两个库中创建modelsviews等等,但在创建真正的应用程序时,你会同时使用backbone和rails吗?

如果是这样的话…

你什么时候使用backbone.js模型,什么时候使用rails模型?

也许我只是想得太多,需要继续练习和做教程,但我似乎找不到直接相关的信息。

谢谢!

3个回答

74
在任何其他事情之前,我建议您先看一下thoughtbot的Backbone.js on Rails书籍,这是一个很好的起点,虽然面向中级到高级的受众群体。我已经使用过rails购买了这本书,但作为完全的backbone.js初学者,它对我非常有帮助。
除此之外,将这些框架结合起来存在一些根本性的问题,超出了本书和其他书籍所涵盖的细节范围。以下是我从自己的RoR和backbone.js配对经验中提出的一些建议,希望能够帮助您理解所面临问题的“大局”意义。

Rails:Web框架与API

当您在rails应用程序上使用backbone.js时,首先要面对的问题是如何处理视图,但这实际上只是更深层次问题的表面。这个问题涉及到创建RESTful web服务的本质。
Rails默认支持RESTful服务,通过在路由中定义一组资源并使用标准的HTTP操作访问统一的URI(在您的routes.rb文件中定义),以鼓励用户创建RESTful服务。因此,如果您有一个Post模型,您可以:
  • 通过向/posts发送GET请求来获取所有帖子
  • 通过向/posts/new发送GET请求,填写表单并将其发送(POST请求)到/posts来创建新帖子
  • 通过向/posts/123/edit发送GET请求,填写表单并将其发送(PUT请求)到posts/123来更新id为123的帖子
  • 通过向/posts/123发送DELETE请求来删除id为123的帖子
这个Rails方面需要记住的关键是它基本上是无状态的:无论之前我在做什么,只要发送一个带有有效表单数据的POST请求到正确的URI(比如/posts),我就可以创建一个新的Post。当然,有些注意事项:我可能需要登录(有一个识别我的会话cookie),但基本上Rails并不真的关心我在发送请求之前在做什么。我可以通过更新另一个post或者发送一个有效的操作到其他可用资源来继续跟进。

Rails设计的这个方面使得将(轻量级Javascript)Rails Web应用程序转换为API相对容易:资源将类似或相同,Web框架返回HTML页面,而API(通常)以JSON或XML格式返回数据。

Backbone.js:一个新的有状态层

Backbone也基于RESTful资源。每当您创建、更新或销毁一个backbone.js模型时,都是通过发送标准HTTP操作到假定具有RESTful架构的URI来完成的。这使其非常适合与RoR等RESTful服务集成。

但这里有一个微妙的问题需要强调:backbone.js与Rails作为API无缝集成。也就是说,如果你去掉HTML视图,只使用Rails来提供RESTful资源、与数据库集成、执行会话管理等,那么它将与backbone.js为客户端代码提供的结构非常好地集成。许多人认为“用这种方式使用Rails没有问题”,我认为在很多方面他们是正确的。
然而,问题出现在我们刚才丢弃的Rails的另一部分上:视图及其表示。
有状态的人类,无状态的机器
这实际上比起初看来更重要。HTML视图代表了人类用于访问您的服务提供的RESTful资源的无状态接口。去掉它们,你将有两个访问点:
1. 对于人类:由backbone.js层提供的丰富的客户端界面(有状态)。 2. 对于机器:由Rails层提供的面向资源的RESTful API(无状态)。
请注意,现在没有面向人类的无状态(RESTful)接口。相反,在传统的带有API的rails应用程序中,我们有更接近以下内容的东西:
  1. 面向人类的HTML资源(无状态)
  2. 面向机器的JSON/XML资源(API)(无状态)
访问资源的后两个接口在本质上比前两个接口更接近。只需想想rails的respond_with,它利用了这些相似之处,将各种RESTful响应器包装在统一的方法中。

共同工作

我知道这可能看起来非常抽象且离题。为了尝试使其更具体,请考虑以下问题,这与您关于使rails和backbone.js合作的问题有关。在这个问题中,您想要:
创建一个使用backbone.js作为客户端,rails作为后端以JSON格式提供资源的Web服务。使用pushState为应用程序中的每个页面提供URL(例如/posts/123),可以通过直接在浏览器栏中输入来访问。对于这些URL的每一个,还要为没有JavaScript的客户端提供HTML页面。
这些对于现代Web服务并不是不寻常的要求,但它们带来了复杂的挑战。简而言之,您现在必须创建两个“面向人”的层:
1.有状态的客户端界面(backbone.js模板和视图) 2.无状态的HTML资源(Rails HTML视图)
实际执行此操作的复杂性使现今许多人放弃后者,只提供丰富的客户端界面。您决定要做什么取决于您的目标和想要实现的内容,但值得认真思考这个问题。
作为另一个可能的参考,我建议查看O'Reilly的RESTful Web Services。在关于Rails和Backbone.js的问题中推荐一本关于REST的书似乎有些奇怪,但实际上我认为这是将这两个非常不同的框架结合起来的关键部分,更全面地理解它将帮助您充分利用它们的优点。

1
哇,这太棒了。稍微澄清一下:在“共同工作”部分,你所概述的解决方案的想法是,在主页面上有一个骨干应用程序,例如使用AJAX或其他方法访问JSON数据而不是视图,但也制作可以通过输入URL自然访问的HTML视图?再次感谢您详尽的答案,我非常感激! - Troy Cosentino
2
很高兴你喜欢它!是的,你提到了关键点,我没有试图具体回答,因为那将是另一个讨论。这真的取决于你正在构建什么样的应用程序。例如,对于我现在正在做的应用程序,我们决定仅为GET请求提供(无js)HTML页面来获取我们的资源。如果用户想要创建或更新这些资源,他们必须通过丰富的界面(或可能直接访问API)进行操作。这是一个设计选择。您还可以选择放弃无JS支持,但仍然为资源设置URL,那么您就不需要Rails视图。 - Chris Salzberg
2
非常棒的回答。如果我能加2分的话,我一定会这么做。感谢您花时间提供如此完整、周到的回复。 - steveax
非常感谢!请将链接传递给其他对此主题感兴趣的人。 - Chris Salzberg
目前正在思考这个问题——问题是,从一个普通的GET请求开始,我必须添加一个哈希符号(#)才能让backbone识别路由,然后呈现它(并在此过程中从URL中删除哈希符号)。 - MBHNYC
1
你不需要添加哈希。你只需要一个(Rails)路由,它可以呈现应用程序的相同根视图,然后 Backbone(启用pushState)将把该路径识别为Backbone路由并呈现相应的(Backbone)视图。如果浏览器不支持pushState,Backbone会识别这一点并重定向到以哈希前缀的路径。 - Chris Salzberg

1

是的,你可以同时使用两者。Backbone用于在客户端浏览器中存储和操作数据。通常需要与服务器通信并从服务器获取数据。这就是Rails的作用。您可以拥有一个没有重型客户端代码的Web应用程序。Backbone用于构建感觉更像应用程序的站点-例如Gmail或Pandora。

我建议先学习Rails。一旦您可以加载静态页面并按照自己的意愿进行样式设置,那么理解Backbone的位置将更加清晰。


1

我曾经使用Rails作为后端服务器来服务一个相当大的网站,其中包括一些单页应用程序(使用backbone构建)。

我建议使用backbone-on-rails gem。这个想法是你的Rails服务器将在你的视图中作为脚本标签提供backbone应用程序。你将backbone应用程序本身保存在Rails的app/assets文件夹中。

Backbone了解Rails路由约定,你只需要给它一个指向Rails几乎可以为你生成的json api的路径,方法是使用rails generate resource

除了模型之间的同步外,你的backbone应用程序和Rails应用程序是相当独立的。Backbone和Rails没有完全相同的MVC模型,但让它们合作起来非常容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接