friendly_id 5.2.3 → 5.4.0

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.
Files changed (45) hide show
  1. checksums.yaml +5 -5
  2. checksums.yaml.gz.sig +0 -0
  3. data/.github/stale.yml +17 -0
  4. data/.github/workflows/test.yml +60 -0
  5. data/Changelog.md +39 -1
  6. data/Gemfile +3 -0
  7. data/README.md +54 -163
  8. data/Rakefile +2 -2
  9. data/UPGRADING.md +115 -0
  10. data/certs/parndt.pem +25 -0
  11. data/friendly_id.gemspec +7 -3
  12. data/gemfiles/Gemfile.rails-5.0.rb +2 -2
  13. data/gemfiles/{Gemfile.rails-4.2.rb → Gemfile.rails-5.1.rb} +4 -5
  14. data/gemfiles/{Gemfile.rails-4.1.rb → Gemfile.rails-5.2.rb} +5 -7
  15. data/gemfiles/{Gemfile.rails-4.0.rb → Gemfile.rails-6.0.rb} +5 -8
  16. data/lib/friendly_id/base.rb +4 -8
  17. data/lib/friendly_id/candidates.rb +0 -2
  18. data/lib/friendly_id/configuration.rb +3 -2
  19. data/lib/friendly_id/finder_methods.rb +18 -7
  20. data/lib/friendly_id/finders.rb +1 -1
  21. data/lib/friendly_id/history.rb +21 -12
  22. data/lib/friendly_id/initializer.rb +11 -0
  23. data/lib/friendly_id/migration.rb +9 -3
  24. data/lib/friendly_id/object_utils.rb +9 -2
  25. data/lib/friendly_id/scoped.rb +8 -1
  26. data/lib/friendly_id/sequentially_slugged.rb +12 -2
  27. data/lib/friendly_id/slug.rb +4 -0
  28. data/lib/friendly_id/slugged.rb +2 -2
  29. data/lib/friendly_id/version.rb +1 -1
  30. data/test/databases.yml +6 -4
  31. data/test/finders_test.rb +24 -0
  32. data/test/helper.rb +13 -3
  33. data/test/history_test.rb +86 -7
  34. data/test/numeric_slug_test.rb +31 -0
  35. data/test/object_utils_test.rb +2 -0
  36. data/test/schema.rb +19 -2
  37. data/test/scoped_test.rb +13 -0
  38. data/test/sequentially_slugged_test.rb +59 -0
  39. data/test/shared.rb +2 -2
  40. data/test/simple_i18n_test.rb +2 -2
  41. data/test/slugged_test.rb +168 -4
  42. data.tar.gz.sig +2 -0
  43. metadata +44 -15
  44. metadata.gz.sig +0 -0
  45. data/.travis.yml +0 -40
@@ -2,21 +2,20 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec path: '../'
4
4
 
5
- gem 'activerecord', '~> 4.1.9'
6
- gem 'railties', '~> 4.1.9'
5
+ gem 'activerecord', '~> 5.2.0'
6
+ gem 'railties', '~> 5.2.0'
7
7
 
8
8
  # Database Configuration
9
9
  group :development, :test do
10
10
  platforms :jruby do
11
- gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.14'
12
- gem 'activerecord-jdbcmysql-adapter', '~> 1.3.14'
13
- gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.14'
11
+ gem 'activerecord-jdbcmysql-adapter', '~> 51.1'
12
+ gem 'activerecord-jdbcpostgresql-adapter', '~> 51.1'
14
13
  gem 'kramdown'
15
14
  end
16
15
 
17
16
  platforms :ruby, :rbx do
18
17
  gem 'sqlite3'
19
- gem 'mysql2', '~> 0.3.13'
18
+ gem 'mysql2'
20
19
  gem 'pg'
21
20
  gem 'redcarpet'
22
21
  end
@@ -24,6 +23,5 @@ group :development, :test do
24
23
  platforms :rbx do
25
24
  gem 'rubysl', '~> 2.0'
26
25
  gem 'rubinius-developer_tools'
27
- gem 'json'
28
26
  end
29
27
  end
@@ -2,22 +2,20 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec path: '../'
4
4
 
5
- gem 'activerecord', '~> 4.0.13'
6
- gem 'railties', '~> 4.0.13'
7
- gem 'minitest', '~> 4.5.0'
5
+ gem 'activerecord', '~> 6.0.0'
6
+ gem 'railties', '~> 6.0.0'
8
7
 
