Skip to content

Instantly share code, notes, and snippets.

@Overbryd
Created February 19, 2010 17:56
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save Overbryd/308983 to your computer and use it in GitHub Desktop.
Save Overbryd/308983 to your computer and use it in GitHub Desktop.
Implement Friendly Permalinks the easy way. Why you should think twice before even starting to implement something like this.
class Document < ActiveRecord::Base
after_save :update_permalink
def to_param
permalink.blank? ? id.to_s : permalink
end
private
def update_permalink
if permalink.blank? && !(title.blank? || isbn.blank?)
update_attribute(:permalink, "#{id}-#{title} #{isbn}".parameterize)
end
end
end
# SPECS
# Note: I am using blueprint for my 'Document' model. (gem install machinist)
describe "permalink" do
before :each do
@document = Document.make :title => 'I want to be in the permalink', :isbn => '978-5-2054-6661-5'
@expected_permalink = "#{@document.id}-i-want-to-be-in-the-permalink-9785205466615"
end
it "should set a permalink" do
@document.permalink.should eql(@expected_permalink)
end
it "should not change indirectly" do
@document.update_attribute(:title, 'Oh I changed my mind')
@document.reload.permalink.should eql(@expected_permalink)
@document.update_attribute(:isbn, Faker::Isbn.isbn_13)
@document.reload.permalink.should eql(@expected_permalink)
end
it "should not set a permalink if one of the permalink components is blank" do
@document = Document.make_unsaved(:title => '')
@document.save(false)
@document.permalink.should eql(nil)
@document = Document.make_unsaved(:isbn => '')
@document.save(false)
@document.permalink.should eql(nil)
end
it "should use the permalink in params" do
@document.to_param.should eql(@expected_permalink)
end
it "should use the id in params if no permalink is set" do
@document.permalink = nil
@document.to_param.should eql(@document.id.to_s)
end
it "should fetch a document the conventional way" do
# Hint: Rails is converting the given id attribute to an integer. This works because '123-whatever'.to_i evaluates as 123.
Document.find(@expected_permalink).should eql(@document)
Document.find_by_id(@expected_permalink).should eql(@document)
end
end
F**K FRIENDLY ID. Why did I ever believe in you?
Yes, it was my very own fault to install this piece of s**t.
To all other people wondering if they should install a gem to take care of friendly ids. Note that I use the term 'permalink' in the meaning of a 'nice looking permalink' or 'Friendly Permalink'.
* It is a bad decision to go with a solution on steroids (or from texas) if you just need to accomplish one simple thing: Nice looking urls that don't break your existing code.
* Versioned permalinks? Way too nerdy plus bad idea at all. If you fail to create a useful permalink in the first place, you should not even start to create permalinks.
There are some hardcore 2 % edge cases often related to a legacy codebase. Anyways, projects with such issues scream for a rewrite.
* Get Real! Think about your business case. Acceptance tests have shown that friendly permalinks are a luxury problem. Do you _really_ need to solve a luxury problem?
* 99% of users just care about the usefulness of your application, not about good looking URI's. The kind of persons (sorted by stupidity) who care are:
* Managers who think that the SEO guy is more worth than the developer
* Overpayed SEO guys
* Plain old Nitpicks
* Managers that don't listen to their developers
* 'Friendly Permalinks' have one bad aspect: They should be permanent and should never change. It _will_ cost you a lot of resources (time, money) migrating permalinks from old to new! Therefore think twice as much before implementing such a luxury thing. Use the simplest most lasting solution (IDS MAYBE???)
Talk to me if you feel uncomfortable with my write up. @Overbryd
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment