friendly_id 2.2.5 → 2.2.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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