Reputation: 2369
I'm trying to implement semi-static pages as per this railscast
At first I named my class 'About', but that threw the following error:
Invalid route name, already in use: 'page' (ArgumentError)
You may have defined two routes with the same name using the :as
option, or you may be overriding a route already defined by a resource with the same naming.
After some googleing, it seemed like it was conflicted with active_admin for some reason, so I rename the table to 'Page' and I've carefully renamed all the appropriate files, classes and methods etc. from 'About' to 'Page'
This is my Page model:
class Page < ActiveRecord::Base
validates_uniqueness_of :url
def to_param
url
end
end
And these are my routes:
get 'signup', to: 'users#new', as: 'signup'
get 'login', to: 'sessions#new', as: 'login'
get 'logout', to: 'sessions#destroy', as: 'logout'
devise_for :admin_users, ActiveAdmin::Devise.config
ActiveAdmin.routes(self)
resources :users
resources :sessions
resources :password_resets
resources :posts do
resources :comments
resources :votes, only: [:new, :create]
resources :flags, only: [:new, :create]
end
resources :comments do
resources :comments
resources :votes, only: [:new, :create]
resources :flags, only: [:new, :create]
end
resources :newsletters
resources :pages, except: :show
resources :subscribers, only: [:index, :new, :create]
# resources :prelaunch
# get 'about', to: 'prelaunch#about'
root to: 'posts#index'
get ':id', to: 'pages#show', as: :page
I'm still getting the same error as described above.
The only way I can get it to half-work is by dropping the 'as: :page' bit, which stops the conflict, and hardcoding the url I want to point to into the code e.g.
<%= link_to page.name, "localhost:3000/#{page.url}" %>
which is far from ideal.
I can't find any help in Routing from the Outside In.
Could anyone help?
Upvotes: 1
Views: 291
Reputation: 2369
Ok, after a lot of hacking around and a helpful pointer from Rich Peck, I've got a working solution.
Routes:
resources :pages, except: :show
if Page.all.any?
Page.all.each do |page|
get "#{page.url}", to: "pages#show", as: "#{page.url}", id: page.id
end
end
Controller:
def show
@page = Page.find(params[:id])
end
Note, I've used the friendly_id gem as suggested.
To dynamically generate links:
Application controller:
def about_us
@pages = Page.all
end
helper_method :about_us
Pages helper:
def about_link(page)
link_to page.name, "/#{page.url}"
end
NB: - you need to include the / otherwise it will try to prepend the name of the controller for the page you're on (I'm not sure why).
My footer:
<% about_us.each do | page | %>
<%= about_link(page) %>
<% end %>
UPDATE:
I've had a lot of trouble deploying my app to Heroku, and I believe it's because of the pages routes.
I've now changed to a much simpler solution:
resources :pages, path: ""
and the problem's have gone away.
Upvotes: 1
Reputation: 6025
Have you considered using a gem that "does the work for you"? I've been using the https://github.com/thoughtbot/high_voltage gem to take care of static pages for me, without any hassle. It takes care of both routing and controller, only leaving the creation of the pages in a dedicated view/pages folder. Linking to a static page is as simple as creating a link to page_path(:name_of_the_page)
Upvotes: 1
Reputation: 76784
Here's the fix:
#config/routes.rb
resources :pages, except: :show
(remove get ':id', to: 'pages#show', as: :page
)
This will create the standard RESTful routes, which will create a routing structure except the show action
Slugs
How to create app-wide slug routing for Rails app?
If you want to have /about
etc, you'll have to generate them specifically:
#config/routes.rb
if Page.all.any?
Page.all.each do |page|
get page, to: "pages#show", id: page.id
end
end
This can also be handled with friendly_id
Upvotes: 1