为啥我需要更加努力地使我的 Rails 应用程序适合 RESTful 架构?

Posted

技术标签:

【中文标题】为啥我需要更加努力地使我的 Rails 应用程序适合 RESTful 架构?【英文标题】:Why do I need to work harder to make my Rails application fit into a RESTful architecture?为什么我需要更加努力地使我的 Rails 应用程序适合 RESTful 架构? 【发布时间】:2010-09-18 19:45:16 【问题描述】:

我最近开始了一个 Rails 项目,并决定使用 RESTful 控制器。我为我的关键实体(例如 Country)创建了控制器,并添加了 indexneweditcreateshowupdatedelete。我将我的map.resources :country 添加到我的路线文件中,生活很好。

开发有点进展后,我开始遇到问题。我有时需要在我的控制器中执行额外的操作。首先是search 操作,它返回了我喜欢的自动完成搜索框的选项。然后需要在应用程序的不同位置以两种不同的方式显示国家/地区(显示的数据也不同,因此不仅仅是两个视图) - 我添加了index_full 操作。然后我想在 URL 中按名称而不是 id 显示国家/地区,因此我添加了 show_by_name 操作。

当您需要在 Rails 的 RESTful 控制器中执行超出标准 indexneweditcreateshowupdatedelete 的操作时,您会怎么做?我是否需要在 routes.rb 文件中添加(和维护)手动路由(这很痛苦),它们是否进入不同的控制器,我是否变得不稳定或我错过了一些基本的东西?

我想我在问,我是否需要更加努力地工作并在我的 routes.rb 文件中添加操作以获得 RESTful 的特权?如果我不使用 map.resources 添加 REST 好东西,标准的 :controller/:action, :controller/:action/:id 路由将自动处理几乎所有事情。

【问题讨论】:

由于 Rails 的默认方法,REST 的含义似乎存在很多混淆。 REST 不仅限于这些方法,而且根本与那些特定方法无关。我也不明白为什么您觉得在向控制器添加其他方法时必须更加努力。 【参考方案1】:

我会将search 视为index 的特例。这两个操作都返回资源集合。请求参数应指定页面、限制、排序顺序和搜索查询等内容。

例如:

/resources/index # normal index
/resources/index?query=foo # search for 'foo'

在 resources_controller 中:

before_filter :do_some_preprocessing_on_parameters

def index
  @resources = Resource.find_by_param(@preprocessed_params)
end

至于index_fullsearch_by_name,您可能会考虑将当前控制器一分为二。你所描述的东西有味道。

话虽如此,您绝对正确,当您的应用没有通过/:controller/:action/:id 提供任何内容时,强制您的应用使用用户宁静的路线是没有意义的。要做出决定,请查看您在表单和链接中使用 restful 资源路由助手的频率。如果你不使用它们,我不会打扰它。

【讨论】:

您在开始时描述的方法打破了我心中的 MVC 模式。我从一个干净地做一件事的动作转变为一个以隐藏的方式做很多不同事情的动作。你的最后一点很有趣——也许我根本不应该使用宁静的路线? 我是这样看的:搜索会找到一堆资源并以某种顺序显示它们。索引操作也是如此,但是 - 默认情况下 - 以硬编码的方式。所以实际上,索引是搜索的一个特例:) 我同意EmbiggensTheMind:我认为索引是搜索的一个特例。【参考方案2】:

如果我的模型超出了标准 CRUD 操作,我通常只根据需要添加方法。搜索是我添加到许多控制器的东西,但不是每个控制器,所以我添加它并正常维护路由:

map.resources :events, :collection =>  :search => :get 

将这些操作移动到一个完全独立的控制器可能会使您的一些控制器保持 RESTful,但我发现将它们保持在上下文中会更有用。

【讨论】:

我只是讨厌在我的路由文件中手动添加和维护大量动作名称。如果我不使用 REST,那么我就不需要这样做。有没有更清洁的方法?如果不是,那么就是这样。 您如何不需要处理路线编辑?仅仅使用“:controller => XXX, :action => YYY”语法?无论您是否使用 REST,命名路由都是一种很好的做法。 Search、index_full、show_by_name 都是参数化的检索操作(即 CRUD 中的 R)。无需添加新路线。【参考方案3】:

