Rails url_for 和命名空间模型
Posted
技术标签:
【中文标题】Rails url_for 和命名空间模型【英文标题】:Rails url_for and namespaced models 【发布时间】:2011-05-23 05:04:12 【问题描述】:在 Rails 中,是否可以在模块中命名模型并仍然从 url_for
获得正确的行为?
例如,在这里,url_for
按预期工作:
# app/models/user.rb
class User < ActiveRecord::Base
end
# config/routes.rb
resources :users
# app/views/users/index.html.haml
= url_for(@user) # /users/1
而在将 User
模型放入模块后,url_for
抱怨未定义的方法 m_user_path
:
# app/models/m/user.rb
module M
class User < ActiveRecord::Base
end
end
# config/routes.rb
resources :users
# app/views/users/index.html.haml
= url_for(@user) # undefined method 'm_users_path'
是否可以让url_for
忽略M::User
中的模块并为url_for(@user)
返回user_path
而不是m_user_path
?
更新
所以,在将近 5 年之后,这就是解决方案,感谢 esad。这已经在 Rails 4.2 中进行了测试。
# app/models/m/user.rb
module M
class User < ActiveRecord::Base
end
end
# app/models/m.rb
module M
def self.use_relative_model_naming?
true
end
def self.table_name_prefix
'm_'
end
end
# config/routes.rb
resources :users
# app/views/users/index.html.haml
= url_for(@user) # /users/1
注意:当使用bin/rails g scaffold m/user
生成模型、视图和控制器时,视图和控制器也会被命名空间。您需要将app/views/m/users
移动到app/views/users
和app/controllers/m/users_controller.rb
到app/controllers/users_controller.rb
;除了模型M::User
之外,您还需要删除对模块M
的引用。
最后,这里的目标是命名模型而不是视图和控制器。使用 esads 解决方案,模块M
(包含User
)被明确告知不要出现在路由中。因此,实际上,M
被删除,只剩下User
。
用户模型现在可以位于app/views/models/m/user.rb
,用户控制器位于app/views/controllers/users_controller.rb
,视图可以在app/views/users
中找到。
【问题讨论】:
【参考方案1】:只需在包含模块中定义use_relative_model_naming?
以避免在生成的路由名称前加上前缀:
module M
def self.use_relative_model_naming?
true
end
end
【讨论】:
这是金!解决了 OP 的要求(以及我在寻找什么)谢谢 这个方法应该是 Rails API 中记录的第一个方法! 对自己(和其他人)的注意:这必须在模块中,即命名空间本身,而不是在类中。【参考方案2】:使用
namespace "blah" do
resources :thing
end
然后路线将被适当地命名。
rake routes
查看所有路线
【讨论】:
谢谢,我试过了,但它并没有解决问题:虽然 url_for 被告知模型命名空间,但路由(控制器)将适应使用相同的命名空间——这不是我的需要。因此:是否可以设置路由以使用位于不同命名空间中的模型和控制器?换句话说,有没有一种方法可以影响 url_for 给定模型实例的行为,而无需触及控制器路由?例如,模型 M::User 将定义在 app/models/m/user.rb 中,而控制器将定义在 app/controllers/user_controller.rb 中。 另外,如果它不是 RESTFul 资源,你会怎么做?我有这个问题,我正在处理的控制器不能被硬塞到资源中。 resources :things do (new line) get "foo" => "controller#action". 这不是正确的答案,请参阅我上面的编辑。要求是这样的:将模型放入模块中,没有命名空间视图和控制器。在您的解决方案中,模型、视图和控制器都必须命名空间。【参考方案3】:指定路由上的模块
resources :users, :module => "m"
或者使用作用域来做
scope :module => "m" do
resources :users
end
【讨论】:
完美运行!谢谢:)【参考方案4】:在我的例子中,我重写了 application_helper.rb 文件中的 url_for 方法,以在我的命名空间 :mkp 的所有路由上添加 :network 参数。
module ApplicationHelper
def url_for(options = )
if options.is_a?(Hash) && options.has_key?(:controller)
if options[:network].nil? && options[:controller].match(/^mkp\//).present?
options[:network] = @network.downcase
end
end
super(options)
end
end
【讨论】:
以上是关于Rails url_for 和命名空间模型的主要内容,如果未能解决你的问题,请参考以下文章
Rails 4:在没有命名空间模型的子路径中组织 Rails 模型?