Skip to content

Commit

Permalink
* Resolved GH issues norman#10 and norman#11 (cached_slug column prot…
Browse files Browse the repository at this point in the history
…ection and slug sequence caching).
  • Loading branch information
norman committed Oct 23, 2009
1 parent f68f7c9 commit 6ec718b
Show file tree
Hide file tree
Showing 8 changed files with 47 additions and 15 deletions.
6 changes: 6 additions & 0 deletions History.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
== 2.2.1 2009-10-23

* 2 minor enhancements:
* slug cache now properly caches the slug sequence (closes GH issue #10)
* attr_protected is now only invoked on the cached_slug column if attr_accessible has not already been invoked. (closes GH issue #11)

== 2.2.0 2009-10-19

* 1 major enhancement:
Expand Down
15 changes: 11 additions & 4 deletions README.rdoc
Original file line number Diff line number Diff line change
Expand Up @@ -172,12 +172,19 @@ Then, redo the slugs:

rake friendly_id:redo_slugs MODEL=User

This feature exists largely to improve the performance of URL
generation, the part of Rails where FriendlyId has the biggest
performance impact. FriendlyId never queries against this column, so
it's not necessary to add an index on it unless your application does.

Two warnings when using this feature:

*DO NOT* forget to redo the slugs, or else this feature will not work!

Also note that this feature exists largely to improve the performance of URL
generation, the part of Rails where FriendlyId has the biggest performance
impact. FriendlyId never queries against this column, so it's not necessary to
add an index on it unless your application does.
Also, this feature uses +attr_protected+ to protect the cached_slug
column, unless you have already invoked +attr_accessible+. So if you
wish to use +attr_accessible+, you must invoke it BEFORE you invoke
+has_friendly_id+ in your class.

==== Using a custom column name:

Expand Down
6 changes: 4 additions & 2 deletions lib/friendly_id.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ module ClassMethods
# Options:
# * <tt>:use_slug</tt> - Defaults to false. Use slugs when you want to use a non-unique text field for friendly ids.
# * <tt>:max_length</tt> - Defaults to 255. The maximum allowed length for a slug.
# * <tt>:cache_column</tt> - Defaults to nil. Use this column as a cache for generating to_param (experimental).
# * <tt>:cache_column</tt> - Defaults to nil. Use this column as a cache for generating to_param (experimental) Note that if you use this option, any calls to +attr_accessible+ must be made BEFORE any calls to has_friendly_id in your class.
# * <tt>:strip_diacritics</tt> - Defaults to false. If true, it will remove accents, umlauts, etc. from western characters.
# * <tt>:strip_non_ascii</tt> - Defaults to false. If true, it will all non-ascii ([^a-z0-9]) characters.
# * <tt>:reserved</tt> - Array of words that are reserved and can't be used as friendly_id's. For sluggable models, if such a word is used, it will raise a FriendlyId::SlugGenerationError. Defaults to ["new", "index"].
Expand Down Expand Up @@ -79,11 +79,13 @@ def has_friendly_id(column, options = {}, &block)
extend SluggableClassMethods
include SluggableInstanceMethods
before_save :set_slug
after_save :set_slug_cache
if block_given?
write_inheritable_attribute :slug_normalizer_block, block
end
if options[:cache_column]
attr_protected options[:cache_column].to_sym
# only protect the column if the class is not already using attributes_accessible
attr_protected options[:cache_column].to_sym unless accessible_attributes
end
else
require 'friendly_id/non_sluggable_class_methods'
Expand Down
14 changes: 8 additions & 6 deletions lib/friendly_id/sluggable_instance_methods.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,12 +118,14 @@ def set_slug
# If we're renaming back to a previously used friendly_id, delete the
# slug so that we can recycle the name without having to use a sequence.
slugs.find(:all, :conditions => {:name => slug_text, :scope => scope}).each { |s| s.destroy }
slug = slugs.build slug_attributes
if cache = friendly_id_options[:cache_column]
new_slug = slug.to_friendly_id
send("#{cache}=", new_slug) unless send(cache) == new_slug
end
slug
slugs.build slug_attributes
end
end

def set_slug_cache
if friendly_id_options[:cache_column] && send(friendly_id_options[:cache_column]) != slug.to_friendly_id
send "#{friendly_id_options[:cache_column]}=", slug.to_friendly_id
send :update_without_callbacks
end
end

Expand Down
2 changes: 1 addition & 1 deletion lib/friendly_id/version.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module FriendlyId #:nodoc:
module Version #:nodoc:
MAJOR = 2
MINOR = 2
TINY = 0
TINY = 1
STRING = [MAJOR, MINOR, TINY].join('.')
end
end
17 changes: 15 additions & 2 deletions test/cached_slug_test.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# encoding: utf-8!
# @paris.reload
require "mocha"

require File.dirname(__FILE__) + '/test_helper'

Expand Down Expand Up @@ -29,9 +29,22 @@ class CachedSlugModelTest < Test::Unit::TestCase
should "protect the cached slug value" do
@paris.update_attributes(:my_slug => "Madrid")
@paris.reload
assert_equal("paris", @paris.my_slug)
assert_equal "paris", @paris.my_slug
end

should "cache the incremented sequence for duplicate slug names" do
@paris2 = City.create!(:name => "Paris")
assert_equal 2, @paris2.slug.sequence
assert_equal "paris--2", @paris2.my_slug
end

should "not update the cached slug column if it has not changed" do
@paris.population = 10_000_000
@paris.expects(:my_slug=).never
@paris.save
end


context "found by its friendly id" do

setup do
Expand Down
1 change: 1 addition & 0 deletions test/models/city.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
class City < ActiveRecord::Base
attr_accessible :name
has_friendly_id :name, :use_slug => true, :cache_column => 'my_slug'
end
1 change: 1 addition & 0 deletions test/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@

create_table "cities", :force => true do |t|
t.column "name", "string"
t.column "population", "integer"
t.column "my_slug", "string"
end

Expand Down

0 comments on commit 6ec718b

Please sign in to comment.