Rails url_for和命名空间模型

时间:2022-06-07 11:03:11

In Rails, is it possible to namespace models in modules and still get correct behavior from url_for?

在Rails中,是否可以在模块中命名模型并仍然从url_for获得正确的行为?

For instance, here, url_for works as expected:

例如,在这里,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

Whereas after putting the User model into a module, url_for complains about an undefined method m_user_path:

将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'

Is it possible to have url_for ignore the module in M::User and return user_path for url_for(@user) instead of m_user_path?

是否可以让url_for忽略M :: User中的模块并返回ur__for(@user)而不是m_user_path的user_path?

UPDATE

UPDATE

So, after almost 5 years, here's the solution, thanks to esad. This has been tested in Rails 4.2.

因此,经过近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

Note: when generating model, view and controller with bin/rails g scaffold m/user, the views and the controller will be namespaced, too. You need to move app/views/m/users to app/views/users and app/controllers/m/users_controller.rb to app/controllers/users_controller.rb; you also need to remove references to the module M everywhere except in the model M::User.

注意:使用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的引用。

Finally, the goal here was to namespace models but not views and controllers. With esads solution, the module M (containing User) is explicitly told to not appear in routes. Thus, effectifely, the M is stripped of and only User remains.

最后,这里的目标是命名空间模型,但不是视图和控制器。使用esads解决方案,模块M(包含用户)被明确告知不会出现在路由中。因此,有效地,M被剥离并且仅剩下用户。

The user model can now reside in app/views/models/m/user.rb, the users controller lives in app/views/controllers/users_controller.rb and the views can be found in app/views/users.

用户模型现在可以驻留在app / views / models / m / user.rb中,用户控制器位于app / views / controllers / users_controller.rb中,并且可以在app / views / users中找到视图。

4 个解决方案

#1


23  

Just define use_relative_model_naming? in the containing module to avoid prefixing the generated route names:

只需定义use_relative_model_naming?在包含模块中,以避免为生成的路由名称添加前缀:

module M
  def self.use_relative_model_naming?
    true
  end
end

#2


4  

Use

使用

namespace "blah" do
  resources :thing
end

Then routes will be named appropiately.

然后路线将被恰当地命名。

rake routes

To view all routes

查看所有路线

#3


3  

Specify the module on the route

指定路径上的模块

resources :users, :module => "m"

or use scope to do it

或使用范围来做到这一点

scope :module => "m" do
  resources :users
end

#4


0  

In my case I overridden the url_for method on my application_helper.rb file to add the :network param on all routes from my namespace :mkp.

在我的例子中,我覆盖了我的application_helper.rb文件中的url_for方法,在我的命名空间的所有路由上添加:network param:mkp。

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

#1


23  

Just define use_relative_model_naming? in the containing module to avoid prefixing the generated route names:

只需定义use_relative_model_naming?在包含模块中,以避免为生成的路由名称添加前缀:

module M
  def self.use_relative_model_naming?
    true
  end
end

#2


4  

Use

使用

namespace "blah" do
  resources :thing
end

Then routes will be named appropiately.

然后路线将被恰当地命名。

rake routes

To view all routes

查看所有路线

#3


3  

Specify the module on the route

指定路径上的模块

resources :users, :module => "m"

or use scope to do it

或使用范围来做到这一点

scope :module => "m" do
  resources :users
end

#4


0  

In my case I overridden the url_for method on my application_helper.rb file to add the :network param on all routes from my namespace :mkp.

在我的例子中,我覆盖了我的application_helper.rb文件中的url_for方法,在我的命名空间的所有路由上添加:network param:mkp。

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