friendly_id 1.9.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. data.tar.gz.sig +0 -0
  2. data/History.txt +81 -0
  3. data/MIT-LICENSE +19 -0
  4. data/Manifest.txt +53 -0
  5. data/README.rdoc +313 -0
  6. data/Rakefile +43 -0
  7. data/coverage/index.html +409 -0
  8. data/coverage/lib-friendly_id-non_sluggable_class_methods_rb.html +646 -0
  9. data/coverage/lib-friendly_id-non_sluggable_instance_methods_rb.html +638 -0
  10. data/coverage/lib-friendly_id-shoulda_macros_rb.html +641 -0
  11. data/coverage/lib-friendly_id-sluggable_class_methods_rb.html +714 -0
  12. data/coverage/lib-friendly_id-sluggable_instance_methods_rb.html +710 -0
  13. data/coverage/lib-friendly_id-string_helpers_rb.html +685 -0
  14. data/coverage/lib-friendly_id_rb.html +665 -0
  15. data/coverage/lib-slug_rb.html +695 -0
  16. data/coverage/rails-init_rb.html +606 -0
  17. data/friendly_id.gemspec +38 -0
  18. data/generators/friendly_id/friendly_id_generator.rb +12 -0
  19. data/generators/friendly_id/templates/create_slugs.rb +18 -0
  20. data/generators/friendly_id_20_upgrade/friendly_id_20_upgrade_generator.rb +11 -0
  21. data/generators/friendly_id_20_upgrade/templates/upgrade_friendly_id_to_20.rb +19 -0
  22. data/init.rb +1 -0
  23. data/lib/friendly_id.rb +61 -0
  24. data/lib/friendly_id/non_sluggable_class_methods.rb +41 -0
  25. data/lib/friendly_id/non_sluggable_instance_methods.rb +33 -0
  26. data/lib/friendly_id/shoulda_macros.rb +36 -0
  27. data/lib/friendly_id/slug.rb +90 -0
  28. data/lib/friendly_id/sluggable_class_methods.rb +109 -0
  29. data/lib/friendly_id/sluggable_instance_methods.rb +105 -0
  30. data/lib/friendly_id/version.rb +8 -0
  31. data/lib/tasks/friendly_id.rake +48 -0
  32. data/lib/tasks/friendly_id.rb +1 -0
  33. data/test/database.yml +3 -0
  34. data/test/fixtures/countries.yml +4 -0
  35. data/test/fixtures/country.rb +4 -0
  36. data/test/fixtures/people.yml +7 -0
  37. data/test/fixtures/person.rb +6 -0
  38. data/test/fixtures/post.rb +3 -0
  39. data/test/fixtures/posts.yml +19 -0
  40. data/test/fixtures/slugs.yml +45 -0
  41. data/test/fixtures/user.rb +3 -0
  42. data/test/fixtures/users.yml +7 -0
  43. data/test/non_slugged_test.rb +63 -0
  44. data/test/rails/2.x/app/controllers/application.rb +0 -0
  45. data/test/rails/2.x/config/boot.rb +109 -0
  46. data/test/rails/2.x/config/database.yml +3 -0
  47. data/test/rails/2.x/config/environment.rb +7 -0
  48. data/test/rails/2.x/config/environments/test.rb +6 -0
  49. data/test/rails/2.x/config/routes.rb +0 -0
  50. data/test/schema.rb +38 -0
  51. data/test/scoped_model_test.rb +21 -0
  52. data/test/slug_test.rb +87 -0
  53. data/test/sluggable_test.rb +181 -0
  54. data/test/test_helper.rb +35 -0
  55. metadata +155 -0
  56. metadata.gz.sig +1 -0
