friendly_id 5.3.0 → 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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8fb8d2b37002508059b4480fe303a2ff277e4ee1264cd4dd3de6261a127aaa8d
4
- data.tar.gz: 8cc571f9b42192a2ff254ed5f134817b6b3d0d7c37bb5cd82df1493055e21830
3
+ metadata.gz: 6fa83b80901ae7c4930b4a0dea61544152f2cc4a7d94b828c2f52e807fb5d686
4
+ data.tar.gz: b5db403619e2d9bc275d567dc9f567fb943316e1222bc9c6052e43a285b92116
5
5
  SHA512:
6
- metadata.gz: 7549da1a767fefcf3cd05913fc59801d4ffe9fe1bac77429d39ad42e544dcd1a03942c74515c5eee47207269c0a7e34a48a728e1d66b2e8d4a86cb7dabe9a84b
7
- data.tar.gz: 181750c6dc3a12cb6e0948504aa2888fbd95823ee3282d2c18938eb3805cc3c86b9ddaabefd18e1d2bcaec3ea8d3e8546260caed38cf9504af768e8fa905c02d
6
+ metadata.gz: f8c8bef9ec1e0a42103fa813d40b087bcb84c1f3148f73d53d21fde568865b9a6dc0a2c83508431a2ffa2c2b09bf7f3d26e49b30ac09a758e39dd02323aff328
7
+ data.tar.gz: 0f78de10e8d9597728e554dc53949318f23a5771adb8014b23172c204f550c48b5f2222f8df144a4368d5f34560f01051a5f42183fcac415f85ad9e1bfb262e4
Binary file
@@ -0,0 +1,2 @@
1
+ �Hi�/��P:L�񔢣$�v���ҿ�Z��c�����B�C�݁�n��^���KӤ��&%�s[��oϗ*�(0&��g��⸡�3<p�X��]����Z�'�&.3f�Ȫ�,�#-�S�YF�Ԛ�_� L�N�6�W �E�dl��N �biS��f�+�� �[
2
+ eY~��˔�� O� �y~B��K8v$"O'�:�
@@ -0,0 +1,17 @@
1
+ # Number of days of inactivity before an issue becomes stale
2
+ daysUntilStale: 42
3
+ # Number of days of inactivity before a stale issue is closed
4
+ daysUntilClose: 7
5
+ # Issues with these labels will never be considered stale
6
+ exemptLabels:
7
+ - pinned
8
+ - security
9
+ # Label to use when marking an issue as stale
10
+ staleLabel: stale
11
+ # Comment to post when marking an issue as stale. Set to `false` to disable
12
+ markComment: >
13
+ This issue has been automatically marked as stale because it has not had
14
+ recent activity. It will be closed if no further activity occurs. Thank you
15
+ for your contributions.
16
+ # Comment to post when closing a stale issue. Set to `false` to disable
17
+ closeComment: false
@@ -0,0 +1,60 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - 'master'
7
+ pull_request:
8
+ jobs:
9
+ test:
10
+ strategy:
11
+ matrix:
12
+ architecture: [ x64 ]
13
+ database: [ mysql, postgresql ]
14
+ gemfile: [ '6.0', '5.2', '5.1', '5.0' ]
15
+ ruby: [ '2.6.x', '2.5.x' ]
16
+ fail-fast: false
17
+ runs-on: ubuntu-latest
18
+ name: ${{ matrix.ruby }} ${{ matrix.database }} rails-${{ matrix.gemfile }}
19
+ steps:
20
+ - uses: actions/setup-ruby@v1.0.0
21
+ with:
22
+ architecture: ${{ matrix.architecture }}
23
+ ruby-version: ${{ matrix.ruby }}
24
+ version: ${{ matrix.ruby }}
25
+ - uses: actions/checkout@v1
26
+ - run: sudo apt-get update && sudo apt-get install libpq-dev postgresql-client libmysqlclient-dev mysql-client libsqlite3-dev -y
27
+ - id: cache-bundler
28
+ uses: actions/cache@v1
29
+ with:
30
+ path: vendor/bundle
31
+ key: ${{ matrix.ruby }}-gem-${{ hashFiles(format('gemfiles/Gemfile.rails-{0}.rb', matrix.gemfile)) }}
32
+ - run: gem install bundler
33
+ - run: bundle install --path vendor/bundle
34
+ - run: bundle exec rake db:create db:up
35
+ - run: bundle exec rake test
36
+
37
+ env:
38
+ BUNDLE_JOBS: 4
39
+ BUNDLE_GEMFILE: gemfiles/Gemfile.rails-${{ matrix.gemfile }}.rb
40
+ BUNDLE_PATH: vendor/bundle
41
+ CI: true
42
+ COVERALLS: true
43
+ DB: ${{ matrix.database }}
44
+ MYSQL_PASSWORD: root
45
+ PGHOST: localhost
46
+ PGPORT: 5432
47
+ PGUSER: postgres
48
+ RAILS_ENV: test
49
+
50
+ services:
51
+ postgres:
52
+ image: postgres:11.5
53
+ ports: ["5432:5432"]
54
+ options: --health-cmd pg_isready --health-interval 10s --health-timeout 5s --health-retries 5
55
+ mysql:
56
+ image: mysql:5.7
57
+ ports: ["3306:3306"]
58
+ options: --health-cmd "mysqladmin ping" --health-interval 10s --health-timeout 5s --health-retries 5
59
+ env:
60
+ MYSQL_ROOT_PASSWORD: root
@@ -3,6 +3,17 @@
3
3
  We would like to think our many [contributors](https://github.com/norman/friendly_id/graphs/contributors) for
4
4
  suggestions, ideas and improvements to FriendlyId.
5
5
 
6
+ ## Unreleased
7
+
8
+ ## 5.4.0 (2020-08-14)
9
+
10
+ * Fix Ruby 2.7 keyword params deprecation warning ([#939](https://github.com/norman/friendly_id/pull/939))
11
+ * Fix Slug Validation in `unset_slug_if_invalid` ([#938](https://github.com/norman/friendly_id/pull/938))
12
+ * Make `first_by_friendly_id` case insensitive using `downcase` ([#787](https://github.com/norman/friendly_id/pull/787))
13
+ * Use `destroy_all` rather than `delete_all` when creating historical slugs ([#924](https://github.com/norman/friendly_id/pull/924))
14
+ * Set required ruby version to `>= 2.1.0` ([#923](https://github.com/norman/friendly_id/pull/923))
15
+ * Avoid using deprecated `update_attributes` ([#922](https://github.com/norman/friendly_id/pull/922))
16
+
6
17
  ## 5.3.0 (2019-09-25)
7
18
 
8
19
  * Record history when scope changes but slug does not ([#916](https://github.com/norman/friendly_id/pull/916))
data/Gemfile CHANGED
@@ -2,6 +2,8 @@ source 'https://rubygems.org'
2
2
 
3
3
  gemspec
4
4
 
5
+ gem 'rake'
6
+
5
7
  group :development, :test do
6
8
  platforms :ruby do
7
9
  gem 'byebug'
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- [![Build Status](https://travis-ci.org/norman/friendly_id.svg)](https://travis-ci.org/norman/friendly_id)
1
+ [![Build Status](https://github.com/norman/friendly_id/workflows/CI/badge.svg)](https://github.com/norman/friendly_id/actions)
2
2
  [![Code Climate](https://codeclimate.com/github/norman/friendly_id.svg)](https://codeclimate.com/github/norman/friendly_id)
3
3
  [![Inline docs](http://inch-ci.org/github/norman/friendly_id.svg?branch=master)](http://inch-ci.org/github/norman/friendly_id)
4
4
 
@@ -95,7 +95,7 @@ User.create! name: "Joe Schmoe"
95
95
  You can then access the user show page using the URL http://localhost:3000/users/joe-schmoe.
96
96
 
97
97
 
98
- If you're adding FriendlyId to an existing app and need to generate slugs for
98
+ If you're adding FriendlyId to an existing app and need to generate slugs for
99
99
  existing users, do this from the console, runner, or add a Rake task:
100
100
 
101
101
  ```ruby
data/Rakefile CHANGED
@@ -71,7 +71,7 @@ namespace :db do
71
71
  driver = FriendlyId::Test::Database.driver
72
72
  config = FriendlyId::Test::Database.config[driver]
73
73
  commands = {
74
- "mysql" => "mysql -u #{config['username']} -e 'create database #{config["database"]};' >/dev/null",
74
+ "mysql" => "mysql -h #{config['host']} -P #{config['port']} -u #{config['username']} --password=#{config['password']} -e 'create database #{config["database"]};' >/dev/null",
75
75
  "postgres" => "psql -c 'create database #{config['database']};' -U #{config['username']} >/dev/null"
76
76
  }
77
77
  %x{#{commands[driver] || true}}
@@ -83,7 +83,7 @@ namespace :db do
83
83
  driver = FriendlyId::Test::Database.driver
84
84
  config = FriendlyId::Test::Database.config[driver]
85
85
  commands = {
86
- "mysql" => "mysql -u #{config['username']} -e 'drop database #{config["database"]};' >/dev/null",
86
+ "mysql" => "mysql -h #{config['host']} -P #{config['port']} -u #{config['username']} --password=#{config['password']} -e 'drop database #{config["database"]};' >/dev/null",
87
87
  "postgres" => "psql -c 'drop database #{config['database']};' -U #{config['username']} >/dev/null"
88
88
  }
89
89
  %x{#{commands[driver] || true}}
@@ -0,0 +1,25 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEMjCCApqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhnZW1z
3
+ L0RDPXAvREM9YXJuZHQvREM9aW8wHhcNMjAwNTEwMjIxOTQ2WhcNMjEwNTEwMjIx
4
+ OTQ2WjAjMSEwHwYDVQQDDBhnZW1zL0RDPXAvREM9YXJuZHQvREM9aW8wggGiMA0G
5
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDT+JzHYPGMYJt9ct2DCsbIymn1uJJp
6
+ HnDkQESfsGe40jTC90oF2iVbVOkaacNc1N3CSWUZvZjuygUuS86P6/kpBILGdO2+
7
+ bkXXKtfGC2YGGx9TdNLpCb4925vQHvdFeKXGpQDZdDw1SNC6zraZou47CvOE1cl2
8
+ Bp+1QMZuGRZ4+5CzOEWDWurjqce3O1jUEbyBB7z5H0h/YEaxfXipxhL1Dhi0sgkH
9
+ qP/e6SxzifdifdZCksJFQ06a1ji9hJY6eM23qbv/aaluVHAZSVBAQBS7rYniLo+N
10
+ G4vpFhoubQO5u8UluUtCaPUpI/qOvVcSaZn3ZkzlMwC8b1RwAeXBQmtFE2wnrv2i
11
+ ovTwoN7rHchwhgaHbkuFh4Wr92wGbrWL7J+X8rWKk1f8RF4kvtNE/NA6YrkxTpVh
12
+ QMyDmekt7rTxvcq2NneLGroWIUVCx/JID+Jw492LKQ6Sl1/P2TRzdEDtqZAZL0gt
13
+ xlWeMUfGG2D/gLnhs5qnaFaWQwGTmBnTgHcCAwEAAaNxMG8wCQYDVR0TBAIwADAL
14
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEqtAyQVxPgKsrgoTQ1YmaIu/fmvMBoGA1Ud
15
+ EQQTMBGBD2dlbXNAcC5hcm5kdC5pbzAaBgNVHRIEEzARgQ9nZW1zQHAuYXJuZHQu
16
+ aW8wDQYJKoZIhvcNAQELBQADggGBALu2HM50B8xqlAXkCwavJDvWWtV9pG1igFUg
17
+ friZRWprUQ5nTaNmAd8p8qbJQwaIK2gt+DfYWfB9LtKnQTfbhLRBbmJ7zYw8LjKY
18
+ PwCs4RWjDAiuyCO3ppfsz+1bsMUXPLgWlaUkXsUy3nr2NruEFTO9zu3wGYQQ93Tt
19
+ vYSHOnP35UB4QjsjNrOO7FBaQfy6O909PP+GnVcJ62s9c26voJz63RSolwY7Jydw
20
+ XUlG68jjJKSoDHRzVTmNB7sX8rs8P2kvYkpIUXPHyls3mWBWjBWbdEYWESZrxI2x
21
+ dS7jY3AnfqhvsWra2pSREb2IDqPnJrHVOejnEI/zuuufUxLwDx3AC6SMdsyWkZ7V
22
+ 9OmLt2rg75Sct6h2220lO5ySqYtqAXuOMBDGv5L0zLalx1g8LACA7uILTKVWh8B8
23
+ Hsej0MQ3drCB1eA4c9OXdCUQJnY2aLTq3uNvTbZvoTgWK55eq3KLBJ4zzoKZ4tBX
24
+ /HIFI/fEwYlI1Ji3oikUrHkc4rWgaQ==
25
+ -----END CERTIFICATE-----
@@ -13,7 +13,7 @@ Gem::Specification.new do |s|
13
13
  s.require_paths = ["lib"]
14
14
  s.license = 'MIT'
15
15
 
16
- s.required_ruby_version = '>= 1.9.3'
16
+ s.required_ruby_version = '>= 2.1.0'
17
17
 
18
18
  s.add_dependency 'activerecord', '>= 4.0.0'
19
19
 
@@ -31,4 +31,9 @@ FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
31
31
  Active Record. It lets you create pretty URLs and work with human-friendly
32
32
  strings as if they were numeric ids.
33
33
  EOM
34
+
35
+ s.cert_chain = [File.expand_path('certs/parndt.pem', __dir__)]
36
+ if $PROGRAM_NAME =~ /gem\z/ && ARGV.include?('build') && ARGV.include?(__FILE__)
37
+ s.signing_key = File.expand_path('~/.ssh/gem-private_key.pem')
38
+ end
34
39
  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
@@ -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)
@@ -59,7 +59,7 @@ module FriendlyId
59
59
  end
60
60
 
61
61
  def first_by_friendly_id(id)
62
- find_by(friendly_id_config.query_field => id)
62
+ find_by(friendly_id_config.query_field => id.downcase)
63
63
  end
64
64
 
65
65
  def raise_not_found_exception(id)
@@ -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(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
@@ -128,7 +128,7 @@ method.
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)
@@ -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.3.0'.freeze
2
+ VERSION = '5.4.0'.freeze
3
3
  end
@@ -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
 
@@ -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
@@ -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
 
@@ -85,7 +86,11 @@ module FriendlyId
85
86
  end
86
87
 
87
88
  def config
88
- @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
+ )
89
94
  end
90
95
 
91
96
  def driver
@@ -65,8 +65,7 @@ class HistoryTest < TestCaseClass
65
65
  test "should not be read only when found by slug" do
66
66
  with_instance_of(model_class) do |record|
67
67
  refute model_class.friendly.find(record.friendly_id).readonly?
68
- assert record.update_attribute :name, 'foo'
69
- assert record.update_attributes name: 'foo'
68
+ assert record.update name: 'foo'
70
69
  end
71
70
  end
72
71
 
@@ -93,6 +92,28 @@ class HistoryTest < TestCaseClass
93
92
  end
94
93
  end
95
94
 
95
+ test 'should maintain history even if current slug is not the most recent one' do
96
+ with_instance_of(model_class) do |record|
97
+ record.name = 'current'
98
+ assert record.save
99
+
100
+ # this feels like a hack. only thing i can get to work with the HistoryTestWithSti
101
+ # test cases. (Editorialist vs Journalist.)
102
+ sluggable_type = FriendlyId::Slug.first.sluggable_type
103
+ # create several slugs for record
104
+ # current slug does not have max id
105
+ FriendlyId::Slug.delete_all
106
+ FriendlyId::Slug.create(sluggable_type: sluggable_type, sluggable_id: record.id, slug: 'current')
107
+ FriendlyId::Slug.create(sluggable_type: sluggable_type, sluggable_id: record.id, slug: 'outdated')
108
+
109
+ record.reload
110
+ record.slug = nil
111
+ assert record.save
112
+
113
+ assert_equal 2, FriendlyId::Slug.count
114
+ end
115
+ end
116
+
96
117
  test "should not create new slugs that match old slugs" do
97
118
  transaction do
98
119
  first_record = model_class.create! :name => "foo"
@@ -109,10 +130,10 @@ class HistoryTest < TestCaseClass
109
130
  first_record = model_class.create! :name => "foo"
110
131
  second_record = model_class.create! :name => 'another'
111
132
 
112
- second_record.update_attributes :name => 'foo', :slug => nil
133
+ second_record.update :name => 'foo', :slug => nil
113
134
  assert_match(/foo-.*/, second_record.slug)
114
135
 
115
- first_record.update_attributes :name => 'another', :slug => nil
136
+ first_record.update :name => 'another', :slug => nil
116
137
  assert_match(/another-.*/, first_record.slug)
117
138
  end
118
139
  end
@@ -230,7 +251,7 @@ if ActiveRecord::VERSION::STRING >= '5.0'
230
251
  record = model_class.create(name: 'paranoid')
231
252
  assert FriendlyId::Slug.find_by_slug('paranoid').present?
232
253
 
233
- record.update_attribute(:deleted_at, Time.now)
254
+ record.update deleted_at: Time.now
234
255
 
235
256
  orphan_slug = FriendlyId::Slug.find_by_slug('paranoid')
236
257
  assert orphan_slug.present?, 'Orphaned slug should exist'
@@ -62,7 +62,7 @@ module FriendlyId
62
62
  my_model_class = Class.new(model_class)
63
63
  self.class.const_set("Foo", my_model_class)
64
64
  with_instance_of my_model_class do |record|
65
- record.update_attributes my_model_class.friendly_id_config.slug_column => nil
65
+ record.update my_model_class.friendly_id_config.slug_column => nil
66
66
  record = my_model_class.friendly.find(record.id)
67
67
  record.class.validate Proc.new {errors.add(:name, "FAIL")}
68
68
  record.save
@@ -132,7 +132,7 @@ module FriendlyId
132
132
  test "updating record's other values should not change the friendly_id" do
133
133
  with_instance_of model_class do |record|
134
134
  old = record.friendly_id
135
- record.update_attributes! :active => false
135
+ record.update! active: false
136
136
  assert model_class.friendly.find old
137
137
  end
138
138
  end
@@ -91,14 +91,14 @@ class SimpleI18nTest < TestCaseClass
91
91
  class RegressionTest < TestCaseClass
92
92
  include FriendlyId::Test
93
93
 
94
- test "should not overwrite other locale's slugs on update_attributes" do
94
+ test "should not overwrite other locale's slugs on update" do
95
95
  transaction do
96
96
  journalist = Journalist.create!(:name => "John Smith")
97
97
  journalist.set_friendly_id("Juan Fulano", :es)
98
98
  journalist.save!
99
99
  assert_equal "john-smith", journalist.to_param
100
100
  journalist.slug = nil
101
- journalist.update_attributes :name => "Johnny Smith"
101
+ journalist.update :name => "Johnny Smith"
102
102
  assert_equal "johnny-smith", journalist.to_param
103
103
  I18n.with_locale(:es) do
104
104
  assert_equal "juan-fulano", journalist.to_param
@@ -92,7 +92,7 @@ class SluggedTest < TestCaseClass
92
92
  end
93
93
  end
94
94
 
95
- test "should not set slug on create if unrelated validations fail" do
95
+ test "should set slug on create if unrelated validations fail" do
96
96
  klass = Class.new model_class do
97
97
  validates_presence_of :active
98
98
  friendly_id :name, :use => :slugged
@@ -106,11 +106,30 @@ class SluggedTest < TestCaseClass
106
106
  instance = klass.new :name => 'foo'
107
107
  refute instance.save
108
108
  refute instance.valid?
109
+ assert_equal 'foo', instance.slug
110
+ end
111
+ end
112
+
113
+ test "should not set slug on create if slug validation fails" do
114
+ klass = Class.new model_class do
115
+ validates_presence_of :active
116
+ validates_length_of :slug, :minimum => 2
117
+ friendly_id :name, :use => :slugged
118
+
119
+ def self.name
120
+ "Journalist"
121
+ end
122
+ end
123
+
124
+ transaction do
125
+ instance = klass.new :name => 'x'
126
+ refute instance.save
127
+ refute instance.valid?
109
128
  assert_nil instance.slug
110
129
  end
111
130
  end
112
131
 
113
- test "should not set slug on create if unrelated validations fail with custom slug_column" do
132
+ test "should set slug on create if unrelated validations fail with custom slug_column" do
114
133
  klass = Class.new(ActiveRecord::Base) do
115
134
  self.table_name = 'authors'
116
135
  extend FriendlyId
@@ -126,11 +145,31 @@ class SluggedTest < TestCaseClass
126
145
  instance = klass.new :name => 'foo'
127
146
  refute instance.save
128
147
  refute instance.valid?
148
+ assert_equal 'foo', instance.subdomain
149
+ end
150
+ end
151
+
152
+ test "should not set slug on create if custom slug column validations fail" do
153
+ klass = Class.new(ActiveRecord::Base) do
154
+ self.table_name = 'authors'
155
+ extend FriendlyId
156
+ validates_length_of :subdomain, :minimum => 2
157
+ friendly_id :name, :use => :slugged, :slug_column => :subdomain
158
+
159
+ def self.name
160
+ "Author"
161
+ end
162
+ end
163
+
164
+ transaction do
165
+ instance = klass.new :name => 'x'
166
+ refute instance.save
167
+ refute instance.valid?
129
168
  assert_nil instance.subdomain
130
169
  end
131
170
  end
132
171
 
133
- test "should not update slug on save if unrelated validations fail" do
172
+ test "should keep new slug on save if unrelated validations fail" do
134
173
  klass = Class.new model_class do
135
174
  validates_presence_of :active
136
175
  friendly_id :name, :use => :slugged
@@ -149,6 +188,28 @@ class SluggedTest < TestCaseClass
149
188
  instance.active = nil
150
189
  refute instance.save
151
190
  refute instance.valid?
191
+ assert_equal 'foobar', instance.slug
192
+ end
193
+ end
194
+
195
+ test "should not update slug on save if slug validations fail" do
196
+ klass = Class.new model_class do
197
+ validates_length_of :slug, :minimum => 2
198
+ friendly_id :name, :use => :slugged
199
+
200
+ def self.name
201
+ "Journalist"
202
+ end
203
+ end
204
+
205
+ transaction do
206
+ instance = klass.new :name => 'foo', :active => true
207
+ assert instance.save
208
+ assert instance.valid?
209
+ instance.name = 'x'
210
+ instance.slug = nil
211
+ instance.active = nil
212
+ refute instance.save
152
213
  assert_equal 'foo', instance.slug
153
214
  end
154
215
  end
@@ -425,6 +486,7 @@ class ToParamTest < TestCaseClass
425
486
  class Journalist < ActiveRecord::Base
426
487
  extend FriendlyId
427
488
  validates_presence_of :active
489
+ validates_length_of :slug, :minimum => 2
428
490
  friendly_id :name, :use => :slugged
429
491
 
430
492
  attr_accessor :to_param_in_callback
@@ -438,9 +500,21 @@ class ToParamTest < TestCaseClass
438
500
  assert_nil Journalist.new.to_param
439
501
  end
440
502
 
441
- test "to_param should return nil if record failed validation" do
503
+ test "to_param should return original slug if record failed validation" do
442
504
  journalist = Journalist.new :name => 'Clark Kent', :active => nil
443
505
  refute journalist.save
506
+ assert_equal 'clark-kent', journalist.to_param
507
+ end
508
+
509
+ test "to_param should clear slug attributes if slug attribute fails validation" do
510
+ journalist = Journalist.new :name => 'x', :active => true
511
+ refute journalist.save
512
+ assert_nil journalist.to_param
513
+ end
514
+
515
+ test "to_param should clear slug attribute if slug attribute fails validation and unrelated validation fails" do
516
+ journalist = Journalist.new :name => 'x', :active => nil
517
+ refute journalist.save
444
518
  assert_nil journalist.to_param
445
519
  end
446
520
 
@@ -452,7 +526,7 @@ class ToParamTest < TestCaseClass
452
526
  end
453
527
  end
454
528
 
455
- test "to_param should use original slug if existing record changes but fails to save" do
529
+ test "to_param should use new slug if existing record changes but fails to save" do
456
530
  transaction do
457
531
  journalist = Journalist.new :name => 'Clark Kent', :active => true
458
532
  assert journalist.save
@@ -460,6 +534,18 @@ class ToParamTest < TestCaseClass
460
534
  journalist.slug = nil
461
535
  journalist.active = nil
462
536
  refute journalist.save
537
+ assert_equal 'superman', journalist.to_param
538
+ end
539
+ end
540
+
541
+ test "to_param should use original slug if new slug attribute is not valid" do
542
+ transaction do
543
+ journalist = Journalist.new :name => 'Clark Kent', :active => true
544
+ assert journalist.save
545
+ journalist.name = 'x'
546
+ journalist.slug = nil
547
+ journalist.active = nil
548
+ refute journalist.save
463
549
  assert_equal 'clark-kent', journalist.to_param
464
550
  end
465
551
  end
metadata CHANGED
@@ -1,15 +1,41 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friendly_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.3.0
4
+ version: 5.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Norman Clarke
8
8
  - Philip Arndt
9
- autorequire:
9
+ autorequire:
10
10
  bindir: bin
11
- cert_chain: []
12
- date: 2019-09-24 00:00:00.000000000 Z
11
+ cert_chain:
12
+ - |
13
+ -----BEGIN CERTIFICATE-----
14
+ MIIEMjCCApqgAwIBAgIBATANBgkqhkiG9w0BAQsFADAjMSEwHwYDVQQDDBhnZW1z
15
+ L0RDPXAvREM9YXJuZHQvREM9aW8wHhcNMjAwNTEwMjIxOTQ2WhcNMjEwNTEwMjIx
16
+ OTQ2WjAjMSEwHwYDVQQDDBhnZW1zL0RDPXAvREM9YXJuZHQvREM9aW8wggGiMA0G
17
+ CSqGSIb3DQEBAQUAA4IBjwAwggGKAoIBgQDT+JzHYPGMYJt9ct2DCsbIymn1uJJp
18
+ HnDkQESfsGe40jTC90oF2iVbVOkaacNc1N3CSWUZvZjuygUuS86P6/kpBILGdO2+
19
+ bkXXKtfGC2YGGx9TdNLpCb4925vQHvdFeKXGpQDZdDw1SNC6zraZou47CvOE1cl2
20
+ Bp+1QMZuGRZ4+5CzOEWDWurjqce3O1jUEbyBB7z5H0h/YEaxfXipxhL1Dhi0sgkH
21
+ qP/e6SxzifdifdZCksJFQ06a1ji9hJY6eM23qbv/aaluVHAZSVBAQBS7rYniLo+N
22
+ G4vpFhoubQO5u8UluUtCaPUpI/qOvVcSaZn3ZkzlMwC8b1RwAeXBQmtFE2wnrv2i
23
+ ovTwoN7rHchwhgaHbkuFh4Wr92wGbrWL7J+X8rWKk1f8RF4kvtNE/NA6YrkxTpVh
24
+ QMyDmekt7rTxvcq2NneLGroWIUVCx/JID+Jw492LKQ6Sl1/P2TRzdEDtqZAZL0gt
25
+ xlWeMUfGG2D/gLnhs5qnaFaWQwGTmBnTgHcCAwEAAaNxMG8wCQYDVR0TBAIwADAL
26
+ BgNVHQ8EBAMCBLAwHQYDVR0OBBYEFEqtAyQVxPgKsrgoTQ1YmaIu/fmvMBoGA1Ud
27
+ EQQTMBGBD2dlbXNAcC5hcm5kdC5pbzAaBgNVHRIEEzARgQ9nZW1zQHAuYXJuZHQu
28
+ aW8wDQYJKoZIhvcNAQELBQADggGBALu2HM50B8xqlAXkCwavJDvWWtV9pG1igFUg
29
+ friZRWprUQ5nTaNmAd8p8qbJQwaIK2gt+DfYWfB9LtKnQTfbhLRBbmJ7zYw8LjKY
30
+ PwCs4RWjDAiuyCO3ppfsz+1bsMUXPLgWlaUkXsUy3nr2NruEFTO9zu3wGYQQ93Tt
31
+ vYSHOnP35UB4QjsjNrOO7FBaQfy6O909PP+GnVcJ62s9c26voJz63RSolwY7Jydw
32
+ XUlG68jjJKSoDHRzVTmNB7sX8rs8P2kvYkpIUXPHyls3mWBWjBWbdEYWESZrxI2x
33
+ dS7jY3AnfqhvsWra2pSREb2IDqPnJrHVOejnEI/zuuufUxLwDx3AC6SMdsyWkZ7V
34
+ 9OmLt2rg75Sct6h2220lO5ySqYtqAXuOMBDGv5L0zLalx1g8LACA7uILTKVWh8B8
35
+ Hsej0MQ3drCB1eA4c9OXdCUQJnY2aLTq3uNvTbZvoTgWK55eq3KLBJ4zzoKZ4tBX
36
+ /HIFI/fEwYlI1Ji3oikUrHkc4rWgaQ==
37
+ -----END CERTIFICATE-----
38
+ date: 2020-08-13 00:00:00.000000000 Z
13
39
  dependencies:
14
40
  - !ruby/object:Gem::Dependency
15
41
  name: activerecord
@@ -149,8 +175,9 @@ extensions: []
149
175
  extra_rdoc_files: []
150
176
  files:
151
177
  - ".gemtest"
178
+ - ".github/stale.yml"
179
+ - ".github/workflows/test.yml"
152
180
  - ".gitignore"
153
- - ".travis.yml"
154
181
  - ".yardopts"
155
182
  - CONTRIBUTING.md
156
183
  - Changelog.md
@@ -160,10 +187,8 @@ files:
160
187
  - Rakefile
161
188
  - UPGRADING.md
162
189
  - bench.rb
190
+ - certs/parndt.pem
163
191
  - friendly_id.gemspec
164
- - gemfiles/Gemfile.rails-4.0.rb
165
- - gemfiles/Gemfile.rails-4.1.rb
166
- - gemfiles/Gemfile.rails-4.2.rb
167
192
  - gemfiles/Gemfile.rails-5.0.rb
168
193
  - gemfiles/Gemfile.rails-5.1.rb
169
194
  - gemfiles/Gemfile.rails-5.2.rb
@@ -214,7 +239,7 @@ homepage: https://github.com/norman/friendly_id
214
239
  licenses:
215
240
  - MIT
216
241
  metadata: {}
217
- post_install_message:
242
+ post_install_message:
218
243
  rdoc_options: []
219
244
  require_paths:
220
245
  - lib
@@ -222,15 +247,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
222
247
  requirements:
223
248
  - - ">="
224
249
  - !ruby/object:Gem::Version
225
- version: 1.9.3
250
+ version: 2.1.0
226
251
  required_rubygems_version: !ruby/object:Gem::Requirement
227
252
  requirements:
228
253
  - - ">="
229
254
  - !ruby/object:Gem::Version
230
255
  version: '0'
231
256
  requirements: []
232
- rubygems_version: 3.0.3
233
- signing_key:
257
+ rubygems_version: 3.1.2
258
+ signing_key:
234
259
  specification_version: 4
235
260
  summary: A comprehensive slugging and pretty-URL plugin.
236
261
  test_files: []
Binary file
@@ -1,96 +0,0 @@
1
- language: ruby
2
- cache: bundler
3
- services:
4
- - postgresql
5
- - mysql
6
- dist: trusty
7
- addons:
8
- postgresql: "9.6"
9
- rvm:
10
- - 2.6.3
11
- - 2.5.5
12
- - 2.4.6
13
- - 2.3.8
14
- - 2.2.0
15
- - 2.1.0
16
- - jruby-9.1.13.0
17
-
18
- env:
19
- global:
20
- - COVERALLS=true
21
- matrix:
22
- - DB=postgres
23
- - DB=mysql
24
-
25
- gemfile:
26
- - gemfiles/Gemfile.rails-4.0.rb
27
- - gemfiles/Gemfile.rails-4.1.rb
28
- - gemfiles/Gemfile.rails-4.2.rb
29
- - gemfiles/Gemfile.rails-5.0.rb
30
- - gemfiles/Gemfile.rails-5.1.rb
31
- - gemfiles/Gemfile.rails-5.2.rb
32
- - gemfiles/Gemfile.rails-6.0.rb
33
-
34
- before_install:
35
- - gem update bundler
36
-
37
- matrix:
38
- exclude:
39
- - rvm: 2.1.0
40
- gemfile: gemfiles/Gemfile.rails-5.2.rb
41
- - rvm: 2.1.0
42
- gemfile: gemfiles/Gemfile.rails-6.0.rb
43
- - rvm: 2.2.0
44
- gemfile: gemfiles/Gemfile.rails-5.2.rb
45
- - rvm: 2.2.0
46
- gemfile: gemfiles/Gemfile.rails-6.0.rb
47
- - rvm: jruby-9.1.13.0
48
- gemfile: gemfiles/Gemfile.rails-5.2.rb
49
- - rvm: jruby-9.1.13.0
50
- gemfile: gemfiles/Gemfile.rails-6.0.rb
51
- - rvm: 2.1.0
52
- gemfile: gemfiles/Gemfile.rails-5.0.rb
53
- - rvm: 2.1.0
54
- gemfile: gemfiles/Gemfile.rails-5.1.rb
55
- - rvm: 2.1.0
56
- gemfile: gemfiles/Gemfile.rails-6.0.rb
57
- - rvm: 2.2.0
58
- gemfile: gemfiles/Gemfile.rails-5.1.rb
59
- - rvm: 2.2.0
60
- gemfile: gemfiles/Gemfile.rails-5.0.rb
61
- - rvm: 2.2.0
62
- gemfile: gemfiles/Gemfile.rails-6.0.rb
63
- - rvm: 2.3.8
64
- gemfile: gemfiles/Gemfile.rails-6.0.rb
65
- - rvm: 2.4.6
66
- gemfile: gemfiles/Gemfile.rails-4.0.rb
67
- - rvm: 2.4.6
68
- gemfile: gemfiles/Gemfile.rails-4.1.rb
69
- - rvm: 2.4.6
70
- gemfile: gemfiles/Gemfile.rails-6.0.rb
71
- - rvm: 2.5.5
72
- gemfile: gemfiles/Gemfile.rails-4.0.rb
73
- - rvm: 2.5.5
74
- gemfile: gemfiles/Gemfile.rails-4.1.rb
75
- - rvm: 2.5.5
76
- gemfile: gemfiles/Gemfile.rails-5.0.rb
77
- - rvm: 2.5.5
78
- gemfile: gemfiles/Gemfile.rails-5.1.rb
79
- - rvm: 2.6.3
80
- gemfile: gemfiles/Gemfile.rails-4.0.rb
81
- - rvm: 2.6.3
82
- gemfile: gemfiles/Gemfile.rails-4.1.rb
83
- - rvm: 2.6.3
84
- gemfile: gemfiles/Gemfile.rails-5.0.rb
85
- - rvm: 2.6.3
86
- gemfile: gemfiles/Gemfile.rails-5.1.rb
87
- allow_failures:
88
- - rvm: jruby-9.1.13.0
89
- gemfile: gemfiles/Gemfile.rails-5.1.rb
90
- - rvm: jruby-9.1.13.0
91
- gemfile: gemfiles/Gemfile.rails-5.0.rb
92
-
93
- before_script:
94
- - bundle exec rake db:create db:up
95
-
96
- script: 'bundle exec rake test'
@@ -1,30 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '../'
4
-
5
- gem 'activerecord', '~> 4.0.13'
6
- gem 'railties', '~> 4.0.13'
7
- gem 'minitest', '~> 4.5.0'
8
-
9
- # Database Configuration
10
- group :development, :test do
11
- 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'
15
- gem 'kramdown'
16
- end
17
-
18
- platforms :ruby, :rbx do
19
- gem 'sqlite3'
20
- gem 'mysql2', '~> 0.3.10'
21
- gem 'pg', '~> 0.15'
22
- gem 'redcarpet'
23
- end
24
-
25
- platforms :rbx do
26
- gem 'rubysl', '~> 2.0'
27
- gem 'rubinius-developer_tools'
28
- gem 'json'
29
- end
30
- end
@@ -1,29 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '../'
4
-
5
- gem 'activerecord', '~> 4.1.9'
6
- gem 'railties', '~> 4.1.9'
7
-
8
- # Database Configuration
9
- group :development, :test do
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'
14
- gem 'kramdown'
15
- end
16
-
17
- platforms :ruby, :rbx do
18
- gem 'sqlite3'
19
- gem 'mysql2', '~> 0.3.13'
20
- gem 'pg', '~> 0.15'
21
- gem 'redcarpet'
22
- end
23
-
24
- platforms :rbx do
25
- gem 'rubysl', '~> 2.0'
26
- gem 'rubinius-developer_tools'
27
- gem 'json'
28
- end
29
- end
@@ -1,28 +0,0 @@
1
- source 'https://rubygems.org'
2
-
3
- gemspec path: '../'
4
-
5
- gem 'activerecord', '~> 4.2.1'
6
- gem 'railties', '~> 4.2.1'
7
- gem 'i18n', '~> 0.7.0'
8
-
9
- # Database Configuration
10
- group :development, :test do
11
- platforms :jruby do
12
- gem 'activerecord-jdbcmysql-adapter', '~> 1.3.14'
13
- gem 'activerecord-jdbcpostgresql-adapter', '~> 1.3.14'
14
- gem 'kramdown'
15
- end
16
-
17
- platforms :ruby, :rbx do
18
- gem 'sqlite3'
19
- gem 'mysql2', '~> 0.4.10'
20
- gem 'pg', '~> 0.15'
21
- gem 'redcarpet'
22
- end
23
-
24
- platforms :rbx do
25
- gem 'rubysl', '~> 2.0'
26
- gem 'rubinius-developer_tools'
27
- end
28
- end