paginate 'nested' rails routes for seo - ruby-on-rails

I need to figure out how to properly use routes to create a url structure like so:
items/page/2
items/expired/page/2
I have items/page/2 working and then I have this which I want to to correct:
items/expired?page=2
I am using Kaminari to provide pretty url structure for rails 4.2 with a concern.
https://github.com/amatsuda/kaminari/#creating-friendly-urls-and-caching
My controller has two actions: index and expired
My views under items are index.html.haml and expired.html.haml
routes.rb
concern :paginatable do
get '(page/:page)', :action => :index, :on => :collection, :as => ''
end
concern :expired_paginatable do
get '(page/:page)', :action => :expired, :on => :collection, :as => ''
end
get 'items/expired', to: "items#expired", :concerns => :expired_paginatable
resources :items, :concerns => :paginatable
my views both have:
= paginate #items
I know I do not need two concerns but thought I would try it.

I ended up changing my resources block to this:
resources :items do
collection do
get 'expired/page/:page', :action => :expired
get :expired
end
concerns :paginatable
end
dropping:
concern :expired_paginatable do
get '(page/:page)', :action => :expired, :on => :collection, :as => ''
end
get 'items/expired', to: "items#expired", :concerns => :expired_paginatable
resources :items, :concerns => :paginatable

Related

How to add custom URLs

How to add custom URLs like localhost:3000/one_hour/page/2 instead of localhost:3000/one_hour?page=2
to get '/one_hour', to: 'feed_entries#one_hour'
I use Rails 4, Kaminari and mongoid
routes.rb
Rails.application.routes.draw do
concern :paginatable do
get '(page/:page)', :action => :index, :on => :collection, :as => ''
end
resources :feed_entries, path: 'news', :concerns => :paginatable
get '/one_hour', to: 'feed_entries#one_hour'
end
feed_entries_controller.rb
class FeedEntriesController < ApplicationController
one_hour
#feed_entries = FeedEntry.includes(:source).one_hour.page(params[:page])
end
end
I found a solution:
in routes.rb
get 'one_hour/(page/:page)', controller: 'feed_entries', action: 'one_hour', to: 'feed_entries#one_hour', as: :one_hour

Can anyone help me with this code? I need to convert it to rails 4 but I don't know how..(routes.rb file from rails 2 to rails 4)

ActionController::Routing::Routes.draw do
map.resources :users, :sent
map.resources :mailbox, :collection => { :trash => :get }
map.resources :messages, :member => { :reply => :get, :forward => :get, :reply_all => :get, :undelete => :put }
map.resource :session
map.inbox '', :controller => "mailbox", :action => "index"
map.connect ':controller/:action/:id'
map.connect ':controller/:action/:id.:format'
end
I believe what you're looking for is this:
ActionController::Routing::Routes.draw do
root to: "mailbox#index"
resources :users
resources :sent
resources :mailbox do
collection do
get :trash
end
end
resources :messages do
member do
get :reply
get :forward
put :undelete
end
end
resource :session
end
The two connect routing definitions are no longer used in Rails, as they make all actions of all controllers available as GET requests. For instance, GET /users/1/destroy. If you find routes that that used to work are no longer working, you will need to define new routes in config/routes.rb for them.

In routes, match to #index does not work...why?

I'm setting up my website such that
www.website.com/articles/2013/07 will list all articles from 2013 in July and
www.website.com/articles/2013 will list all articles in 2013
www.website.com/articles/2013/07/title-of-article will list just the specific article
However, I am able to get only the first and last of the above 3 to work. Entering the url
www.website.com/articles/2013 is not working properly. Specifically, I get a noMethodError in Articles#show which doesn't make sense to me because I have matched the route to Articles#index.
Can someone please explain what's going on here? I don't see where I am making a mistake.
Routes:
match "/articles/:year", :to => "articles#index",
:constraints => { :year => /\d{4}/ }, :as=> :posts_year
match "/articles/:year/:month", :to => "articles#index",
:constraints => { :year => /\d{4}/, :month => /\d{1,2}/ }, :as => :posts_month
match "/articles/:year/:month/:slug", :to => "articles#show",
:constraints => { :year => /\d{4}/, :month => /\d{1,2}/, :slug => /[a-z0-9\-]+/ }, :as => :posts_date
and in my model I have:
def year
created_at.year
end
def month
created_at.strftime("%m")
end
Do you have resources :articles in your routes file? If you do, that explains the error. Move resources :articles below the routes you mentioned in your question and everything should work fine. Alternatively you could change it to:
resources :articles, :except => :show
Guessing that if you've defined articles as a resource, then the default show/:id route is taking precedence over your :posts_year route. Maybe try resources :articles, :except => [:show]

Rails 3 Routes: Override Topics#show with Posts#index

Pretty simple question, but I can't seem to figure out how to do this, even after scouring the Rails Routing guide.
Assume Topics has nested resource Posts.
The Posts for a Topic are all listed in Posts#index (/topics/:topic_id/messages). Topics#show does not serve any purpose. I would like Posts#index to be retrieved when the request is for /topics/:topic_id, without having to stick a redirect in the Topics controller.
Thank you!
UPDATE
I was able to get the desired result with this:
routes.rb
match 'forums/:forum_id' => 'topics#index', :as => 'forum_topics', :via => :get
match 'topics/:topic_id' => 'messages#index', :as => 'topic_messages', :via => :get
resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end
However, I'm not sure if this is the best method.
UPDATE 2
My method above breaks the other CRUD methods (like #create). Still looking for a solution to keep /messages out of the url.
add this route
get "/topics/:topic_id" => redirect("/topics/%{topic_id}/messages")
UPD
without redirecting:
get "/topics/:id" => "topic::Messages#index"
Or, if you're using shallow:
get "/topics/:id" => "messages#index"
resources :forums, :shallow => true, :except => :show do
resources :topics, :shallow => true, :except => :show do
resources :messages
end
end

How can I merge route declarations (subdomain or token)?

I have a model Model that can be access from many ways: by subdomain or a token
http://model1.domain.com
http://domain.com/j4h7
I have the following routes
resources :model, :constraints => {:model_id => /[a-zA-Z0-9]{4}/} do
... (nested resources...)
end
resources :model, :constraints => {:subdomain => /.+/} do
... (same as above: nested resources...)
end
So I currently have to duplicate all the routes for the two cases.
Is there any way to declare it only once?
def nested_routes
get :some_route
post :some route
resources :some_resources
end
resources :model, :constraints => {:model_id => /[a-zA-Z0-9]{4}/} do
nested_routes
end
resources :model, :constraints => {:subdomain => /.+/} do
nested_routes
end
Related topic: Rails 3 Routes: DRY members

Resources