【问题标题】:Rails 3 - default_url_options based on url being generatedRails 3 - default_url_options 基于正在生成的 url
【发布时间】:2012-04-04 09:09:42
【问题描述】:

在 rails 3 中,是否可以访问在 default_url_options() 中生成的 URL 的控制器/操作?在 rails 2 中,你被传递了一个选项的哈希值,这些选项即将传递给 url_for(),你当然可以改变它。

例如Rails 2 代码:

==== config/routes.rb
  map.foo '/foo/:shard/:id', :controller => 'foo', :action => 'show'

==== app/controllers/application.rb
  def default_url_options options = {}
    options = super(options)
    if options[:controller] == 'some_controller' and options[:id]
      options[:shard] = options[:id].to_s[0..2]
    end
    options
  end

==== anywhere
  foo_path(:id => 12345) # => /foo/12/12345

但是,在 rails 3 中,由于 default_url_options 没有传递任何选项哈希,因此相同的代码失败了,而且我还没有弄清楚如何测试控制器是什么。

FWIW,上面的“分片”是由于当您打开缓存时,如果您的数据库中有大量 foo 行,那么您将在基于 unix 的系统上达到文件数量的 inode 限制在某个时候在 1 个文件夹中。此处正确的“修复”可能是更改缓存设置以将文件存储在分片路径中,而不是完全分片路由。不过,在编写上述代码时,我的一部分人认为始终将缓存文件与路由保持相同的结构是很好的,以防万一您想要使用 rails 之外的东西来服务缓存。

但是,唉,我仍然对上述问题的解决方案感兴趣,纯粹是因为它在吞噬我,我无法弄清楚。

编辑:目前我有以下我必须放弃的,因为你失去了所有其他 named_route 功能。

==== config/routes.rb
  match 'foo/:shard/:id' => 'foo#show', :as => 'original_foo'

==== app/controllers/application.rb
  helpers :foo_path

  def foo_path *args
    opts = args.first if opts.is_a?(Array)
    args = opts.merge(:shard => opts[:id].to_s[0..2]) if opts.is_a?(Hash) and opts[:id]
    original_foo_path(args)
  end

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 routing routes rails-routing


    【解决方案1】:

    定义一个类似的助手

    # app/helpers/foo_helper.rb
    module FooHelper
      def link_to name, options = {}, &block
        options[:shard] = options[:id].to_s[0..1] if options[:id]
        super name, options, &block
      end 
    end
    

    然后在您看来执行以下操作,似乎对我有用

    <%= link_to("my shard", id: 12345) %>
    

    编辑:或将foo_path 自定义为

    module FooHelper
      def link_to name, options = {}, &block
        options[:shard] = options[:id].to_s[0..1] if options[:id]
        super name, options, &block
      end 
    
      def foo_path options = {}
        options[:shard] = options[:id].to_s[0..1] if options[:id]
        super options
      end 
    end
    

    【讨论】:

    • 当然,那么我必须将所有调用更改为 foo_path()。如果您覆盖 link_to() 则根本没有命名路径。
    • 哦,我还需要在链接之外生成路径,例如从控制器,所以你可以简单地做expire_cache_path foo_path(:id =&gt; 12345)
    • 原理一样,在FooHelper中自定义foo_path
    猜你喜欢
    • 2011-08-31
    • 2013-05-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-16
    • 1970-01-01
    • 2011-09-21
    • 2011-09-07
    相关资源
    最近更新 更多