ruby-on-rails - Rails 3.2 按日期友好的 url 路由

标签 ruby-on-rails ruby-on-rails-3 url-routing

我想实现博客\新闻应用程序,并且能够:

  1. 显示根目录下的所有帖子:example.com/
  2. 显示回答某年的所有帖子:example.com/2012/
  3. 显示回答某个年份和月份的所有帖子:example.com/2012/07/
  4. 按日期和标题显示一些帖子: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\-]+/ }

因此,我应该在 index 操作中使用参数,并在 show 操作中通过 slug 进行发布(可以选择检查日期是否正确):

# 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

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

def to_param
  "#{created_at.year}/#{created_at.month}/#{slug}"
end

这就是我在 api/guides/SO 中彻夜搜索所学到的全部内容。

但问题是对于我这个 Rails 新手来说奇怪的事情不断发生:

  1. 当我转到 localhost/ 时,应用程序中断并表示它已调用 show 操作,但数据库中的第一个对象已被接收为 :year (原文如此!):

    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">}
    
  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">}
    

我觉得有一些很简单的东西我没有做过,但我找不到它是什么。

无论如何,当这个问题得到解决时,这篇文章将会很有帮助,因为只有针对没有日期的 url 中的 slugs 以及类似但没有用的问题的解决方案。

最佳答案

问题出在 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
    

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

    如果命名正确,posts_pathposts_year_path("2012")posts_month_path("2012","12") 也是如此。

    我建议不要在匹配中使用 :as => :post 也不在模型文件中创建 to_param 因为它可能会破坏你不期望的东西(如active_admin 对我来说)。

  2. Controller 文件 posts-controller.rb 应填充需要在 slug 之前提取和检查日期正确性的帖子。尽管如此,在这种状态下它还是可以的,不会破坏任何东西。

  3. 模型文件posts.rb应以正确的格式填写年份和月份提取物,例如:

    def year
      created_at.year
    end
    
    def month
      created_at.strftime("%m")
    end
    

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

关于ruby-on-rails - Rails 3.2 按日期友好的 url 路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11569876/

相关文章:

ruby-on-rails - 同一模型的 has_many 和 belongs_to

ruby-on-rails - 格式化 Rails 控制台输出

ruby-on-rails - 几乎真实世界应用程序的优秀 ruby​​ on rails 示例

ruby-on-rails - 有没有办法在 Rails 中搭建单例资源?

php - 包含文件无法正常工作 - url 路由

ruby-on-rails - 取消归档序列化模型时如何跳过载波 uploader 回调?

mysql - 很棒的嵌套集 - 如何获得任何子树的语句?

ruby-on-rails - 无需硬编码即可动态提取列名

php - .htaccess 从本地主机切换到远程服务器

javascript - Angular:根据服务方法调用设置路由