SamuraiBlue
SamuraiBlue

Reputation: 861

Rails: How to set the page title to URL (Routes)

I develop my Rails app on the Cloud9.

What I'd like to do is to set a part of title to the URL such as stackoverflow.

(e.g. example.com/part-of-tile-here)

Although I found the similar questions, I don't understand what I should do because some of them are old posts, links in the answer are not found. (e.g. Adding title to rails route)

I will not use Gem as yet.

It would be appreciated if you could give me any hint.

Upvotes: 0

Views: 1039

Answers (2)

Clemens Kofler
Clemens Kofler

Reputation: 1968

Generally, Ho Man is right but there are a few caveats to the proposed solution.

First of all, you should override the to_param method as well so it actually uses the slug:

# app/models/page.rb
def to_param
  slug
end

# ... which allows you to do this in views/controllers:
page_path(@page)
# instead of
page_path(@page.slug)

Second, you should use find_by!(slug: params[:id]) to 1) be up to date (find_by_xxx was deprecated in Rails 4.0 and removed from Rails 4.1) and 2) to replicate the behavior of find and raise an ActiveRecord::RecordNotFound error in case no post can be found for the given slug.

Third, I suggest to always keep the slug up to date and include the ID like so:

# app/models/page.rb
before_validation :set_slug

def to_param
  "#{id}-#{slug}"
end

private

def set_slug
  self.slug = title.parameterize
end

# ... which allows you to use the regular ActiveRecord find again because it just looks at the ID in this case:
@post = Post.find(params[:id]) # even if params[:id] is something like 1-an-example-post

If you care about search engine results, you should then also include the canonical URL in the <head> section and/or redirect with a 301 status in the controller to avoid duplicate content which search engines generally don't like:

# in the view
<%= tag(:link, rel: :canonical, href: page_url(@page)) %>

# and/or in the controller:
redirect_to(post_url(@post), status: 301) and return unless params[:id] == @post.to_param

Hope that helps.

Upvotes: 4

Ho Man
Ho Man

Reputation: 2345

Have a look at this Railscast which is roughly what you want.

tl;dr

You'll want to save a slug which is a parameterized title, delimited by - when you save the page. (In a before_validation or before_save)

For example, "Random Title Of Page" will get random-title-of-page generated as it's slug.

before_validation :generate_slug
def generate_slug
  self.slug ||= title.parameterize
end

In the page controller, you'll need to enable searching by slug.

def show
  @page = Page.find_by_slug(params[:id])
end

Upvotes: 2

Related Questions