friendly_id 5.3.0 → 5.4.0

Sign up to get free protection for your applications and to get access to all the features.
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