【发布时间】: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
嗯,为了建立一个命名空间,似乎需要比我预期的要多得多的工作(和混乱)......
有什么好处/优势???
- 要使用另一个 url 路径?我的控制器中的这个小修改 会容易得多:资源:电影,:路径=> “/管理员/电影”
- 为了使使用相同名称的两个不同控制器成为可能?给我的控制器名称加上前缀不是更容易吗?
当然,提高警惕可以避免上述一些错误。但是你知道,我们只是人类,在深夜编码时,也许你希望 Rails 的这一部分能够,比方说,更适合人类......
我真的不明白为什么人们对拥有命名空间如此兴奋。 如果专家能解释我缺少什么,我将不胜感激。
非常感谢
【问题讨论】:
-
好问题。谢谢(你的)信息。希望你能得到一个好的答案。
标签: namespaces url-routing ruby-on-rails-3.2