6

私のウェブサイトに次のようなURLを設定したいのですが。

example.com/2010/02/my-first-post

フィールド(「my-first-post」)とフィールド(URLの年と月の部分を差し引く)を持つPostモデルがあります。slugpublished_on

PostモデルをRESTfulにしたいので、たとえば、url_for(@post)前述のURLを生成する必要があります。

これを行う方法はありますか?オプションをオーバーライドto_paramして設定する必要があることはわかっていますが、すべてを機能させることはできません。map.resources :posts:requirements


私はそれをほぼ完了しました、私はそこに90%います。resource_hacksプラグインを使用して、これを実現できます。

map.resources :posts, :member_path => '/:year/:month/:slug',
  :member_path_requirements => {:year => /[\d]{4}/, :month => /[\d]{2}/, :slug => /[a-z0-9\-]+/}

rake routes
(...)
post GET    /:year/:month/:slug(.:format)      {:controller=>"posts", :action=>"show"}

とビューで:

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

example.com/2010/02/my-first-post適切なリンクを生成します。

私もこれを機能させたいです:

<%= link_to 'post', post_path(@post) %>

to_paramただし、モデルのメソッドをオーバーライドする必要があります。私が望むようにではなく、それto_paramが戻らなければならないという事実を除いて、かなり簡単なはずです。StringHash

class Post < ActiveRecord::Base
  def to_param
   {:slug => 'my-first-post', :year => '2010', :month => '02'}
  end
end

エラーが発生しcan't convert Hash into Stringます。

これは無視されているようです:

def to_param
  '2010/02/my-first-post'
end

エラーが発生するため: post_url failed to generate from {:action=>"show", :year=>#<Post id: 1, title: (...)(@postオブジェクトを:yearキーに誤って割り当てます)。私はそれをハックする方法についてちょっと無知です。

4

5 に答える 5

4

Rails3.xとRails2.xのきれいなURLで、外部プラグインは必要ありませんが、残念ながら少しハックがあります。

ルート.rb

map.resources :posts, :except => [:show]
map.post '/:year/:month/:slug', :controller => :posts, :action => :show, :year => /\d{4}/, :month => /\d{2}/, :slug => /[a-z0-9\-]+/

application_controller.rb

def default_url_options(options = {})
  # resource hack so that url_for(@post) works like it should
  if options[:controller] == 'posts' && options[:action] == 'show'
    options[:year] = @post.year
    options[:month] = @post.month
  end
  options
end

post.rb

def to_param # optional
  slug
end

def year
  published_on.year
end

def month
  published_on.strftime('%m')
end

見る

<%= link_to 'post', @post %>

Rails 3.xの場合、次のルート定義を使用することをお勧めします。

resources :posts
match '/:year/:month/:slug', :to => "posts#show", :as => :post, :year => /\d{4}/, :month => /\d{2}/, :slug => /[a-z0-9\-]+/

自分の質問に答えるためのバッジはありますか?;)

ところで:routing_testファイルは、Railsルーティングで何ができるかを確認するのに適した場所です。

更新:使用default_url_options行き止まりです。投稿されたソリューション@postは、コントローラーに変数が定義されている場合にのみ機能します。たとえば、@posts投稿の配列を持つ変数がある場合、運が悪いです(のように、default_url_options変数を表示するためのアクセス権がないためです。p@posts.each do |p|

したがって、これは未解決の問題です。誰か助けますか?

于 2010-02-14T18:06:26.887 に答える
4

それはまだハックですが、次のように機能します。

application_controller.rb

def url_for(options = {})
  if options[:year].class.to_s == 'Post'
    post = options[:year]
    options[:year] = post.year
    options[:month] = post.month
    options[:slug] = post.slug
  end
  super(options)
end

そして、以下が機能します(Rails 2.3.xと3.0.0の両方で):

url_for(@post)
post_path(@post)
link_to @post.title, @post
etc.

これは、私の同様の質問に対するいくつかの素晴らしい魂からの答えです。カスタムRESTfulリソース(複合キー。IDだけでなく)のurl_forです

于 2010-02-24T17:23:07.170 に答える
1

Ryan Batesは、スクリーンキャストで、「カスタムルートを追加する方法、一部のパラメーターをオプションにする方法、および他のパラメーターの要件を追加する方法」について説明しました。 http://railscasts.com/episodes/70-custom-routes

于 2010-02-13T20:50:34.053 に答える
1

これは役立つかもしれません。URLヘルパーに渡されたオプションのハッシュを受け取り、それらのURLに使用する追加オプションのハッシュを返すdefault_url_optionsメソッドをで定義できます。ApplicationController

投稿がパラメータとしてに指定されている場合、その投稿はpost_pathルートの最初の(割り当てられていない)パラメータに割り当てられます。テストはしていませんが、機能する可能性があります。

def default_url_options(options = {})
  if options[:controller] == "posts" && options[:year].is_a?Post
    post = options[:year]
    {
      :year  => post.created_at.year,
      :month => post.created_at.month,
      :slug  => post.slug
    }
  else
    {}
  end
end

私は同様の状況にあり、投稿には言語パラメーターとスラッグパラメーターがあります。書き込みにより、このハッシュがメソッドpost_path(@post)に送信されます。default_url_options

{:language=>#<Post id: 1, ...>, :controller=>"posts", :action=>"show"}

更新:そのメソッドからURLパラメーターをオーバーライドできないという問題があります。URLヘルパーに渡されるパラメーターが優先されます。したがって、次のようなことができます。

post_path(:slug => @post)

と:

def default_url_options(options = {})
  if options[:controller] == "posts" && options[:slug].is_a?Post
    {
      :year  => options[:slug].created_at.year,
      :month => options[:slug].created_at.month
    }
  else
    {}
  end
end

これはPost.to_param、ナメクジを返却した場合に機能します。ハッシュに年と月を追加するだけで済みます。

于 2010-02-13T22:18:44.237 に答える
1

ストレスを解消して、friendly_idを使用することができます。その素晴らしい、仕事をします、そしてあなたは始めるためにライアンベイツによるスクリーンキャストを見ることができました。

于 2012-01-12T00:50:07.533 に答える