9
8
  # Database Configuration
10
9
  group :development, :test do
11
10
  platforms :jruby do
12
- gem 'activerecord-jdbcsqlite3-adapter', '~> 1.3.14'
13
- gem 'activerecord-jdbcmysql-adapter', '~> 1.3.14'
14
- gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.14'
11
+ gem 'activerecord-jdbcmysql-adapter', '~> 51.1'
12
+ gem 'activerecord-jdbcpostgresql-adapter', '~> 51.1'
15
13
  gem 'kramdown'
16
14
  end
17
15
 
18
16
  platforms :ruby, :rbx do
19
17
  gem 'sqlite3'
20
- gem 'mysql2', '~> 0.3.10'
18
+ gem 'mysql2'
21
19
  gem 'pg'
22
20
  gem 'redcarpet'
23
21
  end
@@ -25,6 +23,5 @@ group :development, :test do
25
23
  platforms :rbx do
26
24
  gem 'rubysl', '~> 2.0'
27
25
  gem 'rubinius-developer_tools'
28
- gem 'json'
29
26
  end
30
27
  end
@@ -159,8 +159,9 @@ often better and easier to use {FriendlyId::Slugged slugs}.
159
159
  #
160
160
  # @option options [Symbol,Module] :use The addon or name of an addon to use.
161
161
  # By default, FriendlyId provides {FriendlyId::Slugged :slugged},
162
- # {FriendlyId::History :history}, {FriendlyId::Reserved :reserved}, and
163
- # {FriendlyId::Scoped :scoped}, and {FriendlyId::SimpleI18n :simple_i18n}.
162
+ # {FriendlyId::Reserved :finders}, {FriendlyId::History :history},
163
+ # {FriendlyId::Reserved :reserved}, {FriendlyId::Scoped :scoped}, and
164
+ # {FriendlyId::SimpleI18n :simple_i18n}.
164
165
  #
165
166
  # @option options [Array] :reserved_words Available when using `:reserved`,
166
167
  # which is loaded by default. Sets an array of words banned for use as
@@ -261,12 +262,7 @@ often better and easier to use {FriendlyId::Slugged slugs}.
261
262
  # Either the friendly_id, or the numeric id cast to a string.
262
263
  def to_param
263
264
  if friendly_id_config.routes == :friendly
264
- if attribute_changed?(friendly_id_config.query_field)
265
- diff = changes[friendly_id_config.query_field]
266
- diff.first || diff.second
267
- else
268
- friendly_id.presence.to_param || super
269
- end
265
+ friendly_id.presence.to_param || super
270
266
  else
271
267
  super
272
268
  end
@@ -63,8 +63,6 @@ module FriendlyId
63
63
  slug.present?
64
64
  end
65
65
 
66
- private
67
-
68
66
  def reserved?(slug)
69
67
  config = @object.friendly_id_config
70
68
  return false unless config.uses? ::FriendlyId::Reserved
@@ -25,6 +25,7 @@ module FriendlyId
25
25
  attr_accessor :routes
26
26
 
27
27
  def initialize(model_class, values = nil)
28
+ @base = nil
28
29
  @model_class = model_class
29
30
  @defaults = {}
30
31
  @modules = []
@@ -47,8 +48,8 @@ module FriendlyId
47
48
  #
48
49
  # @param [#to_s,Module] modules Arguments should be Modules, or symbols or
49
50
  # strings that correspond with the name of an addon to use with FriendlyId.
50
- # By default FriendlyId provides `:slugged`, `:history`, `:simple_i18n`,
51
- # and `:scoped`.
51
+ # By default FriendlyId provides `:slugged`, `:finders`, `:history`,
52
+ # `:reserved`, `:simple_i18n`, and `:scoped`.
52
53
  def use(*modules)
53
54
  modules.to_a.flatten.compact.map do |object|
54
55
  mod = get_module(object)
@@ -9,7 +9,7 @@ module FriendlyId
9
9
  # id matching '123' and then fall back to looking for a record with the
10
10
  # numeric id '123'.
11
11
  #
12
- # Since FriendlyId 5.0, if the id is a numeric string like '123-foo' it
12
+ # Since FriendlyId 5.0, if the id is a nonnumeric string like '123-foo' it
13
13
  # will *only* search by friendly id and not fall back to the regular find
14
14
  # method.
15
15
  #
@@ -20,20 +20,22 @@ module FriendlyId
20
20
  return super if args.count != 1 || id.unfriendly_id?
