Permalink
Browse files

* Resolved GH issues #10 and #11 (cached_slug column protection and s…

…lug sequence caching).
  • Loading branch information...
1 parent f68f7c9 commit 6ec718bb9d90e2041aac0a2ddb8da9139cdb8808 @norman norman committed Oct 23, 2009
View
@@ -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:
View
@@ -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:
View
@@ -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"].
@@ -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'
@@ -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
@@ -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
View
@@ -1,5 +1,5 @@
# encoding: utf-8!
-# @paris.reload
+require "mocha"
require File.dirname(__FILE__) + '/test_helper'
@@ -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
View
@@ -1,3 +1,4 @@
class City < ActiveRecord::Base
+ attr_accessible :name
has_friendly_id :name, :use_slug => true, :cache_column => 'my_slug'
end
View
@@ -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

0 comments on commit 6ec718b

Please sign in to comment.