5

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

更改 URL 路径

官方文档解释说,如果我们想更改带有前缀的控制器的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

但是您再次遇到另一个错误: “未定义的局部变量或方法'admin' for main:Object”

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

因此,您在 Ruby 类中添加了一个大写字母:

  class Admin::MoviesController < ApplicationController

但你仍然得到一个错误:

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

我勒个去...?哦,文档是否也忘了说控制器的相应视图也必须移动到 app/view/ 中的管理目录?

因此,您创建一个目录并将您的视图移动到 app/view/admin/ 并且您仍然会遇到相同的错误。

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

您仍然收到错误消息:* undefined method `movies_path' for #<#:0xa817c0c>*

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

此外,如果您在控制器文件中使用“ 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::”。这里例如索引方法:

  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 路径?我的控制器中的这个小修改会容易得多:resources :movies, :path => "/admin/movies"
  2. 为了使使用相同名称的两个不同控制器成为可能?给我的控制器名称加上前缀不是比所有这些混乱更容易吗?

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

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

非常感谢

4

2 回答 2

1

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

于 2012-10-03T08:53:22.397 回答
1

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

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

rake generate controller "Foo/Bars"

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

于 2014-01-31T23:25:09.820 回答