问题
I want to implement blog\news application with ability to:
- show all posts at root:
example.com/ - show all posts answering some year:
example.com/2012/ - show all posts answering some year and month:
example.com/2012/07/ - show some post by its date and slug:
example.com/2012/07/slug-of-the-post
So I have created a mockup for routes.rb file:
# 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\-]+/ }
So I should work with params in index action and just get post by slug in show action (checking whether date is corect is an option):
# 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
Also I have to implement to_param for my model:
def to_param
"#{created_at.year}/#{created_at.month}/#{slug}"
end
This is all I have learned from all night long searching in api/guides/SO.
But the problem is strange things keep happenning for me as new to rails:
When I go to
localhost/, the app breaks and says that it had invokedshowaction but first object in database had been recieved as :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">}When I go to
localhost/posts/2012/07/cut-testsame thing happens: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">}
I feel that there is something very easy that I haven't made, but I can't find what is it.
Anyway, this post will be helpful when it is solved, because there are solutions only for just slugs in url without date and similar but not useful questions.
回答1:
The problem was in post's path helper usage as post_path(post), because first parameter must be year since I use :as => :post in parametrized match in routes.rb.
Nevertheless, to make the entire solution clear here are some actions needed to make that all work proper:
You must add proper path helpers names for each match, e.g.
# Get /posts/2012/07/slug-of-the-post match "/posts/:year/:month/:slug", <...>, :as => :post_dateNow you can use
post_date_path("2012","12","end-of-the-world-is-near")in views.Same for
posts_path,posts_year_path("2012"),posts_month_path("2012","12")if properly named.I advice not to use neither
:as => :postin that match nor creatingto_paramin model file as it can break something you don't expect (asactive_adminfor me).Controller file
posts-controller.rbshould be filled with posts that needed extraction and checking of date's correctness before slug. Nevertheless in this state it is OK and breaks nothing.Model file
posts.rbshould be filled with year and month extraciton in proper format, e.g.:def year created_at.year end def month created_at.strftime("%m") endThere is no
to_parammethod really needed as I've noticed already.
回答2:
Is this your full routes.rb file? Sounds like you might have a preceding resources :posts entry, which basically matches /posts/:id. Also, there's nothing I can see from the routes file you posted that could be causing a redirect from the root path to posts, so it must be something else in there.
来源:https://stackoverflow.com/questions/11569876/rails-3-2-friendly-url-routing-by-date