@@ -0,0 +1,38 @@
1
+ Gem::Specification.new do |s|
2
+ s.name = %q{friendly_id}
3
+ s.version = "1.9.9"
4
+
5
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
6
+ s.authors = ["Norman Clarke", "Adrian Mugnolo", "Emilio Tagua"]
7
+ s.cert_chain = ["/Users/norman/.gem/gem-public_cert.pem"]
8
+ s.date = %q{2008-12-16}
9
+ s.description = %q{A comprehensive slugging and pretty-URL plugin for Ruby on Rails.}
10
+ s.email = ["norman@randomba.org", "adrian@randomba.org", "miloops@gmail.com"]
11
+ s.extra_rdoc_files = ["History.txt", "Manifest.txt"]
12
+ s.files = ["History.txt", "MIT-LICENSE", "Manifest.txt", "README.rdoc", "Rakefile", "coverage/index.html", "coverage/lib-friendly_id-non_sluggable_class_methods_rb.html", "coverage/lib-friendly_id-non_sluggable_instance_methods_rb.html", "coverage/lib-friendly_id-shoulda_macros_rb.html", "coverage/lib-friendly_id-sluggable_class_methods_rb.html", "coverage/lib-friendly_id-sluggable_instance_methods_rb.html", "coverage/lib-friendly_id-string_helpers_rb.html", "coverage/lib-friendly_id_rb.html", "coverage/lib-slug_rb.html", "coverage/rails-init_rb.html", "friendly_id.gemspec", "generators/friendly_id/friendly_id_generator.rb", "generators/friendly_id/templates/create_slugs.rb", "init.rb", "lib/friendly_id.rb", "lib/friendly_id/non_sluggable_class_methods.rb", "lib/friendly_id/non_sluggable_instance_methods.rb", "lib/friendly_id/shoulda_macros.rb", "lib/friendly_id/slug.rb", "lib/friendly_id/sluggable_class_methods.rb", "lib/friendly_id/sluggable_instance_methods.rb", "lib/friendly_id/version.rb", "lib/tasks/friendly_id.rake", "lib/tasks/friendly_id.rb", "test/database.yml", "test/fixtures/countries.yml", "test/fixtures/country.rb", "test/fixtures/people.yml", "test/fixtures/person.rb", "test/fixtures/post.rb", "test/fixtures/posts.yml", "test/fixtures/slugs.yml", "test/fixtures/user.rb", "test/fixtures/users.yml", "test/non_slugged_test.rb", "test/rails/2.x/app/controllers/application.rb", "test/rails/2.x/config/boot.rb", "test/rails/2.x/config/database.yml", "test/rails/2.x/config/environment.rb", "test/rails/2.x/config/environments/test.rb", "test/rails/2.x/config/routes.rb", "test/schema.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/sluggable_test.rb", "test/test_helper.rb"]
13
+ s.has_rdoc = true
14
+ s.homepage = %q{http://randomba.org}
15
+ s.rdoc_options = ["--main", "README.txt"]
16
+ s.require_paths = ["lib"]
17
+ s.rubyforge_project = %q{friendly-id}
18
+ s.rubygems_version = %q{1.3.1}
19
+ s.signing_key = %q{/Users/norman/.gem/gem-private_key.pem}
20
+ s.summary = %q{A comprehensive slugging and pretty-URL plugin for Ruby on Rails.}
21
+ s.test_files = ["test/non_slugged_test.rb", "test/scoped_model_test.rb", "test/slug_test.rb", "test/sluggable_test.rb"]
22
+
23
+ if s.respond_to? :specification_version then
24
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
25
+ s.specification_version = 2
26
+
27
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
28
+ s.add_runtime_dependency(%q<unicode>, [">= 0.1"])
29
+ s.add_development_dependency(%q<hoe>, [">= 1.8.2"])
30
+ else
31
+ s.add_dependency(%q<unicode>, [">= 0.1"])
32
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
33
+ end
34
+ else
35
+ s.add_dependency(%q<unicode>, [">= 0.1"])
36
+ s.add_dependency(%q<hoe>, [">= 1.8.2"])
37
+ end
38
+ end
@@ -0,0 +1,12 @@
1
+ class FriendlyIdGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ unless options[:skip_migration]
5
+ m.migration_template(
6
+ 'create_slugs.rb', 'db/migrate', :migration_file_name => 'create_slugs'
7
+ )
8
+ m.file "/../../../lib/tasks/friendly_id.rake", "lib/tasks/friendly_id.rake"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,18 @@
1
+ class CreateSlugs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :slugs do |t|
4
+ t.string :name
5
+ t.integer :sluggable_id
6
+ t.integer :sequence, :null => false, :default => 1
7
+ t.string :sluggable_type, :limit => 40
8
+ t.string :scope, :limit => 40
9
+ t.datetime :created_at
10
+ end
11
+ add_index :slugs, [:name, :sluggable_type, :scope, :sequence], :unique => true
12
+ add_index :slugs, :sluggable_id
13
+ end
14
+
15
+ def self.down
16
+ drop_table :slugs
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ class FriendlyId20UpgradeGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ unless options[:skip_migration]
5
+ m.migration_template(
6
+ 'upgrade_friendly_id_to_20.rb', 'db/migrate', :migration_file_name => 'upgrade_friendly_id_to_20'
7
+ )
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,19 @@
1
+ class UpgradeFriendlyIdTo20 < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ remove_column :slugs, :updated_at
5
+ remove_index :slugs, :column => [:name, :sluggable_type]
6
+ add_column :slugs, :sequence, :integer, :null => false, :default => 1
7
+ add_column :slugs, :scope, :string, :limit => 40
8
+ add_index :slugs, [:name, :sluggable_type, :scope, :sequence], :unique => true, :name => "index_slugs_on_n_s_s_and_s"
9
+ end
10
+
11
+ def self.down
12
+ remove_index :slugs, :name => "index_slugs_on_n_s_s_and_s"
13
+ remove_column :slugs, :scope
14
+ remove_column :slugs, :sequence
15
+ add_column :slugs, :updated_at, :datetime
16
+ add_index :slugs, [:name, :sluggable_type], :unique => true
17
+ end
18
+
19
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'friendly_id'
@@ -0,0 +1,61 @@
1
+ require 'unicode'
2
+ require 'friendly_id/slug'
3
+ require 'friendly_id/shoulda_macros'
4
+
5
+ # FriendlyId is a comprehensize Rails plugin/gem for slugging and permalinks.
6
+ module FriendlyId
7
+
8
+ # Load FriendlyId if the gem is included in a Rails app.
9
+ def self.enable
10
+ return if ActiveRecord::Base.methods.include? 'has_friendly_id'
11
+ ActiveRecord::Base.class_eval { extend FriendlyId::ClassMethods }
12
+ Test::Unit::TestCase.class_eval { include FriendlyId::ShouldaMacros }
13
+ end
14
+
15
+ # This error is raised when it's not possible to generate a unique slug.
16
+ class SlugGenerationError < StandardError ; end
17
+
18
+ module ClassMethods
19
+
20
+ # Default options for friendly_id.
21
+ DEFAULT_FRIENDLY_ID_OPTIONS = {:method => nil, :use_slug => false, :max_length => 255, :reserved => [], :strip_diacritics => false, :scope => nil}.freeze
22
+ VALID_FRIENDLY_ID_KEYS = [:use_slug, :max_length, :reserved, :strip_diacritics, :scope].freeze
23
+
24
+ # Set up an ActiveRecord model to use a friendly_id.
25
+ #
26
+ # The column argument can be one of your model's columns, or a method
27
+ # you use to generate the slug.
28
+ #
29
+ # Options:
30
+ # * <tt>:use_slug</tt> - Defaults to false. Use slugs when you want to use a non-unique text field for friendly ids.
31
+ # * <tt>:max_length</tt> - Defaults to 255. The maximum allowed length for a slug.
32
+ # * <tt>:strip_diacritics</tt> - Defaults to false. If true, it will remove accents, umlauts, etc. from western characters.
33
+ # * <tt>:reseved</tt> - Array of words that are reserved and can't be used as slugs. If such a word is used, it will be treated the same as if that slug was already taken (numeric extension will be appended). Defaults to [].
34
+ def has_friendly_id(column, options = {})
35
+ options.assert_valid_keys VALID_FRIENDLY_ID_KEYS
36
+ options = DEFAULT_FRIENDLY_ID_OPTIONS.merge(options).merge(:column => column)
37
+ write_inheritable_attribute :friendly_id_options, options
38
+ class_inheritable_reader :friendly_id_options
39
+
40
+ if options[:use_slug]
41
+ has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
42
+ require 'friendly_id/sluggable_class_methods'
43
+ require 'friendly_id/sluggable_instance_methods'
44
+ extend SluggableClassMethods
45
+ include SluggableInstanceMethods
46
+ before_save :set_slug
47
+ else
48
+ require 'friendly_id/non_sluggable_class_methods'
49
+ require 'friendly_id/non_sluggable_instance_methods'
50
+ extend NonSluggableClassMethods
51
+ include NonSluggableInstanceMethods
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ if defined?(ActiveRecord)
60
+ FriendlyId::enable
61
+ end
@@ -0,0 +1,41 @@
1
+ module FriendlyId::NonSluggableClassMethods
2
+
3
+ def self.extended(base) #:nodoc:#
4
+ class << base
5
+ alias_method_chain :find_one, :friendly
6
+ alias_method_chain :find_some, :friendly
7
+ end
8
+ end
9
+
10
+ protected
11
+
12
+ def find_one_with_friendly(id, options) #:nodoc:#
13
+ if id.is_a?(String) && result = send("find_by_#{ friendly_id_options[:column] }", id, options)
14
+ result.send(:found_using_friendly_id=, true)
15
+ else
16
+ result = find_one_without_friendly id, options
17
+ end
18
+ result
19
+ end
20
+
21
+ def find_some_with_friendly(ids_and_names, options) #:nodoc:#
22
+ results_by_name = with_scope :find => options do
23
+ find :all, :conditions => ["#{ quoted_table_name }.#{ friendly_id_options[:column] } IN (?)", ids_and_names]
24
+ end
25
+
26
+ ids = ids_and_names - results_by_name.map { |r| r[ friendly_id_options[:column] ] }
27
+ results = results_by_name
28
+
29
+ results += with_scope :find => options do
30
+ find :all, :conditions => ["#{ quoted_table_name }.#{ primary_key } IN (?)", ids]
31
+ end unless ids.empty?
32
+
33
+ expected_size = options[:offset] ? ids_and_names.size - options[:offset] : ids_and_names.size
34
+ expected_size = options[:limit] if options[:limit] && expected_size > options[:limit]
35
+
36
+ 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_size })" if results.size != expected_size
37
+
38
+ results_by_name.each { |r| r.send(:found_using_friendly_id=, true) }
39
+ results
40
+ end
41
+ end
@@ -0,0 +1,33 @@
1
+ module FriendlyId::NonSluggableInstanceMethods
2
+
3
+ attr :found_using_friendly_id
4
+
5
+ # Was the record found using one of its friendly ids?
6
+ def found_using_friendly_id?
7
+ @found_using_friendly_id
8
+ end
9
+
10
+ # Was the record found using its numeric id?
11
+ def found_using_numeric_id?
12
+ !@found_using_friendly_id
13
+ end
14
+ alias has_better_id? found_using_numeric_id?
15
+
16
+ # Returns the friendly_id.
17
+ def friendly_id
18
+ send friendly_id_options[:column]
19
+ end
20
+ alias best_id friendly_id
21
+
22
+ # Returns the friendly id, or if none is available, the numeric id.
23
+ def to_param
24
+ friendly_id.to_s || id.to_s
25
+ end
26
+
27
+ private
28
+
29
+ def found_using_friendly_id=(value) #:nodoc#
30
+ @found_using_friendly_id = value
31
+ end
32
+
33
+ end
@@ -0,0 +1,36 @@
1
+ module FriendlyId
2
+
3
+ # A Shoulda[http://www.thoughtbot.com/projects/shoulda/] macros for testing
4
+ # models using FriendlyId.
5
+ module ShouldaMacros
6
+
7
+ # Ensure that a model is using FriendlyId.
8
+ def self.should_have_friendly_id(column, options = {})
9
+
10
+ options.assert_valid_keys(:use_slug)
11
+ klass = self.model_class
12
+
13
+ should "have friendly id for #{method}" do
14
+ assert_respond_to klass, :friendly_id_options,
15
+ "#{klass} does not respond to friendly_id_options"
16
+ assert_equal column, klass.friendly_id_options[:method]
17
+ end
18
+
19
+ if options[:use_slug]
20
+ should "include/extend friendly_id's sluggable modules" do
21
+ assert klass.extended_by.include?(FriendlyId::SluggableClassMethods),
22
+ "#{klass} does not extend FriendlyId::SluggableClassMethods"
23
+ assert klass.include?(FriendlyId::SluggableInstanceMethods),
24
+ "#{klass} not include FriendlyId::SluggableInstanceMethods"
25
+ end
26
+ else
27
+ should "include/extend friendly_id's non-sluggable modules" do
28
+ assert klass.extended_by.include?(FriendlyId::NonSluggableClassMethods),
29
+ "#{klass} does not extend FriendlyId::NonSluggableClassMethods"
30
+ assert klass.include?(FriendlyId::NonSluggableInstanceMethods),
31
+ "#{klass} not include FriendlyId::NonSluggableInstanceMethods"
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,90 @@
1
+ # A Slug is a unique, human-friendly identifier for an ActiveRecord.
2
+ class Slug < ActiveRecord::Base
3
+
4
+ belongs_to :sluggable, :polymorphic => true
5
+ validates_uniqueness_of :name, :scope => [:sluggable_type, :scope, :sequence]
6
+ before_create :set_sequence
7
+ before_save :check_for_blank_name
8
+
9
+ class << self
10
+
11
+ # Sanitizes and dasherizes string to make it safe for URL's.
12
+ #
13
+ # Example:
14
+ #
15
+ # slug.normalize('This... is an example!') # => "this-is-an-example"
16
+ #
17
+ # Note that Rails 2.2.x offers a parameterize method for this. It's not
18
+ # used here because it assumes you want to strip away accented characters,
19
+ # and this may not always be your desire.
20
+ #
21
+ # At the time of writing, it also handles several characters incorrectly,
22
+ # for instance replacing Icelandic's "thorn" character with "y" rather
23
+ # than "d." This might be pedantic, but I don't want to piss off the
24
+ # Vikings. The last time anyone pissed them off, they uleashed a wave of
25
+ # terror in Europe unlike anything ever seen before or after. I'm not
26
+ # taking any chances.
27
+ def normalize(slug_text)
28
+ return "" if slug_text.blank?
29
+ slug_text.
30
+ send(chars_func).
31
+ # For some reason Spanish ¡ and ¿ are not detected as non-word
32
+ # characters. Bug in Ruby?
33
+ normalize.gsub(/[\W|¡|¿]/u, ' ').
34
+ strip.
35
+ gsub(/\s+/u, '-').
36
+ gsub(/-\z/u, '').
37
+ downcase.
38
+ to_s
39
+ end
40
+
41
+ def parse(friendly_id)
42
+ name, sequence = friendly_id.split('--')
43
+ sequence ||= "1"
44
+ return name, sequence
45
+ end
46
+
47
+ # Remove diacritics (accents, umlauts, etc.) from the string.
48
+ def strip_diacritics(string)
49
+ require 'unicode'
50
+ Unicode::normalize_KD(string).unpack('U*').select { |cp|
51
+ cp < 0x300 || cp > 0x036F
52
+ }.pack('U*')
53
+ end
54
+
55
+ private
56
+
57
+ def chars_func
58
+ Rails.version =~ /2.2.[\d]*/ ? :mb_chars : :chars
59
+ rescue NoMethodError
60
+ :chars
61
+ end
62
+
63
+ end
64
+
65
+ # Whether or not this slug is the most recent of its owner's slugs.
66
+ def is_most_recent?
67
+ sluggable.slug == self
68
+ end
69
+
70
+ def to_friendly_id
71
+ sequence > 1 ? "#{name}--#{sequence}" : name
72
+ end
73
+
74
+ protected
75
+
76
+ # Raise a FriendlyId::SlugGenerationError if the slug name is blank.
77
+ def check_for_blank_name #:nodoc:#
78
+ if name.blank?
79
+ raise FriendlyId::SlugGenerationError.new("The slug text is blank.")
80
+ end
81
+ end
82
+
83
+ def set_sequence
84
+ last = Slug.find(:first, :conditions => { :name => name, :scope => scope,
85
+ :sluggable_type => sluggable_type}, :order => "sequence DESC",
86
+ :select => 'sequence')
87
+ self.sequence = last.sequence + 1 if last
88
+ end
89
+
90
+ end
@@ -0,0 +1,109 @@
1
+ module FriendlyId::SluggableClassMethods
2
+
3
+ def self.extended(base) #:nodoc:#
4
+
5
+ class << base
6
+ alias_method_chain :find_one, :friendly
7
+ alias_method_chain :find_some, :friendly
8
+ alias_method_chain :validate_find_options, :friendly
9
+ end
10
+
11
+ end
12
+
13
+ # Finds a single record using the friendly id, or the record's id.
14
+ def find_one_with_friendly(id_or_name, options) #:nodoc:#
15
+
16
+ scope = options.delete(:scope)
17
+ return find_one_without_friendly(id_or_name, options) if id_or_name.is_a?(Fixnum)
18
+
19
+ find_options = {:select => "#{self.table_name}.*"}
20
+ find_options[:joins] = :slugs unless options[:include] && [*options[:include]].flatten.include?(:slugs)
21
+
22
+ name, sequence = Slug.parse(id_or_name)
23
+
24
+ find_options[:conditions] = {
25
+ "#{Slug.table_name}.name" => name,
26
+ "#{Slug.table_name}.scope" => scope,
27
+ "#{Slug.table_name}.sequence" => sequence
28
+ }
29
+
30
+ result = with_scope(:find => find_options) { find_initial(options) }
31
+
32
+ if result
33
+ result.finder_slug_name = id_or_name
34
+ else
35
+ result = find_one_without_friendly id_or_name, options
36
+ end
37
+
38
+ result
39
+
40
+ end
41
+
42
+ # Finds multiple records using the friendly ids, or the records' ids.
43
+ def find_some_with_friendly(ids_and_names, options) #:nodoc:#
44
+
45
+ slugs, ids = get_slugs_and_ids(ids_and_names, options)
46
+ results = []
47
+
48
+ find_options = {:select => "#{self.table_name}.*"}
49
+ find_options[:joins] = :slugs unless options[:include] && [*options[:include]].flatten.include?(:slugs)
50
+ find_options[:conditions] = "#{quoted_table_name}.#{primary_key} IN (#{ids.empty? ? 'NULL' : ids.join(',')}) "
51
+ find_options[:conditions] << "OR #{Slug.quoted_table_name}.#{Slug.primary_key} IN (#{slugs.to_s(:db)})"
52
+
53
+ results = with_scope(:find => find_options) { find_every(options) }
54
+
55
+ # calculate expected size, taken from active_record/base.rb
56
+ expected = expected_size(ids_and_names, options)
57
+ if results.size != expected
58
+ 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 })"
59
+ end
60
+
61
+ assign_finder_slugs(slugs, results)
62
+
63
+ results
64
+ end
65
+
66
+ def validate_find_options_with_friendly(options) #:nodoc:#
67
+ options.assert_valid_keys([:conditions, :include, :joins, :limit, :offset,
68
+ :order, :select, :readonly, :group, :from, :lock, :having, :scope])
69
+ end
70
+
71
+ private
72
+
73
+ # Assign finder slugs for the results found in find_some_with_friendly
74
+ def assign_finder_slugs(slugs, results) #:nodoc:#
75
+ slugs.each do |slug|
76
+ results.select { |r| r.id == slug.sluggable_id }.each do |result|
77
+ result.send(:finder_slug=, slug)
78
+ end
79
+ end
80
+ end
81
+
82
+ # Calculate expected result size for find_some_with_friendly
83
+ def expected_size(ids_and_names, options) #:nodoc:#
84
+ size = options[:offset] ? ids_and_names.size - options[:offset] : ids_and_names.size
85
+ size = options[:limit] if options[:limit] && size > options[:limit]
86
+ size
87
+ end
88
+
89
+ # Build arrays of slugs and ids, for the find_some_with_friendly method.
90
+ def get_slugs_and_ids(ids_and_names, options) #:nodoc:#
91
+ scope = options.delete(:scope)
92
+ slugs = []
93
+ ids = []
94
+ ids_and_names.each do |id_or_name|
95
+ name, sequence = Slug.parse id_or_name
96
+ slug = Slug.find(:first, :readonly => true, :conditions => {
97
+ :name => name,
98
+ :scope => scope,
99
+ :sequence => sequence,
100
+ :sluggable_type => base_class.name
101
+ })
102
+ # If the slug was found, add it to the array for later use. If not, and
103
+ # the id_or_name is a number, assume that it is a regular record id.
104
+ slug ? slugs << slug : (ids << id_or_name if id_or_name =~ /\A\d*\z/)
105
+ end
106
+ return slugs, ids
107
+ end
108
+
109
+ end