【问题标题】:Rails url_for and namespaced modelsRails url_for 和命名空间模型
【发布时间】: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/usersapp/controllers/m/users_controller.rbapp/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中找到。

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 namespaces url-for


    【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2012-07-08
      • 2012-09-10
      • 2017-03-21
      • 2013-02-12
      • 2015-04-05
      • 1970-01-01
      • 2012-04-18
      • 1970-01-01
      • 2013-05-28
      相关资源
      最近更新 更多