21
21
  first_by_friendly_id(id).tap {|result| return result unless result.nil?}
22
22
  return super if potential_primary_key?(id)
23
- raise ActiveRecord::RecordNotFound, "can't find record with friendly id: #{id.inspect}"
23
+ raise_not_found_exception id
24
+
24
25
  end
25
26
 
26
27
  # Returns true if a record with the given id exists.
27
28
  def exists?(conditions = :none)
28
- return super unless conditions.friendly_id?
29
- exists_by_friendly_id?(conditions)
29
+ return super if conditions.unfriendly_id?
30
+ return true if exists_by_friendly_id?(conditions)
31
+ super
30
32
  end
31
33
 
32
34
  # Finds exclusively by the friendly id, completely bypassing original
33
35
  # `find`.
34
36
  # @raise ActiveRecord::RecordNotFound
35
37
  def find_by_friendly_id(id)
36
- first_by_friendly_id(id) or raise ActiveRecord::RecordNotFound, "can't find record with friendly id: #{id.inspect}"
38
+ first_by_friendly_id(id) or raise raise_not_found_exception(id)
37
39
  end
38
40
 
39
41
  def exists_by_friendly_id?(id)
@@ -50,14 +52,23 @@ module FriendlyId
50
52
  when :integer
51
53
  Integer(id, 10) rescue false
52
54
  when :uuid
53
- id.match /\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/
55
+ id.match(/\A[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\z/)
54
56
  else
55
57
  true
56
58
  end
57
59
  end
58
60
 
59
61
  def first_by_friendly_id(id)
60
- find_by(friendly_id_config.query_field => id)
62
+ find_by(friendly_id_config.query_field => id.downcase)
63
+ end
64
+
65
+ def raise_not_found_exception(id)
66
+ message = "can't find record with friendly id: #{id.inspect}"
67
+ if ActiveRecord.version < Gem::Version.create('5.0') then
68
+ raise ActiveRecord::RecordNotFound.new(message)
69
+ else
70
+ raise ActiveRecord::RecordNotFound.new(message, name, friendly_id_config.query_field, id)
71
+ end
61
72
  end
62
73
 
63
74
  end
@@ -76,7 +76,7 @@ for models that use FriendlyId with something similar to the following:
76
76
  def self.setup(model_class)
77
77
  model_class.instance_eval do
78
78
  relation.class.send(:include, friendly_id_config.finder_methods)
79
- if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2) || ActiveRecord::VERSION::MAJOR == 5
79
+ if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2) || ActiveRecord::VERSION::MAJOR >= 5
80
80
  model_class.send(:extend, friendly_id_config.finder_methods)
81
81
  end
82
82
  end
@@ -44,9 +44,9 @@ method.
44
44
  @post = Post.friendly.find params[:id]
45
45
 
46
46
  # If an old id or a numeric id was used to find the record, then
47
- # the request path will not match the post_path, and we should do
48
- # a 301 redirect that uses the current friendly id.
49
- if request.path != post_path(@post)
47
+ # the request slug will not match the current slug, and we should do
48
+ # a 301 redirect to the new path
49
+ if params[:id] != @post.slug
50
50
  return redirect_to @post, :status => :moved_permanently
51
51
  end
52
52
  end
@@ -72,7 +72,7 @@ method.
72
72
  # Configures the model instance to use the History add-on.
73
73
  def self.included(model_class)
74
74
  model_class.class_eval do
