代码之家  ›  专栏  ›  技术社区  ›  Paweł Gościcki Ywain

自定义RESTful资源的URL_(复合键,而不仅仅是ID)

  •  9
  • Paweł Gościcki Ywain  · 技术社区  · 14 年前

    给定以下资源定义:

    map.resources :posts, :except => [:show]
    map.post '/:year/:month/:slug, :controller => :posts, :action => :show
    

    我可以做 url_for 为我工作,使用以下语法:

    <%= link_to @post.title, post_url(:year => '2010', :month => '02', :slug => 'test') %>
    

    但是,有没有办法让这一切奏效呢?

    <%= link_to @post.title, @post %>
    

    当前它引发此错误:

    No route matches {:year=>#<Post id: 1, title: "test", (...)>, :controller=>"posts", :action=>"show"}
    

    显然,它将@post对象传递给第一个路由参数(看起来像是Rails bug…)。但我能为我工作吗?我再加一句 default_url_options 是死胡同。

    解决方案只在Rails3.x中工作是可以的,但我不想使用任何插件。

    4 回复  |  直到 10 年前
        1
  •  6
  •   anshul    14 年前

    修理怎么样 url_for 对于 PostsController ?可能不是很优雅,但它是干的,事情应该只是工作。

    # app/controllers/posts_controller.rb 
    class PostsController < ApplicationController
    
      protected
    
        def url_for(options = {} )
          if options[:year].class.to_s == "Post"
            obj = options[:year]
            options[:year] = obj.year
            options[:month] = obj.month
            options[:slug] = obj.slug
          end
          super(options)
        end
    
    end
    
        2
  •  7
  •   Luke Francl    14 年前

    重写 to_param . 的默认值 托帕兰 是记录ID,但您可以更改它。

    class Post
      def to_param
        "/#{year}/#{month}/#{slug}"
      end
    end
    

    (这假设您在 Post 类用于 year , month slug )

    现在,当生成URL时,您的 至参数 将被调用。

    <%= link_to @post.title, @post %> 
        => <a href="/2010/02/foobar">Foobar</a>
    

    显然,您必须确保PostController显示操作可以根据传递的参数找到记录。

    您可能需要更改路由定义并删除此路由:

    map.post '/:year/:month/:slug, :controller => :posts, :action => :show
    

    但是,使用 托帕兰 重写,默认的restful post_path 对于您要生成的URL来说,将非常有效。

        3
  •  3
  •   Dancrumb    14 年前

    不幸的是,当您将ActiveRecord传递给 link_to 它尝试使用多态URL帮助器来生成链接的URL。

    routing_hash

    (:year => post.year, :month => post.month, :slug => post.slug)
    

        4
  •  0
  •   Chris Hobbs    10 年前

    class TempoDB::Series
      def self.model_name
        ActiveModel::Name.new(TempoDB::Series,nil,'series')
      end
      def to_param
        self.key
      end
    end