REST 未指定您不能拥有其他视图。没有现实世界的应用程序将能够仅使用提供的操作;这就是为什么您可以添加自己的操作。

REST 是关于能够对服务器进行无状态调用。每次返回数据时,您的搜索操作都是无状态的,对吗?您的备用显示操作也是无状态的,只是视图不同。

至于它们应该是手动路由还是新控制器,这取决于活动的不同程度。您的替代视图,如果它提供一整套 CRUD(创建、读取、更新、删除)操作,那么在新控制器中会做得很好。如果您对数据只有一个备用 view,我只会添加一个备用视图操作。

换句话说,听起来你的应用程序没有 RESTful,更多的是意识到自动生成的功能集是一个起点,而不是一个结论。

【讨论】:

我是有状态的,所以我正确地使用了 REST。我想我担心的是因为我决定使用 RESTful,所以我现在需要在我的 routes.rb 文件中做更多的工作,如果我不使用 REST,我就不需要做这些工作。 好吧,代码必须去某个地方:我很好奇您是否觉得拥有明确定义的操作不如拥有说明使用哪个视图的额外标志数据有用?虽然该标志很容易编码,但它会掩盖动作正在做的事情。动作的可发现性很好。 我 100% 反对国旗的想法 - 不用担心。问题是,一旦我为控制器添加了 map.resources 行以添加 REST 映射,我的操作就会从自动发现变为需要在路由文件中手动配置。然后我开始有 Struts 闪回!!【参考方案4】:

在我看来,他们在这里可能有点偏离了轨道。 DRY 怎么了?

我刚刚回到 Rails 并没有对它进行过多的开发,因为它是 beta 版,我仍在等待灯泡出现在这里。我仍然给它一个机会,但如果在我当前的项目结束时它还没有发生,我可能会退回到旧的标准路线并定义我实际上需要它们用于下一个的方法.

【讨论】:

资源路由对 DRYness 影响不大,更多的是约定优于配置。他们为所有 CRUD 操作设置了标准命名路由,对于我参与过的 20 个左右的 Rails 应用程序,这些路由始终占路由的 90% 以上。当然使用默认的 :controller/:action/:id 看起来很简洁,但是当你有成千上万的 url_for :controller => 'foo', :action => 'bar', :id => @ foo 散落在整个模板中,而不是 foo_url(@foo)?【参考方案5】:

我不会继续解释更多关于 REST 的内容,因为我认为这个问题已经回答了,但是我会稍微谈谈默认路由。

我对默认路由的主要问题是,如果您有多个站点使用同一个 Rails 应用程序,它看起来会很糟糕。

例如,您可能不希望人们在一个应用上看到某些控制器:

http://example1.somesite.com/example_2/foo/bar/1

比较一下

/:controller/:action/:id

这将转到控制器 example_2/foo、操作栏和 id 1

我认为这是 Rails 默认路由的主要缺陷,这是 RESTful 路由(带有子域扩展)或仅命名路由(map.connect 'foo' ...)可以解决的问题。

【讨论】:

【参考方案6】:

要在您的设计中保持 RESTful,您需要重新考虑您所谓的资源。

在您的示例中,搜索控制器的显示操作(搜索资源)是保持安静的方向。

我有一个仪表板控制器(显示)和用于就地 ecditors 的单个字段的控制器(显示和更新)

【讨论】:

我不确定我理解你的意思。你可以再详细一点吗?您是说某些操作(例如搜索)应该被视为资源吗?像“map.resources :user_search”这样的东西?

以上是关于为啥我需要更加努力地使我的 Rails 应用程序适合 RESTful 架构?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我的 unwind segue 会使我的应用程序崩溃?

为啥我的 ListView 使我的应用程序崩溃而不是列出我的条目?

为啥意图使我的应用程序崩溃?

为啥这个旧的依赖会使我的 gradle 崩溃?

如何使我的背景图像仅出现在 rails 4 的一页上?

为啥我需要多个 EOF (CTRL+Z) 字符?