75
- has_many :slugs, -> {order("#{Slug.quoted_table_name}.id DESC")}, {
75
+ has_many :slugs, -> {order(id: :desc)}, **{
76
76
  :as => :sluggable,
77
77
  :dependent => @friendly_id_config.dependent_value,
78
78
  :class_name => Slug.to_s
@@ -86,14 +86,13 @@ method.
86
86
  include ::FriendlyId::FinderMethods
87
87
 
88
88
  def exists_by_friendly_id?(id)
89
- where(arel_table[friendly_id_config.query_field].eq(id)).exists? || joins(:slugs).where(slug_history_clause(id)).exists?
89
+ super || joins(:slugs).where(slug_history_clause(id)).exists?
90
90
  end
91
91
 
92
92
  private
93
93
 
94
94
  def first_by_friendly_id(id)
95
- matching_record = where(friendly_id_config.query_field => id).first
96
- matching_record || slug_table_record(id)
95
+ super || slug_table_record(id)
97
96
  end
98
97
 
99
98
  def slug_table_record(id)
@@ -111,9 +110,10 @@ method.
111
110
  # to be conflicts. This will allow a record to revert to a previously
112
111
  # used slug.
113
112
  def scope_for_slug_generator
114
- relation = super
115
- return relation if new_record?
116
- relation = relation.joins(:slugs).merge(Slug.where('sluggable_id <> ?', id))
113
+ relation = super.joins(:slugs)
114
+ unless new_record?
115
+ relation = relation.merge(Slug.where('sluggable_id <> ?', id))
116
+ end
117
117
  if friendly_id_config.uses?(:scoped)
118
118
  relation = relation.where(Slug.arel_table[:scope].eq(serialized_scope))
119
119
  end
@@ -122,17 +122,26 @@ method.
122
122
 
123
123
  def create_slug
124
124
  return unless friendly_id
125
- return if slugs.first.try(:slug) == friendly_id
125
+ return if history_is_up_to_date?
126
126
  # Allow reversion back to a previously used slug
127
127
  relation = slugs.where(:slug => friendly_id)
128
128
  if friendly_id_config.uses?(:scoped)
129
129
  relation = relation.where(:scope => serialized_scope)
130
130
  end
131
- relation.delete_all
131
+ relation.destroy_all unless relation.empty?
132
132
  slugs.create! do |record|
133
133
  record.slug = friendly_id
134
134
  record.scope = serialized_scope if friendly_id_config.uses?(:scoped)
135
135
  end
136
136
  end
137
+
138
+ def history_is_up_to_date?
139
+ latest_history = slugs.first
140
+ check = latest_history.try(:slug) == friendly_id
141
+ if friendly_id_config.uses?(:scoped)
142
+ check = check && latest_history.scope == serialized_scope
143
+ end
144
+ check
145
+ end
137
146
  end
138
147
  end
@@ -18,6 +18,12 @@ FriendlyId.defaults do |config|
18
18
 
19
19
  config.reserved_words = %w(new edit index session login logout users admin
20
20
  stylesheets assets javascripts images)
21
+
22
+ # This adds an option to treat reserved words as conflicts rather than exceptions.
23
+ # When there is no good candidate, a UUID will be appended, matching the existing
24
+ # conflict behavior.
25
+
26
+ # config.treat_reserved_as_conflict = true
21
27
 
22
28
  # ## Friendly Finders
23
29
  #
@@ -76,7 +82,12 @@ FriendlyId.defaults do |config|
76
82
  # behavior by overriding the `should_generate_new_friendly_id?` method that
77
83
  # FriendlyId adds to your model. The change below makes FriendlyId 5.0 behave
78
84
  # more like 4.0.
85
+ # Note: Use(include) Slugged module in the config if using the anonymous module.
86
+ # If you have `friendly_id :name, use: slugged` in the model, Slugged module
87
+ # is included after the anonymous module defined in the initializer, so it
88
+ # overrides the `should_generate_new_friendly_id?` method from the anonymous module.
79
89
  #
90
+ # config.use :slugged
80
91
  # config.use Module.new {
81
92
  # def should_generate_new_friendly_id?
82
93
  # slug.blank? || <your_column_name_here>_changed?
@@ -1,4 +1,11 @@
1
- class CreateFriendlyIdSlugs < ActiveRecord::Migration
1
+ MIGRATION_CLASS =
2
+ if ActiveRecord::VERSION::MAJOR >= 5
3
+ ActiveRecord::Migration["#{ActiveRecord::VERSION::MAJOR}.#{ActiveRecord::VERSION::MINOR}"]
4
+ else
5
+ ActiveRecord::Migration
6
+ end
7
+
8
+ class CreateFriendlyIdSlugs < MIGRATION_CLASS
2
9
  def change
3
10
  create_table :friendly_id_slugs do |t|
4
11
  t.string :slug, :null => false
@@ -7,9 +14,8 @@ class CreateFriendlyIdSlugs < ActiveRecord::Migration
7
14
  t.string :scope
8
15
  t.datetime :created_at
9
16
  end
10
- add_index :friendly_id_slugs, :sluggable_id
17
+ add_index :friendly_id_slugs, [:sluggable_type, :sluggable_id]
11
18
  add_index :friendly_id_slugs, [:slug, :sluggable_type], length: { slug: 140, sluggable_type: 50 }
12
19
  add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], length: { slug: 70, sluggable_type: 50, scope: 70 }, unique: true
13
- add_index :friendly_id_slugs, :sluggable_type
14
20
  end
15
21
  end
@@ -2,7 +2,6 @@ module FriendlyId
2
2
  # Instances of these classes will never be considered a friendly id.
3
3
  # @see FriendlyId::ObjectUtils#friendly_id
4
4
  UNFRIENDLY_CLASSES = [
5
- ActiveRecord::Base,
6
5
  Array,
7
6
  FalseClass,
8
7
  Hash,
@@ -59,6 +58,10 @@ module FriendlyId
59
58
  true
60
59
  end
61
60
  end
61
+
62
+ def self.mark_as_unfriendly(klass)
63
+ klass.send(:include, FriendlyId::UnfriendlyUtils)
64
+ end
62
65
  end
63
66
 
64
67
  Object.send :include, FriendlyId::ObjectUtils
@@ -66,4 +69,8 @@ Object.send :include, FriendlyId::ObjectUtils
66
69
  # Considered unfriendly if object is an instance of an unfriendly class or
67
70
  # one of its descendants.
68
71
 
69
- FriendlyId::UNFRIENDLY_CLASSES.each { |klass| klass.send(:include, FriendlyId::UnfriendlyUtils) }
72
+ FriendlyId::UNFRIENDLY_CLASSES.each { |klass| FriendlyId.mark_as_unfriendly(klass) }
73
+
74
+ ActiveSupport.on_load(:active_record) do
75
+ FriendlyId.mark_as_unfriendly(ActiveRecord::Base)
76
+ end
@@ -122,7 +122,10 @@ an example of one way to set this up:
122
122
  end
123
123
 
124
124
  def scope_for_slug_generator
125
- relation = self.class.unscoped.friendly
125
+ if friendly_id_config.uses?(:History)
126
+ return super
127
+ end
128
+ relation = self.class.base_class.unscoped.friendly
126
129
  friendly_id_config.scope_columns.each do |column|
127
130
  relation = relation.where(column => send(column))
128
131
  end
@@ -136,6 +139,10 @@ an example of one way to set this up:
136
139
  end
137
140
  private :slug_generator
138
141
 
142
+ def should_generate_new_friendly_id?
143
+ (changed & friendly_id_config.scope_columns).any? || super
144
+ end
145
+
139
146
  # This module adds the `:scope` configuration option to
140
147
  # {FriendlyId::Configuration FriendlyId::Configuration}.
141
148
  module Configuration
@@ -11,7 +11,7 @@ module FriendlyId
11
11
  candidate,
12
12
  friendly_id_config.slug_column,
13
13
  friendly_id_config.sequence_separator,
14
- self.class.base_class).next_slug
14
+ slug_base_class).next_slug
15
15
  end
