Skip to content

Commit bdfccd6

Browse files
committed
Merge pull request coderwall#222 from ddyy/protip-slugs
#372 Add Slug to Protip URLs for SEO
2 parents 23b29a0 + c9a523a commit bdfccd6

File tree

10 files changed

+48
-9
lines changed

10 files changed

+48
-9
lines changed

Gemfile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ gem 'acts_as_follower', '0.1.1'
107107
gem 'color'
108108
gem 'createsend'
109109
gem 'fog'
110+
gem 'friendly_id', '4.0.10.1'
110111
gem 'geocoder'
111112
gem 'hashie'
112113
gem 'linkedin'

Gemfile.lock

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,8 @@ GEM
261261
dotenv (~> 0.11.1)
262262
thor (~> 0.19.1)
263263
formatador (0.2.5)
264+
friendly_id (4.0.10.1)
265+
activerecord (>= 3.0, < 4.0)
264266
fssm (0.2.10)
265267
fukuzatsu (0.9.16)
266268
ephemeral
@@ -762,6 +764,7 @@ DEPENDENCIES
762764
flog
763765
fog
764766
foreman
767+
friendly_id (= 4.0.10.1)
765768
fukuzatsu
766769
fuubar (= 2.0.0.rc1)
767770
geocoder

app/assets/javascripts/backbone/routers/ProtipRouter.js.coffee

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,11 @@ window.ProtipRouter = Backbone.Router.extend(
44
'*path': 'closeProtip'
55

66
fetchProtip: (id)->
7-
if(id.match(/^[\dA-Z\-_]{6}$/i))
87
$.ajax '/p/' + id,
98
type: 'GET'
109
data:
1110
mode: 'popup'
1211
dataType: 'script'
13-
else
14-
@.closeProtip()
1512

1613
closeProtip: ->
1714
$('#x-active-preview-pane').remove()

app/controllers/protips_controller.rb

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,8 @@ def show
135135
end
136136

137137
return redirect_to protip_missing_destination, notice: "The pro tip you were looking for no longer exists" if @protip.nil?
138+
return redirect_to protip_path(@protip.public_id<<'/'<<@protip.friendly_id, :p => params[:p], :q => params[:q]) if params[:slug]!=@protip.friendly_id
139+
138140
@comments = @protip.comments
139141
@reply_to = show_params[:reply_to]
140142
@next_protip = Protip.search_next(show_params[:q], show_params[:t], show_params[:i], show_params[:p]) if is_admin?

app/models/protip.rb

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@
77
require 'search'
88

99
class Protip < ActiveRecord::Base
10+
extend FriendlyId
11+
friendly_id :slug_format, :use => :slugged
12+
1013
include Featurable
1114
# TODO: Break out the various responsibilities on the Protip into modules/concerns.
1215

@@ -951,7 +954,11 @@ def matching_jobs
951954
def to_html
952955
CFM::Markdown.render self.body
953956
end
954-
957+
958+
def slug_format
959+
"#{title}"
960+
end
961+
955962
protected
956963
def check_links
957964
errors[:body] << "one or more of the links are invalid or not publicly reachable/require login" unless valid_links?
@@ -969,7 +976,7 @@ def adjust_like_value(user, like_value)
969976
def analyze_spam
970977
AnalyzeSpamJob.perform_async({ id: id, klass: self.class.name })
971978
end
972-
979+
973980
end
974981

975982
# == Schema Information

config/routes.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -287,8 +287,9 @@
287287
get '/jobs(/:location(/:skill))' => 'opportunities#index', as: :jobs
288288
get '/jobs-map' => 'opportunities#map', as: :jobs_map
289289

290-
resources :protips, :path => '/p', :constraints => {id: /[\dA-Z\-_]{6}/i} do
290+
resources :protips, :path => '/p' do
291291
collection do
292+
get ':id/:slug' => 'protips#show', as: :slug, :constraints => {:slug => /(?!.*?edit).*/}
292293
get 'random'
293294
get 'search' => 'protips#search', as: :search
294295
post 'search' => 'protips#search'
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
class AddSlugToProtips < ActiveRecord::Migration
2+
def change
3+
add_column :protips, :slug, :string
4+
add_index :protips, :slug
5+
end
6+
end

db/schema.rb

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
#
1212
# It's strongly recommended to check this file into your version control system.
1313

14-
ActiveRecord::Schema.define(:version => 20140807214719) do
14+
ActiveRecord::Schema.define(:version => 20141015182230) do
1515

1616
add_extension "citext"
1717

@@ -254,9 +254,11 @@
254254
t.float "boost_factor", :default => 1.0
255255
t.integer "inappropriate", :default => 0
256256
t.integer "likes_count", :default => 0
257+
t.string "slug"
257258
end
258259

259260
add_index "protips", ["public_id"], :name => "index_protips_on_public_id"
261+
add_index "protips", ["slug"], :name => "index_protips_on_slug"
260262
add_index "protips", ["user_id"], :name => "index_protips_on_user_id"
261263

262264
create_table "purchased_bundles", :force => true do |t|

lib/tasks/generate_protip_slugs.rake

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
desc 'Generate slugs for existing protips'
2+
task :generate_protip_slugs => :environment do
3+
begin
4+
Protip.all.each do |pt|
5+
pt.save
6+
end
7+
rescue => e
8+
puts "Rake task protip slugs failed: #{e}"
9+
end
10+
end

spec/controllers/protips_controller_spec.rb

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,20 @@ def valid_session
4949
# end
5050
# end
5151

52-
describe "GET show" do
53-
it "assigns the requested protip as @protip" do
52+
describe "GET show using public_id" do
53+
it "redirects to GET show using slug" do
5454
protip = Protip.create! valid_attributes
55+
protip.save
5556
get :show, {id: protip.to_param}, valid_session
57+
expect(response).to redirect_to slug_protips_path(protip,protip.friendly_id)
58+
end
59+
end
60+
61+
describe "GET show using slug" do
62+
it "assigns the requested protip as @protip" do
63+
protip = Protip.create! valid_attributes
64+
protip.save
65+
get :show, {id: protip.public_id, slug: protip.friendly_id}, valid_session
5666
expect(assigns(:protip)).to eq(protip)
5767
end
5868
end

0 commit comments

Comments
 (0)