Rails routes for cms cms powered site - ruby-on-rails

I've been away from Rails for a while but I have a site that is running on rails where I have created a page editor. I need some help with my routes.
I want to have something like this for my URL on the front end of the site:
//domain/welcome/pagename/page or //domain/welcome/page/pagename
Then within the welcome_controller I have this:
def page
# I provide the user with the a page
#mypage = Contents.find_by_name(params[:pagename])
end
Then within the page view itself I can render aspects of the #mypage record as I see fit.
However, I need some help with the routes to get this all working the way I intend.
Currently, I have this for my welcome route:
resources :welcome do
collection do
get :site
get :home
get :page
get :thankyou
post :newslettersignup
post :sendcontact
end
end
I know that I need more... Just now sure exactly what it should be.
Any help would greatly be appreciated!

You can use non-resourceful routing to do this easily:
get '/welcome/:pagename/site', to: 'welcome#site'
get '/welcome/:pagename/home', to: 'welcome#home'
get '/welcome/:pagename/page', to: 'welcome#page'
get '/welcome/:pagename/thankyou', to: 'welcome#thankyou'
post '/welcome/:pagename/newslettersignup', to: 'welcome#newslettersignup'
post '/welcome/:pagename/sendcontact', to: 'welcome#sendcontact'
The :pagename syntax allows the value of that segment of the URL to be included in params[:pagename]. The to: 'welcome#site' bit means, "Route this to the WelcomeController#site action."
Please see Rails Routing from the Outside In for a great reference when working with routes.

Related

Rails 6 - change params for root_path in URL to SEO friendly URL

I know how to change routes when I'm calling some controller which name is in URL, but do not have idea what do with this:
Will_paginate:
http://localhost:3000/?page=4
and I want
http://localhost:3000/page/4
Route:
root to: 'pages#home_logged_in'
I'm not sure if will_paginate has the functionality to change the way it structures the links so you may need to calculate and display the page links manually in your views.
In the routes, you can setup a standard non-paginated route to handle the initial request and then a paginated route to handle individual pages.
get '/pages/:page', to: 'pages#index' # will pass params[:page]
root to: 'pages#index'
Then in the pages#index you just check for and apply the page param if it exists:
def index
page = params[:page] || 1
#items_being_paginated = ItemModel.paginate(page)
end
I've not used the will_paginate gem personally so the gem specific code is taken from their wiki.
Depending on what you're using this for -- if its just paginating items, for example -- the above should work for you. If you're trying to get SEO quality links for individual items you can using dynamic routing, like this:
get '*path', to: 'pages#show', as: 'pages_show'
or parameterized
get ':category/:sub_category', to: 'pages#index', as: 'sub_pages_index'
get ':category/:sub_category/pages/:page', to: 'pages#index', as: 'sub_paginated_pages_index'
get ':category/:sub_category/:item', to: 'pages#show', as: 'pages_show'
In the controller you just parse the route with the first, or use the params with the second.
This part of the Rails Routing Guide might interest you if you want more info.

Nested routes in rails

I am someone who has always liked sinatra better than rails, and has never had to do a large enough scale project that rails was required (all the sources I have read say that rails is better for larger scale projects) and now I do have to do a large scale project. I have gotten very confused with the url structure of rails. What I am trying to do is the rails equivalent of this:
get "/" do
erb :index
end
get "/home" do
erb :dashboard
end
get "/home/profile" do
erb :profile
end
get "/home/friends" do
erb :friends
end
In the first one I understand that I should put in app/routes.rb I should put root home#index and in the home controller I should put def index end.
In the second one, I understand that I should do the same except replacing index with home.
But for the third and forth ones I have no idea what to do.
Also, is the a RESTful way to do the first two?
You probably want something like this
root 'home#index'
get 'home' => 'home#dashboard'
get 'home/profile' => 'home#profile'
get 'home/friends' => 'home#friends'
remember to use the command rake routes to see all your routes, where they lead and what their names are (if they have any)
I never understood what RESTful means, so someone else will have to answer that part of your question.
K M Rakibul Islam has shown you what can be called a "resourceful" way to do routes (because it uses the keyword resources) but it looks like you're just doing the static pages at this stage, so it's not necessary.
The simplest way to do routes is with this formula:
method url => controller::action, as: route_name
where method can be get, post, patch or delete so you can have different actions linked to the same URL depending on the method the request uses.
Putting a name on the route is optional, but it gives you a clean way to use the route in your views (route_name_path)
When you start making models then you'll find that using the resources keyword comes in handy. Read about it.
You can have this:
resources :home do
collection do
get :profile
end
collection do
get :friends
end
end
end
This will give you routes like this:
profile_home_index GET /home/profile(.:format) home#profile
friends_home_index GET /home/friends(.:format) home#friends
The standard way of declaring the root path:
root 'home#index'
And for the 2nd one, you have to do:
get 'home' => 'home#dashboard'
which will give you this route:
GET /home(.:format) home#dashboard
One route can be defined in many ways that works. But, Rails has conventions that should be followed while defining routes in your Rails app.
I would highly recommend you to take a look at the Rails Routing Guide