16
16
 
17
17
  class SequentialSlugCalculator
@@ -47,7 +47,7 @@ module FriendlyId
47
47
  def slug_conflicts
48
48
  scope.
49
49
  where(conflict_query, slug, sequential_slug_matcher).
50
- order(ordering_query).pluck(slug_column)
50
+ order(Arel.sql(ordering_query)).pluck(Arel.sql(slug_column))
51
51
  end
52
52
 
53
53
  def conflict_query
@@ -73,5 +73,15 @@ module FriendlyId
73
73
  "#{length_command}(#{slug_column}) ASC, #{slug_column} ASC"
74
74
  end
75
75
  end
76
+
77
+ private
78
+
79
+ def slug_base_class
80
+ if friendly_id_config.uses?(:history)
81
+ Slug
82
+ else
83
+ self.class.base_class
84
+ end
85
+ end
76
86
  end
77
87
  end
@@ -5,6 +5,10 @@ module FriendlyId
5
5
  class Slug < ActiveRecord::Base
6
6
  belongs_to :sluggable, :polymorphic => true
7
7
 
8
+ def sluggable
9
+ sluggable_type.constantize.unscoped { super }
10
+ end
11
+
8
12
  def to_param
9
13
  slug
10
14
  end
@@ -67,7 +67,7 @@ app's behavior and requirements.
67
67
  #### Formatting
68
68
 
69
69
  By default, FriendlyId uses Active Support's
