How Rubycoders use FriendlyId gem
Cristiano - 2017-03-20
By default Ruby On Rails shows jobs advertisement published at Rubycoders with a progessive number, instead we want a better url representation using a slug.
We could create the solution by ourselves, but today we'll use the awesome FriendlyId to help us with this issue.
Add FriendlyId to your
and then install with
$ bundle install
In order to generate slugs for existing job records, we need to tell our FriendlyId when to generate the slugs, by adding this private method:
# app/models/job.rb private def should_generate_new_friendly_id? slug.nil? || title_changed? end
We're telling FriendlyId to generate new slugs when the slug is nil or the title has changed.
Let's add a migration for adding the slug attribute
$ rails generate migration add_slug_to_jobs
We could also generate the slugs as part of the migration, if we had existing job records.
class AddSlugToJobs < ActiveRecord::Migration def up add_column :jobs, :slug, :string add_index :jobs, :slug, unique: true say_with_time 'generating job slugs' do Job.find_each(&:save) end end def down remove_index :jobs, :slug remove_column :jobs, :slug end end
Calling save on the models triggers slug generation, so let's run the migration and see our slugs created:
$ rake db:migrate
Job model we add:
# app/models/job.rb extend FriendlyId friendly_id :title, use: :slugged
On the controller we use the
# app/controllers/companies_controller.rb class JobsController < ApplicationController def show @job = Job.friendly.find(params[:id]) end end
params[:id] is the job slug, rather than job id, the
friendly method makes the finder to look up jobs by slug, rather than id.
Pay attention with metaprogramming! After using FriendlyId I changed the controller for the favorite jobs. Favorite controller manage a polymorphic relation, so the
friendly method is not always present.
# app/controllers/favorites_controller.rb private def set_favorable @favorable = favorite_class.respond_to?(:friendly) ? favorite_class.friendly.find(params[:id]) : favorite_class.find(params[:id]) end