Set Up Route for Accessing Private S3 Content

I've been following
https://github.com/thoughtbot/paperclip/wiki/Restricting-Access-to-Objects-Stored-on-Amazon-S3
and
Rails 3, paperclip + S3 - Howto Store for an Instance and Protect Access to try and get Paperclip's expiring links to work. I believe most of what I'm running into is one of the routing variety.
In my pieces_controller I put a method in like this
def download
redirect_to #asset.asset.expiring_url(1000)
end
And then in my routes, I put this:
match "pieces/download"
Then in my view I have:
<%= link_to download_asset_path(piece)%>
It would seem to be far from working, and I'm not sure what is messed up. I know I'm getting routing errors for one, but it's also telling me that my download_asset_path is undefined, which is likely also routing related... I feel like I'm doing everything all wrong.
Tearing my hair out. Thanks!
Try modifying your routes file to:
match 'pieces/download' => 'pieces#download', :as => 'download_asset'
Your match needs to tell which controller#action to go to, and the as option will allow you to name the route download_asset_path.
If your pieces controller is for a Piece resource it could be cleaner like:
resources :pieces do
member do
get :download
end
end
But then you would want to change the link to:
link_to 'Link text', download_piece_path(piece)
For further reading: http://guides.rubyonrails.org/routing.html

Simple routing error

Total noob question.
I am building a simple photoblog in Rails which consists of Posts. Each post has its own id "/posts/1". I built Posts using rails scaffolding.
The problem is that I am unable to go to a url such as "/posts/index" or "/posts/anything" because it's trying to match anything after "/posts/" it to an id... So I get back an error like:
Couldn't find Post with ID=index
I'm sure this could be fixed with routes, but I'm not really sure how and I feel that there is some big-picture problem I am missing here.
You can clone my app from here: https://github.com/tbhockey/PhotoBlog
Thank you.
Running rake routes is usually pretty helpful. In this case, the route to your index should just be /posts (not /posts/index). If you run rake routes you'll probably see something like
posts GET /posts(.:format) {:action=>"index", :controller=>"posts"}
That's trying to tell you that the URL /posts will be directed to the index action of your posts_controller. Also, this may be referred to in your code as posts_path or posts_url.
Try to do this for your routes.rb :
scope :path => '/posts', :controller => :posts do
get 'show/(:id)' => :show, :as => 'show_post'
end
For a /posts/show/1, it will call the show action of the posts controller.
It's always a nice idea to learn about how routing works in Rails. It's very important and will help you understand many things about Rails. Especially looking at named routes is vital for good Rails programming.

A very basic issue with routes in ruby

I am new to ruby and while creating a sample application found out an issue that whenever I go to http://127.0.0.1:3000/people/index by default show action is executed and index is taken as a parameter. This is server log:
Started GET "/people/index" for
127.0.0.1 at 2010-12-23 18:43:01 +0500 Processing by PeopleController#show as
HTML Parameters: {"id"=>"index"}
I have this in my route file:
root :to => "people#index"
resources :people
match ':controller(/:action(/:id(.:format)))'
What is going on here and how can I fix the issue?
The route
resources :people
creates "sub"-routes
get '/people' => 'people#index'
get '/people/new' => 'people#new'
post '/people' => 'people#create'
get '/people/:id' => 'people#show'
get '/people/:id/edit' => 'people#edit'
put '/people/:id' => 'people#update'
delete '/people/:id' => 'people#destroy'
Actually, all of these sub-routes include (.:format) at the end of the recognized path.
The path /people/index would be recognized by the route /people/:id, mapping to the action #show.
The path /people would be recognized by the route /people, mapping to the action #index.
Use the URL helpers people_path and people_url for the /people route.
To get Rails to travel backward in time to before it espoused REST and to understand /people/index, do this:
resources :people do
get :index => 'people#index'
end
You might want to watch this Railscast episode.
A couple things to keep in mind when working with your routes:
rake routes dumps the map of URLs to your controllers
When providing backwards compatibility, redirect the user to the correct path
I personally have yet to upgrade my app to Rails 3, and I'll be dragging my feet until I really need to do it (just got it out the door not too long ago). In Rails 2.x you had resource routes, but if you kept the default controller/action/id route it would fall through and resolve. It appears that is no longer the case in Rails 3. Essentially your resource routes handle all URLs in that resource namespace (/people in your case).
To provide backwards compatibility, I would add a redirect route to resolve that incompatibility.
match "/people/index", :to => redirect("/people")
The main reason for that is to prevent users from saving an incorrect URL for their personal links--while allowing legacy users to still be able to get where they meant to go.
Edit: New answer, removed pointing out the typo in the question.

Resources