rakutenusa-friendly_id 2.0.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,41 @@
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 || id).to_s
25
+ end
26
+
27
+ private
28
+
29
+ def validate_friendly_id
30
+ if self.class.friendly_id_options[:reserved].include? friendly_id
31
+ self.errors.add(self.class.friendly_id_options[:column],
32
+ self.class.friendly_id_options[:reserved_message] % friendly_id)
33
+ return false
34
+ end
35
+ end
36
+
37
+ def found_using_friendly_id=(value) #:nodoc#
38
+ @found_using_friendly_id = value
39
+ end
40
+
41
+ end
@@ -0,0 +1,91 @@
1
+ require 'unicode'
2
+ # A Slug is a unique, human-friendly identifier for an ActiveRecord.
3
+ class Slug < ActiveRecord::Base
4
+
5
+ belongs_to :sluggable, :polymorphic => true
6
+ before_save :check_for_blank_name, :set_sequence
7
+
8
+ class << self
9
+
10
+ # Sanitizes and dasherizes string to make it safe for URL's.
11
+ #
12
+ # Example:
13
+ #
14
+ # slug.normalize('This... is an example!') # => "this-is-an-example"
15
+ #
16
+ # Note that Rails 2.2.x offers a parameterize method for this. It's not
17
+ # used here because it assumes you want to strip away accented characters,
18
+ # and this may not always be your desire.
19
+ #
20
+ # At the time of writing, it also handles several characters incorrectly,
21
+ # for instance replacing Icelandic's "thorn" character with "y" rather
22
+ # than "d." This might be pedantic, but I don't want to piss off the
23
+ # Vikings. The last time anyone pissed them off, they uleashed a wave of
24
+ # terror in Europe unlike anything ever seen before or after. I'm not
25
+ # taking any chances.
26
+ def normalize(slug_text)
27
+ return "" if slug_text.nil? || slug_text == ""
28
+ Unicode::normalize_KC(slug_text).
29
+ send(chars_func).
30
+ # For some reason Spanish ¡ and ¿ are not detected as non-word
31
+ # characters. Bug in Ruby?
32
+ gsub(/[\W|¡|¿]/u, ' ').
33
+ strip.
34
+ gsub(/\s+/u, '-').
35
+ gsub(/-\z/u, '').
36
+ downcase.
37
+ to_s
38
+ end
39
+
40
+ def parse(friendly_id)
41
+ name, sequence = friendly_id.split('--')
42
+ sequence ||= "1"
43
+ return name, sequence
44
+ end
45
+
46
+ # Remove diacritics (accents, umlauts, etc.) from the string. Borrowed
47
+ # from "The Ruby Way."
48
+ def strip_diacritics(string)
49
+ Unicode::normalize_KD(string).unpack('U*').select { |u| u < 0x300 || u > 0x036F }.pack('U*')
50
+ end
51
+
52
+ # Remove non-ascii characters from the string.
53
+ def strip_non_ascii(string)
54
+ strip_diacritics(string).gsub(/[^a-z0-9]+/i, ' ')
55
+ end
56
+
57
+ private
58
+
59
+ def chars_func
60
+ "".respond_to?(:mb_chars) ? :mb_chars : :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 == "" || name.nil?
79
+ raise FriendlyId::SlugGenerationError.new("The slug text is blank.")
80
+ end
81
+ end
82
+
83
+ def set_sequence
84
+ return unless new_record?
85
+ last = Slug.find(:first, :conditions => { :name => name, :scope => scope,
86
+ :sluggable_type => sluggable_type}, :order => "sequence DESC",
87
+ :select => 'sequence')
88
+ self.sequence = last.sequence + 1 if last
89
+ end
90
+
91
+ end
@@ -0,0 +1,114 @@
1
+ module FriendlyId::SluggableClassMethods
2
+
3
+ include FriendlyId::Helpers
4
+
5
+ def self.extended(base) #:nodoc:#
6
+
7
+ class << base
8
+ alias_method_chain :find_one, :friendly
9
+ alias_method_chain :find_some, :friendly
10
+ alias_method_chain :validate_find_options, :friendly
11
+ end
12
+
13
+ end
14
+
15
+ # Finds a single record using the friendly id, or the record's id.
16
+ def find_one_with_friendly(id_or_name, options) #:nodoc:#
17
+
18
+ scope = options.delete(:scope)
19
+ return find_one_without_friendly(id_or_name, options) if id_or_name.is_a?(Fixnum)
20
+
21
+ find_options = {:select => "#{self.table_name}.*"}
22
+ find_options[:joins] = :slugs unless options[:include] && [*options[:include]].flatten.include?(:slugs)
23
+
24
+ name, sequence = Slug.parse(id_or_name)
25
+
26
+ find_options[:conditions] = {
27
+ "#{Slug.table_name}.name" => name,
28
+ "#{Slug.table_name}.scope" => scope,
29
+ "#{Slug.table_name}.sequence" => sequence
30
+ }
31
+
32
+ result = with_scope(:find => find_options) { find_initial(options) }
33
+
34
+ if result
35
+ result.finder_slug_name = id_or_name
36
+ else
37
+ result = find_one_without_friendly id_or_name, options
38
+ end
39
+
40
+ result
41
+ rescue ActiveRecord::RecordNotFound => e
42
+
43
+ if friendly_id_options[:scope]
44
+ if !scope
45
+ e.message << "; expected scope but got none"
46
+ else
47
+ e.message << " and scope=#{scope}"
48
+ end
49
+ end
50
+
51
+ raise e
52
+
53
+ end
54
+
55
+ # Finds multiple records using the friendly ids, or the records' ids.
56
+ def find_some_with_friendly(ids_and_names, options) #:nodoc:#
57
+
58
+ slugs, ids = get_slugs_and_ids(ids_and_names, options)
59
+ results = []
60
+
61
+ find_options = {:select => "#{self.table_name}.*"}
62
+ find_options[:joins] = :slugs unless options[:include] && [*options[:include]].flatten.include?(:slugs)
63
+ find_options[:conditions] = "#{quoted_table_name}.#{primary_key} IN (#{ids.empty? ? 'NULL' : ids.join(',')}) "
64
+ find_options[:conditions] << "OR slugs.id IN (#{slugs.to_s(:db)})"
65
+
66
+ results = with_scope(:find => find_options) { find_every(options) }
67
+
68
+ expected = expected_size(ids_and_names, options)
69
+ if results.size != expected
70
+ 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 })"
71
+ end
72
+
73
+ assign_finder_slugs(slugs, results)
74
+
75
+ results
76
+ end
77
+
78
+ def validate_find_options_with_friendly(options) #:nodoc:#
79
+ options.assert_valid_keys([:conditions, :include, :joins, :limit, :offset,
80
+ :order, :select, :readonly, :group, :from, :lock, :having, :scope])
81
+ end
82
+
83
+ private
84
+
85
+ # Assign finder slugs for the results found in find_some_with_friendly
86
+ def assign_finder_slugs(slugs, results) #:nodoc:#
87
+ slugs.each do |slug|
88
+ results.select { |r| r.id == slug.sluggable_id }.each do |result|
89
+ result.send(:finder_slug=, slug)
90
+ end
91
+ end
92
+ end
93
+
94
+ # Build arrays of slugs and ids, for the find_some_with_friendly method.
95
+ def get_slugs_and_ids(ids_and_names, options) #:nodoc:#
96
+ scope = options.delete(:scope)
97
+ slugs = []
98
+ ids = []
99
+ ids_and_names.each do |id_or_name|
100
+ name, sequence = Slug.parse id_or_name
101
+ slug = Slug.find(:first, :conditions => {
102
+ :name => name,
103
+ :scope => scope,
104
+ :sequence => sequence,
105
+ :sluggable_type => base_class.name
106
+ })
107
+ # If the slug was found, add it to the array for later use. If not, and
108
+ # the id_or_name is a number, assume that it is a regular record id.
109
+ slug ? slugs << slug : (ids << id_or_name if id_or_name =~ /\A\d*\z/)
110
+ end
111
+ return slugs, ids
112
+ end
113
+
114
+ end
@@ -0,0 +1,113 @@
1
+ module FriendlyId::SluggableInstanceMethods
2
+
3
+ NUM_CHARS_RESERVED_FOR_FRIENDLY_ID_EXTENSION = 2
4
+
5
+ attr :finder_slug
6
+ attr_accessor :finder_slug_name
7
+
8
+ def finder_slug
9
+ @finder_slug ||= init_finder_slug or nil
10
+ end
11
+
12
+ # Was the record found using one of its friendly ids?
13
+ def found_using_friendly_id?
14
+ finder_slug
15
+ end
16
+
17
+ # Was the record found using its numeric id?
18
+ def found_using_numeric_id?
19
+ !found_using_friendly_id?
20
+ end
21
+
22
+ # Was the record found using an old friendly id?
23
+ def found_using_outdated_friendly_id?
24
+ finder_slug.id != slug.id
25
+ end
26
+
27
+ # Was the record found using an old friendly id, or its numeric id?
28
+ def has_better_id?
29
+ slug and found_using_numeric_id? || found_using_outdated_friendly_id?
30
+ end
31
+
32
+ # Returns the friendly id.
33
+ def friendly_id
34
+ slug(true).to_friendly_id
35
+ end
36
+ alias best_id friendly_id
37
+
38
+ # Has the basis of our friendly id changed, requiring the generation of a
39
+ # new slug?
40
+ def new_slug_needed?
41
+ !slug || slug_text != slug.name
42
+ end
43
+
44
+ # Returns the most recent slug, which is used to determine the friendly
45
+ # id.
46
+ def slug(reload = false)
47
+ @most_recent_slug = nil if reload
48
+ @most_recent_slug ||= slugs.first
49
+ end
50
+
51
+ # Returns the friendly id, or if none is available, the numeric id.
52
+ def to_param
53
+ slug ? slug.to_friendly_id : id.to_s
54
+ end
55
+
56
+ # Get the processed string used as the basis of the friendly id.
57
+ def slug_text
58
+ base = send friendly_id_options[:column]
59
+ if self.slug_normalizer_block
60
+ base = self.slug_normalizer_block.call(base)
61
+ else
62
+ if self.friendly_id_options[:strip_diacritics]
63
+ base = Slug::strip_diacritics(base)
64
+ end
65
+ if self.friendly_id_options[:strip_non_ascii]
66
+ base = Slug::strip_non_ascii(base)
67
+ end
68
+ base = Slug::normalize(base)
69
+ end
70
+
71
+ if base.length > friendly_id_options[:max_length]
72
+ base = base[0...friendly_id_options[:max_length]]
73
+ end
74
+ if friendly_id_options[:reserved].include?(base)
75
+ raise FriendlyId::SlugGenerationError.new("The slug text is a reserved value")
76
+ end
77
+ return base
78
+ end
79
+
80
+ private
81
+
82
+ def finder_slug=(finder_slug)
83
+ @finder_slug_name = finder_slug.name
84
+ slug = finder_slug
85
+ slug.sluggable = self
86
+ slug
87
+ end
88
+
89
+ def init_finder_slug
90
+ return false if !@finder_slug_name
91
+ name, sequence = Slug.parse(@finder_slug_name)
92
+ slug = Slug.find(:first, :conditions => {:sluggable_id => id, :name => name, :sequence => sequence, :sluggable_type => self.class.base_class.name })
93
+ finder_slug = slug
94
+ end
95
+
96
+ # Set the slug using the generated friendly id.
97
+ def set_slug
98
+ if self.class.friendly_id_options[:use_slug] && new_slug_needed?
99
+ @most_recent_slug = nil
100
+ slug_attributes = {:name => slug_text}
101
+ if friendly_id_options[:scope]
102
+ scope = send(friendly_id_options[:scope])
103
+ slug_attributes[:scope] = scope.respond_to?(:to_param) ? scope.to_param : scope.to_s
104
+ end
105
+ # If we're renaming back to a previously used friendly_id, delete the
106
+ # slug so that we can recycle the name without having to use a sequence.
107
+ slugs.find(:all, :conditions => {:name => slug_text, :scope => scope}).each { |s| s.destroy }
108
+ slug = slugs.build slug_attributes
109
+ slug
110
+ end
111
+ end
112
+
113
+ end
@@ -0,0 +1,8 @@
1
+ module FriendlyId #:nodoc:
2
+ module Version #:nodoc:
3
+ MAJOR = 2
4
+ MINOR = 0
5
+ TINY = 4
6
+ STRING = [MAJOR, MINOR, TINY].join('.')
7
+ end
8
+ end
@@ -0,0 +1,87 @@
1
+ require 'friendly_id/helpers'
2
+ require 'friendly_id/slug'
3
+
4
+ # FriendlyId is a comprehensize Rails plugin/gem for slugging and permalinks.
5
+ module FriendlyId
6
+
7
+ # Default options for has_friendly_id.
8
+ DEFAULT_FRIENDLY_ID_OPTIONS = {
9
+ :max_length => 255,
10
+ :method => nil,
11
+ :reserved => ["new", "index"],
12
+ :reserved_message => 'can not be "%s"',
13
+ :scope => nil,
14
+ :strip_diacritics => false,
15
+ :strip_non_ascii => false,
16
+ :use_slug => false }.freeze
17
+
18
+ # Valid keys for has_friendly_id options.
19
+ VALID_FRIENDLY_ID_KEYS = [
20
+ :max_length,
21
+ :reserved,
22
+ :reserved_message,
23
+ :scope,
24
+ :strip_diacritics,
25
+ :strip_non_ascii,
26
+ :use_slug ].freeze
27
+
28
+ # This error is raised when it's not possible to generate a unique slug.
29
+ class SlugGenerationError < StandardError ; end
30
+
31
+ module ClassMethods
32
+
33
+ # Set up an ActiveRecord model to use a friendly_id.
34
+ #
35
+ # The column argument can be one of your model's columns, or a method
36
+ # you use to generate the slug.
37
+ #
38
+ # Options:
39
+ # * <tt>:use_slug</tt> - Defaults to false. Use slugs when you want to use a non-unique text field for friendly ids.
40
+ # * <tt>:max_length</tt> - Defaults to 255. The maximum allowed length for a slug.
41
+ # * <tt>:strip_diacritics</tt> - Defaults to false. If true, it will remove accents, umlauts, etc. from western characters.
42
+ # * <tt>:strip_non_ascii</tt> - Defaults to false. If true, it will all non-ascii ([^a-z0-9]) characters.
43
+ # * <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 be treated the same as if that slug was already taken (numeric extension will be appended). Defaults to ["new", "index"].
44
+ # * <tt>:reserved_message</tt> - The validation message that will be shown when a reserved word is used as a frindly_id. Defaults to '"%s" is reserved'.
45
+ def has_friendly_id(column, options = {}, &block)
46
+ options.assert_valid_keys VALID_FRIENDLY_ID_KEYS
47
+ options = DEFAULT_FRIENDLY_ID_OPTIONS.merge(options).merge(:column => column)
48
+ write_inheritable_attribute :friendly_id_options, options
49
+ class_inheritable_accessor :friendly_id_options
50
+ class_inheritable_reader :slug_normalizer_block
51
+
52
+ if options[:use_slug]
53
+ has_many :slugs, :order => 'id DESC', :as => :sluggable, :dependent => :destroy
54
+ require 'friendly_id/sluggable_class_methods'
55
+ require 'friendly_id/sluggable_instance_methods'
56
+ extend SluggableClassMethods
57
+ include SluggableInstanceMethods
58
+ before_save :set_slug
59
+ if block_given?
60
+ write_inheritable_attribute :slug_normalizer_block, block
61
+ end
62
+ else
63
+ require 'friendly_id/non_sluggable_class_methods'
64
+ require 'friendly_id/non_sluggable_instance_methods'
65
+ extend NonSluggableClassMethods
66
+ include NonSluggableInstanceMethods
67
+ validate_on_create :validate_friendly_id
68
+ end
69
+ end
70
+
71
+ end
72
+
73
+ class << self
74
+
75
+ # Load FriendlyId if the gem is included in a Rails app.
76
+ def enable
77
+ return if ActiveRecord::Base.methods.include? 'has_friendly_id'
78
+ ActiveRecord::Base.class_eval { extend FriendlyId::ClassMethods }
79
+ end
80
+
81
+ end
82
+
83
+ end
84
+
85
+ if defined?(ActiveRecord)
86
+ FriendlyId::enable
87
+ end
@@ -0,0 +1,48 @@
1
+ namespace :friendly_id do
2
+ desc "Make slugs for a model."
3
+ task :make_slugs => :environment do
4
+ raise 'USAGE: rake friendly_id:make_slugs MODEL=MyModelName' if ENV["MODEL"].nil?
5
+ if !sluggable_class.friendly_id_options[:use_slug]
6
+ raise "Class \"#{sluggable_class.to_s}\" doesn't appear to be using slugs"
7
+ end
8
+ while records = sluggable_class.find(:all, :include => :slugs, :conditions => "slugs.id IS NULL", :limit => 1000) do
9
+ break if records.size == 0
10
+ records.each do |r|
11
+ r.send(:set_slug)
12
+ r.save!
13
+ puts "#{sluggable_class.to_s}(#{r.id}) friendly_id set to \"#{r.slug.name}\""
14
+ end
15
+ end
16
+ end
17
+
18
+ desc "Regenereate slugs for a model."
19
+ task :redo_slugs => :environment do
20
+ raise 'USAGE: rake friendly_id:redo_slugs MODEL=MyModelName' if ENV["MODEL"].nil?
21
+ if !sluggable_class.friendly_id_options[:use_slug]
22
+ raise "Class \"#{sluggable_class.to_s}\" doesn't appear to be using slugs"
23
+ end
24
+ Slug.destroy_all(["sluggable_type = ?", sluggable_class.to_s])
25
+ Rake::Task["friendly_id:make_slugs"].invoke
26
+ end
27
+
28
+ desc "Kill obsolete slugs older than 45 days."
29
+ task :remove_old_slugs => :environment do
30
+ if ENV["DAYS"].nil?
31
+ @days = 45
32
+ else
33
+ @days = ENV["DAYS"].to_i
34
+ end
35
+ slugs = Slug.find(:all, :conditions => ["created_at < ?", DateTime.now - @days.days])
36
+ slugs.each do |s|
37
+ s.destroy if !s.is_most_recent?
38
+ end
39
+ end
40
+ end
41
+
42
+ def sluggable_class
43
+ if (ENV["MODEL"].split('::').size > 1)
44
+ ENV["MODEL"].split('::').inject(Kernel) {|scope, const_name| scope.const_get(const_name)}
45
+ else
46
+ Object.const_get(ENV["MODEL"])
47
+ end
48
+ end
@@ -0,0 +1 @@
1
+ load 'tasks/friendly_id.rake'
@@ -0,0 +1,35 @@
1
+ # encoding: utf-8
2
+
3
+ require File.dirname(__FILE__) + '/test_helper'
4
+
5
+ class CustomSlugNormalizerTest < Test::Unit::TestCase
6
+
7
+ context "A slugged model using a custom slug generator" do
8
+
9
+ setup do
10
+ Thing.friendly_id_options = FriendlyId::DEFAULT_FRIENDLY_ID_OPTIONS.merge(:column => :name, :use_slug => true)
11
+ Thing.delete_all
12
+ Slug.delete_all
13
+ end
14
+
15
+ should "invoke the block code" do
16
+ @thing = Thing.create!(:name => "test")
17
+ assert_equal "a94a8fe5ccb19ba61c4c0873d391e987982fbbd3", @thing.friendly_id
18
+ end
19
+
20
+ should "respect the max_length option" do
21
+ Thing.friendly_id_options = Thing.friendly_id_options.merge(:max_length => 10)
22
+ @thing = Thing.create!(:name => "test")
23
+ assert_equal "a94a8fe5cc", @thing.friendly_id
24
+ end
25
+
26
+ should "respect the reserved option" do
27
+ Thing.friendly_id_options = Thing.friendly_id_options.merge(:reserved => ["a94a8fe5ccb19ba61c4c0873d391e987982fbbd3"])
28
+ assert_raises FriendlyId::SlugGenerationError do
29
+ Thing.create!(:name => "test")
30
+ end
31
+ end
32
+
33
+ end
34
+
35
+ end
@@ -0,0 +1,2 @@
1
+ class Book < ActiveRecord::Base
2
+ end
@@ -0,0 +1,4 @@
1
+ class Country < ActiveRecord::Base
2
+ has_many :people
3
+ has_friendly_id :name, :use_slug => true
4
+ end
@@ -0,0 +1,3 @@
1
+ class Novel < Book
2
+ has_friendly_id :title, :use_slug => true
3
+ end
@@ -0,0 +1,6 @@
1
+ class Person < ActiveRecord::Base
2
+
3
+ belongs_to :country
4
+ has_friendly_id :name, :use_slug => true, :scope => :country
5
+
6
+ end
@@ -0,0 +1,3 @@
1
+ class Post < ActiveRecord::Base
2
+ has_friendly_id :title, :use_slug => true
3
+ end
@@ -0,0 +1,6 @@
1
+ require 'digest/sha1'
2
+ class Thing < ActiveRecord::Base
3
+ has_friendly_id :name, :use_slug => true do |text|
4
+ Digest::SHA1::hexdigest(text)
5
+ end
6
+ end
@@ -0,0 +1,3 @@
1
+ class User < ActiveRecord::Base
2
+ has_friendly_id :login
3
+ end
@@ -0,0 +1,96 @@
1
+ require File.dirname(__FILE__) + '/test_helper'
2
+
3
+ class NonSluggedTest < Test::Unit::TestCase
4
+
5
+ context "A non-slugged model with default FriendlyId options" do
6
+
7
+ setup do
8
+ User.delete_all
9
+ @user = User.create!(:login => "joe", :email => "joe@example.org")
10
+ end
11
+
12
+ should "have friendly_id options" do
13
+ assert_not_nil User.friendly_id_options
14
+ end
15
+
16
+ should "not have a slug" do
17
+ assert !@user.respond_to?(:slug)
18
+ end
19
+
20
+ should "be findable by its friendly_id" do
21
+ assert User.find(@user.friendly_id)
22
+ end
23
+
24
+ should "be findable by its regular id" do
25
+ assert User.find(@user.id)
26
+ end
27
+
28
+ should "respect finder conditions" do
29
+ assert_raises ActiveRecord::RecordNotFound do
30
+ User.find(@user.friendly_id, :conditions => "1 = 2")
31
+ end
32
+ end
33
+
34
+ should "indicate if it was found by its friendly id" do
35
+ @user = User.find(@user.friendly_id)
36
+ assert @user.found_using_friendly_id?
37
+ end
38
+
39
+ should "indicate if it was found by its numeric id" do
40
+ @user = User.find(@user.id)
41
+ assert @user.found_using_numeric_id?
42
+ end
43
+
44
+ should "indicate if it has a better id" do
45
+ @user = User.find(@user.id)
46
+ assert @user.has_better_id?
47
+ end
48
+
49
+ should "not validate if the friendly_id text is reserved" do
50
+ @user = User.new(:login => "new", :email => "test@example.org")
51
+ assert !@user.valid?
52
+ end
53
+
54
+ should "have always string for a friendly_id" do
55
+ assert_equal String, @user.to_param.class
56
+ end
57
+
58
+ should "return its id if the friendly_id is null" do
59
+ @user.login = nil
60
+ assert_equal @user.id.to_s, @user.to_param
61
+ end
62
+
63
+
64
+ context "when using an array as the find argument" do
65
+
66
+ setup do
67
+ @user2 = User.create(:login => "jane", :email => "jane@example.org")
68
+ end
69
+
70
+ should "return results" do
71
+ assert_equal 2, User.find([@user.friendly_id, @user2.friendly_id]).size
72
+ end
73
+
74
+ should "not allow mixed friendly and non-friendly ids for the same record" do
75
+ assert_raises ActiveRecord::RecordNotFound do
76
+ User.find([@user.id, @user.friendly_id]).size
77
+ end
78
+ end
79
+
80
+ should "raise an error when all records are not found" do
81
+ assert_raises ActiveRecord::RecordNotFound do
82
+ User.find(['bad', 'bad2'])
83
+ end
84
+ end
85
+
86
+ should "indicate if the results were found using a friendly_id" do
87
+ @users = User.find([@user.id, @user2.friendly_id], :order => "login ASC")
88
+ assert @users[0].found_using_friendly_id?
89
+ assert @users[1].found_using_numeric_id?
90
+ end
91
+
92
+ end
93
+
94
+ end
95
+
96
+ end