friendly_id 2.2.5 → 2.2.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,8 +1,21 @@
1
+ == 2.2.6 2009-12-10
2
+
3
+ * 2 major fixes
4
+ * Made cached_slug automagic configuration occur outside of has_friendly_id. This was causing problems
5
+ in code where the class is loaded before ActiveRecord has established its connection.
6
+ * Fixes for scope feature with Postgres (Ben Woosley)
7
+
8
+ * 2 minor enhancements
9
+ * Migrated away from Hoe/Newgem for gem management.
10
+ * Made tests database-agnostic (Ben Woosley)
11
+
1
12
  == 2.2.5 2009-11-30
13
+
2
14
  * 1 minor fix
3
15
  * Fixed typo which in config options (Steven Noble).
4
16
 
5
17
  == 2.2.4 2009-11-12
18
+
6
19
  * 1 minor fix
7
20
  * Fixed typo in post-install message.
8
21
 
File without changes
@@ -12,9 +12,8 @@ instead of:
12
12
 
13
13
  http://example.com/states/4323454
14
14
 
15
- Want to find out more? Read on. The {most recent version of the FriendlyId
16
- RDocs}[http://friendly-id.rubyforge.org] can always be found on
17
- Rubyforge[http://www.rubyforge.org].
15
+ You can always read the latest version of this document at the {friendly_id page on
16
+ rdoc.info}[http://rdoc.info/projects/norman/friendly_id].
18
17
 
19
18
  === Why?
20
19
 
@@ -294,8 +293,7 @@ discouraged:
294
293
  == Setting it up
295
294
 
296
295
  The current release works with Rails 2.2 and above, and is compatible with
297
- Ruby 1.8 and 1.9. If you need support for Rails 2.0 - 2.1, you need to install
298
- an older version of FriendlyId. Here's how to set it up.
296
+ Ruby 1.8 and 1.9.
299
297
 
300
298
  1) Install the Gem:
301
299
 
@@ -363,6 +361,7 @@ particular from the following people:
363
361
  * Adam Cigánek
364
362
  * Alistair Holt
365
363
  * Andrew Loe III
364
+ * Ben Woosley
366
365
  * Bence Nagy
367
366
  * Bruno Michel
368
367
  * Chris Nolan
@@ -378,6 +377,7 @@ particular from the following people:
378
377
  * Rob Ingram
379
378
  * Sean Abrahams
380
379
  * Steve Luscher
380
+ * Steven Noble
381
381
  * Tim Kadom
382
382
 
383
383
  Copyright (c) 2008 Norman Clarke, Adrian Mugnolo and Emilio Tagua, released
data/Rakefile CHANGED
@@ -1,46 +1,35 @@
1
- require 'newgem'
2
- require 'hoe'
3
- require 'lib/friendly_id/version'
4
- require 'hoe'
5
-
6
- Hoe.spec "friendly_id" do
7
- self.version = FriendlyId::Version::STRING
8
- self.rubyforge_name = "friendly-id"
9
- self.author = ['Norman Clarke', 'Adrian Mugnolo', 'Emilio Tagua']
10
- self.email = ['norman@njclarke.com', 'adrian@mugnolo.com', 'miloops@gmail.com']
11
- self.summary = "A comprehensive slugging and pretty-URL plugin for ActiveRecord."
12
- self.description = 'A comprehensive slugging and pretty-URL plugin for Rails apps using ActiveRecord.'
13
- self.url = 'http://friendly-id.rubyforge.org/'
14
- self.test_globs = ['test/**/*_test.rb']
15
- self.extra_deps << ['activerecord', '>= 2.2.3']
16
- self.extra_deps << ['activesupport', '>= 2.2.3']
17
- self.extra_dev_deps << ['newgem', ">= #{::Newgem::VERSION}"]
18
- self.extra_dev_deps << ['sqlite3-ruby']
19
- self.remote_rdoc_dir = ""
20
- self.readme_file = "README.rdoc"
21
- self.extra_rdoc_files = ["README.rdoc"]
22
- self.post_install_message = <<-EOM
23
-
24
- ***********************************************************
25
-
26
- If you are upgrading friendly_id, please run
27
-
28
- ./script/generate friendly_id --skip-migration
29
-
30
- in your Rails application to ensure that you have the
31
- latest friendly_id Rake tasks.
32
-
33
- ***********************************************************
34
-
35
- EOM
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/rdoctask'
5
+ require 'rake/clean'
6
+
7
+ CLEAN << "pkg" << "docs" << "coverage"
8
+
9
+ task :default => :test
10
+
11
+ Rake::TestTask.new(:test) { |t| t.pattern = 'test/**/*_test.rb' }
12
+ Rake::GemPackageTask.new(eval(File.read("friendly_id.gemspec"))) { |pkg| }
13
+ Rake::RDocTask.new do |r|
14
+ r.rdoc_dir = "docs"
15
+ r.main = "README.rdoc"
16
+ r.rdoc_files.include "README.rdoc", "History.txt", "lib/**/*.rb"
36
17
  end
37
18
 
38
- require 'newgem/tasks'
19
+ begin
20
+ require "yard"
21
+ YARD::Rake::YardocTask.new do |t|
22
+ t.options = ["--output-dir=docs"]
23
+ end
24
+ rescue LoadError
25
+ end
39
26
 
40
- desc 'Publish RDoc to RubyForge.'
41
- task :publish_docs => [:clean, :docs] do
42
- host = "compay@rubyforge.org"
43
- remote_dir = "/var/www/gforge-projects/friendly-id"
44
- local_dir = 'doc'
45
- sh %{rsync -av --delete #{local_dir}/ #{host}:#{remote_dir}}
27
+ begin
28
+ require 'rcov/rcovtask'
29
+ Rcov::RcovTask.new do |r|
30
+ r.test_files = FileList['test/*_test.rb']
31
+ r.verbose = true
32
+ r.rcov_opts << "--exclude gems/*"
33
+ end
34
+ rescue LoadError
46
35
  end
@@ -0,0 +1,3 @@
1
+ These templates are here to generate FriendlyId-enabled Rails apps for
2
+ testing. They are for developers, they are not intended for generating
3
+ "real" applications.
@@ -0,0 +1,26 @@
1
+ run "rm public/index.html"
2
+ gem "friendly_id"
3
+ gem "haml"
4
+ gem "will_paginate"
5
+ run "haml --rails ."
6
+ generate "friendly_id"
7
+ generate :haml_scaffold, "post title:string"
8
+ route "map.root :controller => 'posts', :action => 'index'"
9
+ rake "db:migrate"
10
+ rake "db:fixtures:load"
11
+ file 'app/models/post.rb',
12
+ %q{class Post < ActiveRecord::Base
13
+ has_friendly_id :title, :use_slug => true
14
+ end}
15
+ file 'test/fixtures/slugs.yml',
16
+ %q{
17
+ one:
18
+ name: mystring
19
+ sequence: 1
20
+ sluggable: one (Post)
21
+
22
+ two:
23
+ name: mystring
24
+ sequence: 2
25
+ sluggable: two (Post)
26
+ }
@@ -0,0 +1,28 @@
1
+ run "rm public/index.html"
2
+ inside 'vendor/plugins' do
3
+ run "git clone ../../../../ friendly_id"
4
+ end
5
+ gem "haml"
6
+ gem "will_paginate"
7
+ run "haml --rails ."
8
+ generate "friendly_id"
9
+ generate :haml_scaffold, "post title:string"
10
+ route "map.root :controller => 'posts', :action => 'index'"
11
+ rake "db:migrate"
12
+ rake "db:fixtures:load"
13
+ file 'app/models/post.rb',
14
+ %q{class Post < ActiveRecord::Base
15
+ has_friendly_id :title, :use_slug => true
16
+ end}
17
+ file 'test/fixtures/slugs.yml',
18
+ %q{
19
+ one:
20
+ name: mystring
21
+ sequence: 1
22
+ sluggable: one (Post)
23
+
24
+ two:
25
+ name: mystring
26
+ sequence: 2
27
+ sluggable: two (Post)
28
+ }
@@ -70,6 +70,6 @@ module FriendlyId
70
70
  end
71
71
  end
72
72
 
73
- class ActiveRecord::Base
74
- extend FriendlyId
73
+ class ActiveRecord::Base #:nodoc:#
74
+ extend FriendlyId #:nodoc:#
75
75
  end
@@ -5,7 +5,7 @@ module FriendlyId::NonSluggableClassMethods
5
5
  protected
6
6
 
7
7
  def find_one(id, options) #:nodoc:#
8
- if id.is_a?(String) && result = send("find_by_#{ friendly_id_options[:method] }", id, options)
8
+ if id.respond_to?(:to_str) && result = send("find_by_#{ friendly_id_options[:method] }", id.to_str, options)
9
9
  result.send(:found_using_friendly_id=, true)
10
10
  else
11
11
  result = super id, options
@@ -15,9 +15,10 @@ module FriendlyId::NonSluggableClassMethods
15
15
 
16
16
  def find_some(ids_and_names, options) #:nodoc:#
17
17
 
18
+ names, ids = ids_and_names.partition {|id_or_name| id_or_name.respond_to?(:to_str) && id_or_name.to_str }
18
19
  results = with_scope :find => options do
19
- find :all, :conditions => ["#{quoted_table_name}.#{primary_key} IN (?) OR #{friendly_id_options[:method].to_s} IN (?)",
20
- ids_and_names, ids_and_names]
20
+ find :all, :conditions => ["#{quoted_table_name}.#{primary_key} IN (?) OR #{friendly_id_options[:method]} IN (?)",
21
+ ids, names]
21
22
  end
22
23
 
23
24
  expected = expected_size(ids_and_names, options)
@@ -25,7 +26,7 @@ module FriendlyId::NonSluggableClassMethods
25
26
  raise ActiveRecord::RecordNotFound, "Couldn't find all #{ name.pluralize } with IDs (#{ ids_and_names * ', ' }) AND #{ sanitize_sql options[:conditions] } (found #{ results.size } results, but was looking for #{ expected })"
26
27
  end
27
28
 
28
- results.each {|r| r.send(:found_using_friendly_id=, true) if ids_and_names.include?(r.friendly_id)}
29
+ results.each {|r| r.send(:found_using_friendly_id=, true) if names.include?(r.friendly_id)}
29
30
 
30
31
  results
31
32
 
@@ -6,6 +6,7 @@ module FriendlyId::SluggableClassMethods
6
6
  def find_one(id_or_name, options) #:nodoc:#
7
7
 
8
8
  scope = options.delete(:scope)
9
+ scope = scope.to_param if scope && scope.respond_to?(:to_param)
9
10
 
10
11
  if id_or_name.is_a?(Integer) || id_or_name.kind_of?(ActiveRecord::Base)
11
12
  return super(id_or_name, options)
@@ -23,7 +24,6 @@ module FriendlyId::SluggableClassMethods
23
24
  }
24
25
 
25
26
  result = with_scope(:find => find_options) { find_initial(options) }
26
-
27
27
  if result
28
28
  result.finder_slug_name = id_or_name
29
29
  elsif id_or_name.to_i.to_s != id_or_name
@@ -1,18 +1,31 @@
1
1
  module FriendlyId::SluggableInstanceMethods
2
2
 
3
3
  def self.included(base)
4
- base.has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
5
- base.before_save :set_slug
6
- base.after_save :set_slug_cache
7
- unless base.friendly_id_options[:cache_column]
8
- if base.columns.any? { |c| c.name == 'cached_slug' }
9
- base.friendly_id_options[:cache_column] = :cached_slug
4
+ base.class_eval do
5
+ has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
6
+ before_save :set_slug
7
+ after_save :set_slug_cache
8
+ # only protect the column if the class is not already using attributes_accessible
9
+ if !accessible_attributes
10
+ if friendly_id_options[:cache_column]
11
+ attr_protected friendly_id_options[:cache_column].to_sym
12
+ end
13
+ attr_protected :cached_slug
10
14
  end
11
15
  end
12
- # only protect the column if the class is not already using attributes_accessible
13
- if base.friendly_id_options[:cache_column] && !base.accessible_attributes
14
- base.attr_protected base.friendly_id_options[:cache_column].to_sym
16
+
17
+ def base.cache_column
18
+ if defined?(@cache_column)
19
+ return @cache_column
20
+ elsif friendly_id_options[:cache_column]
21
+ @cache_column = friendly_id_options[:cache_column].to_sym
22
+ elsif columns.any? { |c| c.name == 'cached_slug' }
23
+ @cache_column = :cached_slug
24
+ else
25
+ @cache_column = nil
26
+ end
15
27
  end
28
+
16
29
  end
17
30
 
18
31
  NUM_CHARS_RESERVED_FOR_FRIENDLY_ID_EXTENSION = 2
@@ -36,9 +49,7 @@ module FriendlyId::SluggableInstanceMethods
36
49
 
37
50
  # Was the record found using an old friendly id?
38
51
  def found_using_outdated_friendly_id?
39
- if cache = friendly_id_options[:cache_column]
40
- return false if send(cache) == @finder_slug_name
41
- end
52
+ return false if cache_column && send(cache_column) == @finder_slug_name
42
53
  finder_slug.id != slug.id
43
54
  end
44
55
 
@@ -73,10 +84,11 @@ module FriendlyId::SluggableInstanceMethods
73
84
 
74
85
  # Returns the friendly id, or if none is available, the numeric id.
75
86
  def to_param
76
- if cache = friendly_id_options[:cache_column]
77
- return read_attribute(cache) || id.to_s
87
+ if cache_column
88
+ read_attribute(cache_column) || id.to_s
89
+ else
90
+ slug ? slug.to_friendly_id : id.to_s
78
91
  end
79
- slug ? slug.to_friendly_id : id.to_s
80
92
  end
81
93
 
82
94
  # Get the processed string used as the basis of the friendly id.
@@ -105,6 +117,10 @@ module FriendlyId::SluggableInstanceMethods
105
117
 
106
118
  private
107
119
 
120
+ def cache_column
121
+ self.class.cache_column
122
+ end
123
+
108
124
  def finder_slug=(finder_slug)
109
125
  @finder_slug_name = finder_slug.name
110
126
  slug = finder_slug
@@ -130,14 +146,14 @@ private
130
146
  end
131
147
  # If we're renaming back to a previously used friendly_id, delete the
132
148
  # slug so that we can recycle the name without having to use a sequence.
133
- slugs.find(:all, :conditions => {:name => slug_text, :scope => scope}).each { |s| s.destroy }
149
+ slugs.find(:all, :conditions => {:name => slug_text, :scope => slug_attributes[:scope]}).each { |s| s.destroy }
134
150
  slugs.build slug_attributes
135
151
  end
136
152
  end
137
153
 
138
154
  def set_slug_cache
139
- if friendly_id_options[:cache_column] && send(friendly_id_options[:cache_column]) != slug.to_friendly_id
140
- send "#{friendly_id_options[:cache_column]}=", slug.to_friendly_id
155
+ if cache_column && send(cache_column) != slug.to_friendly_id
156
+ send "#{cache_column}=", slug.to_friendly_id
141
157
  send :update_without_callbacks
142
158
  end
143
159
  end
@@ -19,8 +19,8 @@ module FriendlyId
19
19
  klass = parse_class_name(klass)
20
20
  validate_uses_slugs(klass)
21
21
  Slug.destroy_all(["sluggable_type = ?", klass.to_s])
22
- if klass.friendly_id_options[:cache_column]
23
- klass.update_all("#{klass.friendly_id_options[:cache_column]} = NULL")
22
+ if klass.cache_column
23
+ klass.update_all("#{klass.cache_column} = NULL")
24
24
  end
25
25
  end
26
26
 
@@ -2,7 +2,7 @@ module FriendlyId #:nodoc:
2
2
  module Version #:nodoc:
3
3
  MAJOR = 2
4
4
  MINOR = 2
5
- TINY = 5
5
+ TINY = 6
6
6
  STRING = [MAJOR, MINOR, TINY].join('.')
7
7
  end
8
8
  end
@@ -1,6 +1,3 @@
1
- # encoding: utf-8!
2
- require "mocha"
3
-
4
1
  require File.dirname(__FILE__) + '/test_helper'
5
2
 
6
3
  class CachedSlugModelTest < Test::Unit::TestCase
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require File.dirname(__FILE__) + '/test_helper'
4
2
 
5
3
  class CustomSlugNormalizerTest < Test::Unit::TestCase
@@ -7,29 +5,29 @@ class CustomSlugNormalizerTest < Test::Unit::TestCase
7
5
  context "A slugged model using a custom slug generator" do
8
6
 
9
7
  setup do
10
- Thing.friendly_id_options = FriendlyId::DEFAULT_OPTIONS.merge(:method => :name, :use_slug => true)
8
+ Person.friendly_id_options = FriendlyId::DEFAULT_OPTIONS.merge(:method => :name, :use_slug => true)
11
9
  end
12
10
 
13
11
  teardown do
14
- Thing.delete_all
12
+ Person.delete_all
15
13
  Slug.delete_all
16
14
  end
17
15
 
18
16
  should "invoke the block code" do
19
- thing = Thing.create!(:name => "test")
20
- assert_equal "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", thing.friendly_id
17
+ @person = Person.create!(:name => "Joe Schmoe")
18
+ assert_equal "JOE SCHMOE", @person.friendly_id
21
19
  end
22
20
 
23
21
  should "respect the max_length option" do
24
- Thing.friendly_id_options = Thing.friendly_id_options.merge(:max_length => 10)
25
- thing = Thing.create!(:name => "test")
26
- assert_equal "a94a8fe5cc", thing.friendly_id
22
+ Person.friendly_id_options = Person.friendly_id_options.merge(:max_length => 3)
23
+ @person = Person.create!(:name => "Joe Schmoe")
24
+ assert_equal "JOE", @person.friendly_id
27
25
  end
28
26
 
29
27
  should "respect the reserved option" do
30
- Thing.friendly_id_options = Thing.friendly_id_options.merge(:reserved => ["a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"])
28
+ Person.friendly_id_options = Person.friendly_id_options.merge(:reserved => ["JOE"])
31
29
  assert_raises FriendlyId::SlugGenerationError do
32
- Thing.create!(:name => "test")
30
+ Person.create!(:name => "Joe")
33
31
  end
34
32
  end
35
33
 
@@ -1,5 +1,3 @@
1
- # encoding: utf-8
2
-
3
1
  require File.dirname(__FILE__) + '/test_helper'
4
2
 
5
3
  class NonSluggedTest < Test::Unit::TestCase
@@ -7,7 +5,7 @@ class NonSluggedTest < Test::Unit::TestCase
7
5
  context "A non-slugged model with default FriendlyId options" do
8
6
 
9
7
  setup do
10
- @user = User.create!(:login => "joe", :email => "joe@example.org")
8
+ @user = User.create!(:name => "joe")
11
9
  end
12
10
 
13
11
  teardown do
@@ -52,7 +50,7 @@ class NonSluggedTest < Test::Unit::TestCase
52
50
  end
53
51
 
54
52
  should "not validate if the friendly_id text is reserved" do
55
- user = User.new(:login => "new", :email => "test@example.org")
53
+ user = User.new(:name => "new")
56
54
  assert !user.valid?
57
55
  end
58
56
 
@@ -61,7 +59,7 @@ class NonSluggedTest < Test::Unit::TestCase
61
59
  end
62
60
 
63
61
  should "return its id if the friendly_id is null" do
64
- @user.login = nil
62
+ @user.name = nil
65
63
  assert_equal @user.id.to_s, @user.to_param
66
64
  end
67
65
 
@@ -69,7 +67,7 @@ class NonSluggedTest < Test::Unit::TestCase
69
67
  context "when using an array as the find argument" do
70
68
 
71
69
  setup do
72
- @user2 = User.create(:login => "jane", :email => "jane@example.org")
70
+ @user2 = User.create(:name => "jane")
73
71
  end
74
72
 
75
73
  should "return results" do
@@ -89,7 +87,7 @@ class NonSluggedTest < Test::Unit::TestCase
89
87
  end
90
88
 
91
89
  should "indicate if the results were found using a friendly_id" do
92
- users = User.find([@user.id, @user2.friendly_id], :order => "login ASC")
90
+ users = User.find([@user.id, @user2.friendly_id], :order => "name ASC")
93
91
  assert users[0].found_using_friendly_id?
94
92
  assert users[1].found_using_numeric_id?
95
93
  end