【问题标题】:Rails : Benefit of URL path modification vs Namespace?Rails:URL路径修改与命名空间的好处?
【发布时间】:2012-09-30 20:36:49
【问题描述】:

许多人将命名空间作为一种更改 URL 的方法,该 URL 带有前缀(即:/admin/movies 而不是 /movies)

更改 URL 路径

official doc 解释说,如果我们想更改带有前缀的控制器的 URL,我们只需要更改 config/route.rb 中的资源。

从此:

  resources :movies

到这里:

  resources :movies, :path => "/admin/movies"

实现命名空间

经过大量的谷歌搜索,我想知道为什么这么多人喜欢使用命名空间以及 命名空间与仅在路由器文件中修改通向特定控制器的 URL 路径相比有何优势 : myapp/config/route.rb

要实现命名空间,官方文档解释说您需要进行以下修改。 你会发现这是很多工作

  namespace :admin do
    resources :movies
  end

...并将您的 movies_controller.rb 控制器移动到 app/controllers/admin 目录。

但如果您按照这些说明进行操作,您将收到此错误:

*"预期 /var/www/myapp/app/controllers/admin/movies_controller.rb 来定义 Admin::MoviesController"*

*然后您意识到 Rails 期望在您的 movies_controller.rb 开头出现这种“外星人”写作:“Admin::”*

因此,您将 movies_controller.rb 的第一行更改为:

  class admin::MoviesController < ApplicationController

而不是:

  class MoviesController < ApplicationController

但你又得到另一个错误: "main:Object 的未定义局部变量或方法 `admin'"

然后你意识到你忘记了 Ruby 类必须以大写开头。

所以你在你的 Ruby 类中添加了一个大写字母:

  class Admin::MoviesController < ApplicationController

但你仍然得到一个错误:

*缺少模板 admin/movies/index, application/index with {:locale=>[:"fr-CH"], :formats=>[:html], :handlers=>[:erb, :builder, :rxls, :coffee, :haml]}。搜索:*“/var/www/myapp/app/views”*

什么鬼……?哦,文档忘了说控制器的相应视图也必须移动到 app/view/ 中的管理目录?

所以你创建一个目录并将你的视图移动到 app/view/admin/ 你仍然会遇到同样的错误。

然后您意识到您忘记将电影文件夹本身包含在 app/view/admin 中 所以你做到了。

您仍然收到一条错误消息: *#*

的未定义方法 `movies_path'

这一次您知道路由、控制器和视图可以工作,但您仍然需要更改所有视图的路径...

此外,如果您在控制器文件中使用“respond_with”方法,则必须包含命名空间作为参数。这是索引操作的示例:

  def index
    @movies = Movie.all
    respond_with(:admin, @movies)
  end

此外,如果您使用 declarative_authentification gem(类似于 cancan gem),您必须在您的 permited_to 参数前加上前缀?带有命名空间的方法。例如(使用 HAML 语法):

- if permitted_to? :index, :admin_movies
  // And prefix as well your path
  = link_to 'Show all my movie", admin_movies_path

- if permitted_to? :show, :admin_movies
  // And prefix as well your path
  = link_to 'Show selected movie", admin_movie_path(@movie)

你意识到你要创建一个命名空间只是为了方便 url 路径,所以你决定放弃,回滚你的 modif,只需在你的 route.rb 文件中添加以下行:

  resources :movies, :path => "/admin/movies"

效果立竿见影。

作为测试目的我创建了一个新的假项目“testapp”,包括带有生成器的命名空间。 我执行了“rails generate scaffold admin/movie title:string”来检查生成器如何处理命名空间。 生成的 app/controller/admin/movies_controller.rb 与我们预期的完全不同。 每个实例变量声明前都有附加前缀“Admin::”。 这里以 index 方法为例:

  def index
    @admin_movies = Admin::Movie.all

    respond_to do |format|
      format.html # index.html.erb
      format.json { render json: @admin_movies }
    end
  end

我猜这是因为生成器也将模型 movie.rb 移动到了 app/models/admin 目录

此外,我看到 app/models 中有另一个模型:admin.rb 其中包含:

  module Admin
    def self.table_name_prefix
      'admin_'
    end
  end

我不知道这个方法将如何被使用,也不知道由谁使用?

我还注意到,我的表将在 /db/migrate/2012blabla_create_admin_movies.rb 中命名为“admin_movies”

  class CreateAdminMovies < ActiveRecord::Migration
    def change
      create_table :admin_movies do |t|

        t.timestamps
      end
    end
  end

嗯,为了建立一个命名空间,似乎需要比我预期的要多得多的工作(和混乱)......

有什么好处/优势???

  1. 要使用另一个 url 路径?我的控制器中的这个小修改 会容易得多:资源:电影,:路径=> “/管理员/电影”
  2. 为了使使用相同名称的两个不同控制器成为可能?给我的控制器名称加上前缀不是更容易吗?

当然,提高警惕可以避免上述一些错误。但是你知道,我们只是人类,在深夜编码时,也许你希望 Rails 的这一部分能够,比方说,更适合人类......

我真的不明白为什么人们对拥有命名空间如此兴奋。 如果专家能解释我缺少什么,我将不胜感激。

非常感谢

【问题讨论】:

  • 好问题。谢谢(你的)信息。希望你能得到一个好的答案。

标签: namespaces url-routing ruby-on-rails-3.2


【解决方案1】:

如果您有两个具有相同名称但功能不同的不同控制器,那么您可以使用命名空间路由。您不必为它重命名控制器。查看http://guides.rubyonrails.org/routing.html 上的“2.6 控制器命名空间和路由”。

【讨论】:

  • 感谢您的回答。是的,我阅读并重新阅读了至少 5 次 ^^ 没有关于该实用程序的真正解释。特别是因为您可以为每个控制器添加一个简单的前缀,就像 rails 对您的每个关联表一样......老实说,这是一种更简单的方式;)
【解决方案2】:

我们的想法是不要在一个目录中拥有大量控制器。命名空间通过将控制器分组到目录中来帮助您做到这一点。

就完成所有这些工作而言,使用命名空间路径生成所需的控制器要容易得多,例如:

rake generate controller "Foo/Bars"

然后,rails 可以完成所有繁重的工作,因此您不必这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-01
    • 2011-08-29
    • 2014-02-18
    • 1970-01-01
    • 2012-10-10
    • 1970-01-01
    • 1970-01-01
    • 2012-09-02
    相关资源
    最近更新 更多