70
- [paramaterize](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize)
70
+ [parameterize](http://api.rubyonrails.org/classes/ActiveSupport/Inflector.html#method-i-parameterize)
71
71
  method to create slugs. This method will intelligently replace spaces with
72
72
  dashes, and Unicode Latin characters with ASCII approximations:
73
73
 
@@ -375,7 +375,7 @@ Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
375
375
  private :slug_generator
376
376
 
377
377
  def unset_slug_if_invalid
378
- if errors.present? && attribute_changed?(friendly_id_config.query_field.to_s)
378
+ if errors[friendly_id_config.query_field].present? && attribute_changed?(friendly_id_config.query_field.to_s)
379
379
  diff = changes[friendly_id_config.query_field]
380
380
  send "#{friendly_id_config.slug_column}=", diff.first
381
381
  end
@@ -1,3 +1,3 @@
1
1
  module FriendlyId
2
- VERSION = '5.2.3'.freeze
2
+ VERSION = '5.4.0'.freeze
3
3
  end
data/test/databases.yml CHANGED
@@ -2,14 +2,16 @@ mysql:
2
2
  adapter: mysql2
3
3
  database: friendly_id_test
4
4
  username: root
5
- hostname: localhost
5
+ password: <%= ENV['MYSQL_PASSWORD'] %>
6
+ host: 127.0.0.1
7
+ port: 3306
6
8
  encoding: utf8
7
9
 
8
10
  postgres:
9
11
  adapter: postgresql
10
- host: localhost
11
- port: 5432
12
- username: postgres
12
+ host: <%= ENV.fetch('PGHOST') { 'localhost' } %>
13
+ port: <%= ENV.fetch('PGPORT') { '5432' } %>
14
+ username: <%= ENV.fetch('PGUSER') { 'postgres' } %>
13
15
  database: friendly_id_test
14
16
  encoding: utf8
15
17
 
data/test/finders_test.rb CHANGED
@@ -26,4 +26,28 @@ class Finders < TestCaseClass
26
26
  assert model_class.existing.find(record.friendly_id)
27
27
  end
28
28
  end
29
+
30
+ test 'should find capitalized records with finders as class methods' do
31
+ with_instance_of(model_class) do |record|
32
+ assert model_class.find(record.friendly_id.capitalize)
33
+ end
34
+ end
35
+
36
+ test 'should find capitalized records with finders on relations' do
37
+ with_instance_of(model_class) do |record|
38
+ assert model_class.existing.find(record.friendly_id.capitalize)
39
+ end
40
+ end
41
+
42
+ test 'should find upcased records with finders as class methods' do
43
+ with_instance_of(model_class) do |record|
44
+ assert model_class.find(record.friendly_id.upcase)
45
+ end
46
+ end
47
+
48
+ test 'should find upcased records with finders on relations' do
49
+ with_instance_of(model_class) do |record|
50
+ assert model_class.existing.find(record.friendly_id.upcase)
51
+ end
52
+ end
29
53
  end
data/test/helper.rb CHANGED
@@ -27,6 +27,7 @@ end
27
27
  require "mocha/setup"
28
28
  require "active_record"
29
29
  require 'active_support/core_ext/time/conversions'
30
+ require 'erb'
30
31
 
31
32
  I18n.enforce_available_locales = false
32
33
 
@@ -38,6 +39,10 @@ if ENV["LOG"]
38
39
  ActiveRecord::Base.logger = Logger.new($stdout)
39
40
  end
40
41
 
42
+ if ActiveSupport::VERSION::STRING >= '4.2'
43
+ ActiveSupport.test_order = :random
44
+ end
45
+
41
46
  module FriendlyId
42
47
  module Test
43
48
 
@@ -65,7 +70,6 @@ module FriendlyId
65
70
 
66
71
  def connect
67
72
  version = ActiveRecord::VERSION::STRING
68
- driver = FriendlyId::Test::Database.driver
69
73
  engine = RUBY_ENGINE rescue "ruby"
70
74
 
71
75
  ActiveRecord::Base.establish_connection config[driver]
@@ -82,11 +86,17 @@ module FriendlyId
82
86
  end
83
87
 
84
88
  def config
85
- @config ||= YAML::load(File.open(File.expand_path("../databases.yml", __FILE__)))
89
+ @config ||= YAML::load(
90
+ ERB.new(
91
+ File.read(File.expand_path("../databases.yml", __FILE__))
92
+ ).result
93
+ )
86
94
  end
87
95
 
88
96
  def driver
89
- (ENV["DB"] or "sqlite3").downcase
97
+ _driver = ENV.fetch('DB', 'sqlite3').downcase
98
+ _driver = "postgres" if %w(postgresql pg).include?(_driver)
99
+ _driver
90
100
  end
91
101
 
92
102
  def in_memory?