Rails 3.2友好的URL按日期路由

iEu*_*ene 5 ruby-on-rails url-routing ruby-on-rails-3

我想实现具有以下能力的blog \news应用程序:

  1. 显示root的所有帖子: example.com/
  2. 显示所有回答某些年份的帖子: example.com/2012/
  3. 显示所有回答某些年份和月份的帖子: example.com/2012/07/
  4. 按日期和slug显示一些帖子: example.com/2012/07/slug-of-the-post

所以我为routes.rb文件创建了一个模型:

# GET /?page=1
root :to => "posts#index"

match "/posts" => redirect("/")
match "/posts/" => redirect("/")

# Get /posts/2012/?page=1
match "/posts/:year", :to => "posts#index",
  :constraints => { :year => /\d{4}/ }

# Get /posts/2012/07/?page=1
match "/posts/:year/:month", :to => "posts#index",
  :constraints => { :year => /\d{4}/, :month => /\d{1,2}/ }

# Get /posts/2012/07/slug-of-the-post
match "/posts/:year/:month/:slug", :to => "posts#show", :as => :post,
  :constraints => { :year => /\d{4}/, :month => /\d{1,2}/, :slug => /[a-z0-9\-]+/ }
Run Code Online (Sandbox Code Playgroud)

所以我应该在index行动中使用params,然后通过slug in showaction(检查日期是否为corect是一个选项)来发布:

# GET /posts?page=1
def index
  #render :text => "posts#index<br/><br/>#{params.to_s}"
  @posts = Post.order('created_at DESC').page(params[:page])
  # sould be more complicated in future
end

# GET /posts/2012/07/19/slug
def show
  #render :text => "posts#show<br/><br/>#{params.to_s}"
  @post = Post.find_by_slug(params[:slug])
end
Run Code Online (Sandbox Code Playgroud)

我还必须to_param为我的模型实现:

def to_param
  "#{created_at.year}/#{created_at.month}/#{slug}"
end
Run Code Online (Sandbox Code Playgroud)

这是我从api/guides/SO中彻夜搜索的所有知识.

但问题是奇怪的事情一直在发生在我身上作为铁杆的新手:

  1. 当我去localhost/,应用程序中断并说它已经调用了show动作,但数据库中的第一个对象已被收到:year(sic!):

    No route matches {:controller=>"posts", :action=>"show", :year=>#<Post id: 12, slug: "*", title: "*", content: "*", created_at: "2012-07-19 15:25:38", updated_at: "2012-07-19 15:25:38">}
    
    Run Code Online (Sandbox Code Playgroud)
  2. 当我localhost/posts/2012/07/cut-test发生同样的事情时:

    No route matches {:controller=>"posts", :action=>"show", :year=>#<Post id: 12, slug: "*", title: "*", content: "*", created_at: "2012-07-19 15:25:38", updated_at: "2012-07-19 15:25:38">}
    
    Run Code Online (Sandbox Code Playgroud)

我觉得我有一些非常容易的东西,但我找不到它是什么.

无论如何,这篇文章在解决后会有所帮助,因为只有针对url的解决方案才有解决方案,没有日期和相似但没有用的问题.

iEu*_*ene 5

问题出在post的路径助手用法中post_path(post),因为我:as => :post参数化匹配中使用的第一个参数必须是年份routes.rb.

尽管如此,要使整个解决方案清晰明确,还需要采取一些措施来使所有工作正常运行:

  1. 您必须为每个匹配添加正确的路径助手名称,例如

    # Get /posts/2012/07/slug-of-the-post
    match "/posts/:year/:month/:slug", <...>,
      :as => :post_date
    
    Run Code Online (Sandbox Code Playgroud)

    现在您可以post_date_path("2012","12","end-of-the-world-is-near")在视图中使用.

    同为posts_path,posts_year_path("2012"),posts_month_path("2012","12")如果正确命名.

    我建议不要:as => :post在那场比赛中使用也不要to_param在模型文件中创建,因为它可能会破坏你不期望的东西(就active_admin我而言).

  2. 控制器文件posts-controller.rb应填充需要提取的帖子,并在slug之前检查日期的正确性.然而,在这种状态下它是可以的,什么都不打破.

  3. 模型文件posts.rb应以适当的格式填写年份和月份,例如:

    def year
      created_at.year
    end
    
    def month
      created_at.strftime("%m")
    end
    
    Run Code Online (Sandbox Code Playgroud)

    to_param我已经注意到,没有真正需要的方法.