friendly_id 5.2.0.beta.1 → 5.2.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
  SHA1:
3
- metadata.gz: d11cd5a5fc78a05718add4cf44e44f4425700f02
4
- data.tar.gz: 581623a3a24eff70d1e0ee307bdcaf814631a80c
3
+ metadata.gz: 606af0800382602b2f88d11be3a839a3e8c23255
4
+ data.tar.gz: a501dd78829d595fe897475bdf4a6c6d98caee9c
5
5
  SHA512:
6
- metadata.gz: 9068ff6f4efaab2c47673eb31b5f700898d5fad4f3d6f3fa754e7b9f9264ee1b02689637af319995c83a2b0771a40d7c70ce422b112e8337b0281ba42a5e41bb
7
- data.tar.gz: 5726a377bc4573bfb59cbfdc0d0d4abe224516bd691017299809da5304abd51477da9c8c7bb0f48916afd44b4de9b77ddc81716e0e9be69e24427018eb7abe51
6
+ metadata.gz: cb2afe89084b532541152c46056649ec6bfca0a2fe51493706f7f996ee233bae010a248a735fb55451e89b1918b29e60b5471e78c0272f29a5c5c410220eacc8
7
+ data.tar.gz: 8a527f735585ce88c1627bc54f206745f69a826d27574f6d306ee4a29dff23421e82225b0b9e9751cdd5a3a9911f3dba755d10d7a9951758052a3bd869b26441
data/.travis.yml CHANGED
@@ -2,11 +2,11 @@ language: ruby
2
2
  cache: bundler
3
3
 
4
4
  rvm:
5
+ - 2.3.0
5
6
  - 2.2.0
6
- - 2.0.0
7
7
  - 2.1.0
8
- - jruby-19mode
9
- - rbx-2
8
+ - 2.0.0
9
+ - jruby-9.0.4.0
10
10
 
11
11
  env:
12
12
  - DB=postgres
@@ -16,15 +16,26 @@ gemfile:
16
16
  - gemfiles/Gemfile.rails-4.0.rb
17
17
  - gemfiles/Gemfile.rails-4.1.rb
18
18
  - gemfiles/Gemfile.rails-4.2.rb
19
+ - gemfiles/Gemfile.rails-5.0.rb
19
20
 
20
21
  matrix:
21
22
  allow_failures:
22
23
  - rvm: jruby-19mode
23
24
  gemfile: gemfiles/Gemfile.rails-4.2.rb
24
25
  env: DB=postgres
26
+ - rvm: jruby-9.0.4.0
27
+ gemfile: gemfiles/Gemfile.rails-5.0.rb
28
+ exclude:
29
+ - rvm: 2.0.0
30
+ gemfile: gemfiles/Gemfile.rails-5.0.rb
31
+ - rvm: 2.1.0
32
+ gemfile: gemfiles/Gemfile.rails-5.0.rb
33
+ - rvm: 2.2.0
34
+ gemfile: gemfiles/Gemfile.rails-5.0.rb
25
35
 
26
36
  sudo: false
27
37
 
28
- before_script: 'bundle exec rake db:create db:up'
38
+ before_script:
39
+ - bundle exec rake db:create db:up
29
40
 
30
41
  script: 'COVERALLS=true bundle exec rake test'
data/CONTRIBUTING.md CHANGED
@@ -3,7 +3,7 @@
3
3
  Please ask questions on [Stack
4
4
  Overflow](http://stackoverflow.com/questions/tagged/friendly-id) using the
5
5
  "friendly_id" or "friendly-id" tag. Prior to asking, search and see if your
6
- question has already been anwered.
6
+ question has already been answered.
7
7
 
8
8
  Please only post issues in Github issues for actual bugs.
9
9
 
data/Changelog.md CHANGED
@@ -1,15 +1,19 @@
1
1
  # FriendlyId Changelog
2
2
 
3
- We would like to think our many {file:Contributors contributors} for
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
- ## 5.2.0 (NOT RELEASED YET)
6
+ ## 5.2.0 (2016-12-01)
7
7
 
8
8
  * Add sequential slug module for FriendlyId 4.x-style sequential slugs. ([#644](https://github.com/norman/friendly_id/pull/644)).
9
9
  * Make Candidates#each iterable without block ([#651](https://github.com/norman/friendly_id/pull/651)).
10
10
  * Ensure slug history prefers the record that most recently used the slug ([#663](https://github.com/norman/friendly_id/pull/663)).
11
11
  * Don't calculate all changes just to check if the param field has changed ([#667](https://github.com/norman/friendly_id/pull/667)).
12
12
  * Don't set or change slug when unrelated validation failures block the record from being saved ([#642](https://github.com/norman/friendly_id/issues/642)).
13
+ * Fix order dependence bug between history and finders modules ([#718](https://github.com/norman/friendly_id/pull/718))
14
+ * Added ability to conditionally turn off :dependent => :destory on FriendlyId::Slugs([#724](https://github.com/norman/friendly_id/pull/724))
15
+ * Add support for Rails 5. ([#728](https://github.com/norman/friendly_id/pull/728))
16
+ * Allow per-model conditional disabling of friendly path generation using a :routes option to friendly_id ([#735](https://github.com/norman/friendly_id/pull/735))
13
17
 
14
18
  ## 5.1.0 (2015-01-15)
15
19
 
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2014 Norman Clarke, Adrian Mugnolo and Emilio Tagua.
1
+ Copyright (c) 2008-2016 Norman Clarke, Adrian Mugnolo and Emilio Tagua.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md CHANGED
@@ -16,7 +16,7 @@ over and over and over again in the issues.
16
16
 
17
17
  # FriendlyId
18
18
 
19
- <em>For the most complete, user-friendly documentation, see the [FriendlyId Guide](http://norman.github.io/friendly_id/file.Guide.html).</em>
19
+ **For the most complete, user-friendly documentation, see the [FriendlyId Guide](http://norman.github.io/friendly_id/file.Guide.html).**
20
20
 
21
21
  FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
22
22
  Active Record. It lets you create pretty URLs and work with human-friendly
@@ -236,7 +236,7 @@ volunteers](https://github.com/norman/friendly_id/contributors).
236
236
 
237
237
  ## License
238
238
 
239
- Copyright (c) 2008-2014 Norman Clarke and contributors, released under the MIT
239
+ Copyright (c) 2008-2016 Norman Clarke and contributors, released under the MIT
240
240
  license.
241
241
 
242
242
  Permission is hereby granted, free of charge, to any person obtaining a copy of
data/Rakefile CHANGED
@@ -36,6 +36,16 @@ task :bench => :load_path do
36
36
  require File.expand_path("../bench", __FILE__)
37
37
  end
38
38
 
39
+ desc "Run benchmarks on finders"
40
+ task :bench_finders => :load_path do
41
+ require File.expand_path("../test/benchmarks/finders", __FILE__)
42
+ end
43
+
44
+ desc "Run benchmarks on ObjectUtils"
45
+ task :bench_object_utils => :load_path do
46
+ require File.expand_path("../test/benchmarks/object_utils", __FILE__)
47
+ end
48
+
39
49
  desc "Generate Guide.md"
40
50
  task :guide do
41
51
  load File.expand_path('../guide.rb', __FILE__)
data/bench.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  require File.expand_path("../test/helper", __FILE__)
2
2
  require "ffaker"
3
3
 
4
- N = 1000
4
+ N = 10000
5
5
 
6
6
  def transaction
7
7
  ActiveRecord::Base.transaction { yield ; raise ActiveRecord::Rollback }
@@ -37,7 +37,7 @@ MANUALS = []
37
37
  RESTAURANTS = []
38
38
 
39
39
  100.times do
40
- name = Faker::Name.name
40
+ name = FFaker::Name.name
41
41
  BOOKS << (Book.create! :name => name).id
42
42
  JOURNALISTS << (Journalist.create! :name => name).friendly_id
43
43
  MANUALS << (Manual.create! :name => name).friendly_id
@@ -64,18 +64,18 @@ Benchmark.bmbm do |x|
64
64
  end
65
65
 
66
66
  x.report 'insert (without FriendlyId)' do
67
- N.times {transaction {Book.create :name => Faker::Name.name}}
67
+ N.times {transaction {Book.create :name => FFaker::Name.name}}
68
68
  end
69
69
 
70
70
  x.report 'insert (in-table-slug)' do
71
- N.times {transaction {Journalist.create :name => Faker::Name.name}}
71
+ N.times {transaction {Journalist.create :name => FFaker::Name.name}}
72
72
  end
73
73
 
74
74
  x.report 'insert (in-table-slug; using finders module)' do
75
- N.times {transaction {Restaurant.create :name => Faker::Name.name}}
75
+ N.times {transaction {Restaurant.create :name => FFaker::Name.name}}
76
76
  end
77
77
 
78
78
  x.report 'insert (external slug)' do
79
- N.times {transaction {Manual.create :name => Faker::Name.name}}
79
+ N.times {transaction {Manual.create :name => FFaker::Name.name}}
80
80
  end
81
81
  end
data/friendly_id.gemspec CHANGED
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  s.version = FriendlyId::VERSION
7
7
  s.authors = ["Norman Clarke", "Philip Arndt"]
8
8
  s.email = ["norman@njclarke.com", "p@arndt.io"]
9
- s.homepage = "http://github.com/norman/friendly_id"
9
+ s.homepage = "https://github.com/norman/friendly_id"
10
10
  s.summary = "A comprehensive slugging and pretty-URL plugin."
11
11
  s.rubyforge_project = "friendly_id"
12
12
  s.files = `git ls-files`.split("\n")
@@ -17,7 +17,7 @@ group :development, :test do
17
17
 
18
18
  platforms :ruby, :rbx do
19
19
  gem 'sqlite3'
20
- gem 'mysql2'
20
+ gem 'mysql2', '~> 0.3.10'
21
21
  gem 'pg'
22
22
  gem 'redcarpet'
23
23
  end
@@ -16,7 +16,7 @@ group :development, :test do
16
16
 
17
17
  platforms :ruby, :rbx do
18
18
  gem 'sqlite3'
19
- gem 'mysql2'
19
+ gem 'mysql2', '~> 0.3.13'
20
20
  gem 'pg'
21
21
  gem 'redcarpet'
22
22
  end
@@ -0,0 +1,28 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'activerecord', '~> 5.0.0'
6
+ gem 'railties', '~> 5.0.0'
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'
20
+ gem 'pg'
21
+ gem 'redcarpet'
22
+ end
23
+
24
+ platforms :rbx do
25
+ gem 'rubysl', '~> 2.0'
26
+ gem 'rubinius-developer_tools'
27
+ end
28
+ end
data/lib/friendly_id.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # encoding: utf-8
2
+ require 'active_record'
2
3
  require "friendly_id/base"
3
4
  require "friendly_id/object_utils"
4
5
  require "friendly_id/configuration"
@@ -51,19 +52,6 @@ module FriendlyId
51
52
  autoload :Finders, "friendly_id/finders"
52
53
  autoload :SequentiallySlugged, "friendly_id/sequentially_slugged"
53
54
 
54
- # Instances of these classes will never be considered a friendly id.
55
- # @see FriendlyId::ObjectUtils#friendly_id
56
- UNFRIENDLY_CLASSES = [
57
- ActiveRecord::Base,
58
- Array,
59
- FalseClass,
60
- Hash,
61
- NilClass,
62
- Numeric,
63
- Symbol,
64
- TrueClass
65
- ]
66
-
67
55
  # FriendlyId takes advantage of `extended` to do basic model setup, primarily
68
56
  # extending {FriendlyId::Base} to add {FriendlyId::Base#friendly_id
69
57
  # friendly_id} as a class method.
@@ -187,9 +187,22 @@ often better and easier to use {FriendlyId::Slugged slugs}.
187
187
  # allows an alternate configuration syntax, and conditional configuration
188
188
  # logic.
189
189
  #
190
+ # @option options [Symbol,Boolean] :dependent Available when using `:history`.
191
+ # Sets the value used for the slugged association's dependent option. Use
192
+ # `false` if you do not want to dependently destroy the associated slugged
193
+ # record. Defaults to `:destroy`.
194
+ #
195
+ # @option options [Symbol] :routes When set to anything other than :friendly,
196
+ # ensures that all routes generated by default do *not* use the slug. This
197
+ # allows `form_for` and `polymorphic_path` to continue to generate paths like
198
+ # `/team/1` instead of `/team/number-one`. You can still generate paths
199
+ # like the latter using: team_path(team.slug). When set to :friendly, or
200
+ # omitted, the default friendly_id behavior is maintained.
201
+ #
190
202
  # @yieldparam config The model class's {FriendlyId::Configuration friendly_id_config}.
191
203
  def friendly_id(base = nil, options = {}, &block)
192
204
  yield friendly_id_config if block_given?
205
+ friendly_id_config.dependent = options.delete :dependent
193
206
  friendly_id_config.use options.delete :use
194
207
  friendly_id_config.send :set, base ? options.merge(:base => base) : options
195
208
  include Model
@@ -244,11 +257,15 @@ often better and easier to use {FriendlyId::Slugged slugs}.
244
257
 
245
258
  # Either the friendly_id, or the numeric id cast to a string.
246
259
  def to_param
247
- if attribute_changed?(friendly_id_config.query_field)
248
- diff = changes[friendly_id_config.query_field]
249
- diff.first || diff.second
260
+ if friendly_id_config.routes == :friendly
261
+ if attribute_changed?(friendly_id_config.query_field)
262
+ diff = changes[friendly_id_config.query_field]
263
+ diff.first || diff.second
264
+ else
265
+ friendly_id.presence.to_param || super
266
+ end
250
267
  else
251
- friendly_id.presence.to_param || super
268
+ super
252
269
  end
253
270
  end
254
271
 
@@ -18,11 +18,18 @@ module FriendlyId
18
18
  # The module to use for finders
19
19
  attr_accessor :finder_methods
20
20
 
21
+ # The value used for the slugged association's dependent option
22
+ attr_accessor :dependent
23
+
24
+ # Route generation preferences
25
+ attr_accessor :routes
26
+
21
27
  def initialize(model_class, values = nil)
22
28
  @model_class = model_class
23
29
  @defaults = {}
24
30
  @modules = []
25
31
  @finder_methods = FriendlyId::FinderMethods
32
+ self.routes = :friendly
26
33
  set values
27
34
  end
28
35
 
@@ -20,7 +20,7 @@ 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
23
+ raise ActiveRecord::RecordNotFound, "can't find record with friendly id: #{id.inspect}"
24
24
  end
25
25
 
26
26
  # Returns true if a record with the given id exists.
@@ -33,7 +33,7 @@ module FriendlyId
33
33
  # `find`.
34
34
  # @raise ActiveRecord::RecordNotFound
35
35
  def find_by_friendly_id(id)
36
- first_by_friendly_id(id) or raise ActiveRecord::RecordNotFound
36
+ first_by_friendly_id(id) or raise ActiveRecord::RecordNotFound, "can't find record with friendly id: #{id.inspect}"
37
37
  end
38
38
 
39
39
  def exists_by_friendly_id?(id)
@@ -54,8 +54,8 @@ module FriendlyId
54
54
  end
55
55
 
56
56
  def first_by_friendly_id(id)
57
- where(friendly_id_config.query_field => id).first
57
+ find_by(friendly_id_config.query_field => id)
58
58
  end
59
59
 
60
60
  end
61
- end
61
+ end
@@ -76,17 +76,14 @@ 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
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
83
- end
84
-
85
- def self.included(model_class)
86
- model_class.extend(ClassMethods)
87
83
 
88
84
  # Support for friendly finds on associations for Rails 4.0.1 and above.
89
85
  if ::ActiveRecord.const_defined?('AssociationRelation')
86
+ model_class.extend(ClassMethods)
90
87
  association_relation_delegate_class = model_class.relation_delegate_class(::ActiveRecord::AssociationRelation)
91
88
  association_relation_delegate_class.send(:include, model_class.friendly_id_config.finder_methods)
92
89
  end
@@ -41,7 +41,7 @@ method.
41
41
  ...
42
42
 
43
43
  def find_post
44
- @post = Post.find params[:id]
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
47
  # the request path will not match the post_path, and we should do
@@ -54,16 +54,18 @@ method.
54
54
  =end
55
55
  module History
56
56
 
57
+ module Configuration
58
+ def dependent_value
59
+ dependent.nil? ? :destroy : dependent
60
+ end
61
+ end
62
+
57
63
  def self.setup(model_class)
58
64
  model_class.instance_eval do
59
65
  friendly_id_config.use :slugged
66
+ friendly_id_config.class.send :include, History::Configuration
60
67
  friendly_id_config.finder_methods = FriendlyId::History::FinderMethods
61
- if friendly_id_config.uses? :finders
62
- relation.class.send(:include, friendly_id_config.finder_methods)
63
- if ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2
64
- model_class.send(:extend, friendly_id_config.finder_methods)
65
- end
66
- end
68
+ FriendlyId::Finders.setup(model_class) if friendly_id_config.uses? :finders
67
69
  end
68
70
  end
69
71
 
@@ -72,7 +74,7 @@ method.
72
74
  model_class.class_eval do
73
75
  has_many :slugs, -> {order("#{Slug.quoted_table_name}.id DESC")}, {
74
76
  :as => :sluggable,
75
- :dependent => :destroy,
77
+ :dependent => @friendly_id_config.dependent_value,
76
78
  :class_name => Slug.to_s
77
79
  }
78
80
 
@@ -84,7 +86,7 @@ method.
84
86
  include ::FriendlyId::FinderMethods
85
87
 
86
88
  def exists_by_friendly_id?(id)
87
- joins(:slugs).where(arel_table[friendly_id_config.query_field].eq(id)).exists? || joins(:slugs).where(slug_history_clause(id)).exists?
89
+ where(arel_table[friendly_id_config.query_field].eq(id)).exists? || joins(:slugs).where(slug_history_clause(id)).exists?
88
90
  end
89
91
 
90
92
  private
@@ -111,7 +113,7 @@ method.
111
113
  def scope_for_slug_generator
112
114
  relation = super
113
115
  return relation if new_record?
114
- relation = relation.merge(Slug.where('sluggable_id <> ?', id))
116
+ relation = relation.joins(:slugs).merge(Slug.where('sluggable_id <> ?', id))
115
117
  if friendly_id_config.uses?(:scoped)
116
118
  relation = relation.where(Slug.arel_table[:scope].eq(serialized_scope))
117
119
  end
@@ -8,8 +8,8 @@ class CreateFriendlyIdSlugs < ActiveRecord::Migration
8
8
  t.datetime :created_at
9
9
  end
10
10
  add_index :friendly_id_slugs, :sluggable_id
11
- add_index :friendly_id_slugs, [:slug, :sluggable_type]
12
- add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], :unique => true
11
+ add_index :friendly_id_slugs, [:slug, :sluggable_type], length: { slug: 140, sluggable_type: 50 }
12
+ add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], length: { slug: 70, sluggable_type: 50, scope: 70 }, unique: true
13
13
  add_index :friendly_id_slugs, :sluggable_type
14
14
  end
15
15
  end
@@ -1,4 +1,17 @@
1
1
  module FriendlyId
2
+ # Instances of these classes will never be considered a friendly id.
3
+ # @see FriendlyId::ObjectUtils#friendly_id
4
+ UNFRIENDLY_CLASSES = [
5
+ ActiveRecord::Base,
6
+ Array,
7
+ FalseClass,
8
+ Hash,
9
+ NilClass,
10
+ Numeric,
11
+ Symbol,
12
+ TrueClass
13
+ ]
14
+
2
15
  # Utility methods for determining whether any object is a friendly id.
3
16
  #
4
17
  # Monkey-patching Object is a somewhat extreme measure not to be taken lightly
@@ -27,13 +40,7 @@ module FriendlyId
27
40
  # "123".friendly_id? #=> nil
28
41
  # "abc123".friendly_id? #=> true
29
42
  def friendly_id?
30
- # Considered unfriendly if this is an instance of an unfriendly class or
31
- # one of its descendants.
32
- if FriendlyId::UNFRIENDLY_CLASSES.detect {|klass| self.class <= klass}
33
- false
34
- elsif respond_to?(:to_i) && to_i.to_s != to_s
35
- true
36
- end
43
+ true if respond_to?(:to_i) && to_i.to_s != to_s
37
44
  end
38
45
 
39
46
  # True if the id is definitely unfriendly, false if definitely friendly,
@@ -42,6 +49,21 @@ module FriendlyId
42
49
  val = friendly_id? ; !val unless val.nil?
43
50
  end
44
51
  end
52
+
53
+ module UnfriendlyUtils
54
+ def friendly_id?
55
+ false
56
+ end
57
+
58
+ def unfriendly_id?
59
+ true
60
+ end
61
+ end
45
62
  end
46
63
 
47
64
  Object.send :include, FriendlyId::ObjectUtils
65
+
66
+ # Considered unfriendly if object is an instance of an unfriendly class or
67
+ # one of its descendants.
68
+
69
+ FriendlyId::UNFRIENDLY_CLASSES.each { |klass| klass.send(:include, FriendlyId::UnfriendlyUtils) }
@@ -4,13 +4,11 @@ module FriendlyId
4
4
  model_class.friendly_id_config.use :slugged
5
5
  end
6
6
 
7
- def should_generate_new_friendly_id?
8
- send(friendly_id_config.base).present? && super
9
- end
10
-
11
7
  def resolve_friendly_id_conflict(candidate_slugs)
8
+ candidate = candidate_slugs.first
9
+ return if candidate.nil?
12
10
  SequentialSlugCalculator.new(scope_for_slug_generator,
13
- candidate_slugs.first,
11
+ candidate,
14
12
  friendly_id_config.slug_column,
15
13
  friendly_id_config.sequence_separator).next_slug
16
14
  end
@@ -37,15 +37,15 @@ friendly_id_globalize gem instead.
37
37
  Finds will take into consideration the current locale:
38
38
 
39
39
  I18n.locale = :es
40
- Post.find("la-guerra-de-las-galaxias")
40
+ Post.friendly.find("la-guerra-de-las-galaxias")
41
41
  I18n.locale = :en
42
- Post.find("star-wars")
42
+ Post.friendly.find("star-wars")
43
43
 
44
44
  To find a slug by an explicit locale, perform the find inside a block
45
45
  passed to I18n's `with_locale` method:
46
46
 
47
47
  I18n.with_locale(:es) do
48
- Post.find("la-guerra-de-las-galaxias")
48
+ Post.friendly.find("la-guerra-de-las-galaxias")
49
49
  end
50
50
 
51
51
  ### Creating Records
@@ -263,6 +263,7 @@ Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
263
263
  # ### Example
264
264
  #
265
265
  # class Person < ActiveRecord::Base
266
+ # extend FriendlyId
266
267
  # friendly_id :name_and_location
267
268
  #
268
269
  # def name_and_location
@@ -1,3 +1,3 @@
1
1
  module FriendlyId
2
- VERSION = "5.2.0.beta.1"
2
+ VERSION = "5.2.0"
3
3
  end
@@ -0,0 +1,88 @@
1
+ require File.expand_path("../../helper", __FILE__)
2
+ require "ffaker"
3
+
4
+ # This benchmark tests ActiveRecord and FriendlyId methods for performing a find
5
+ #
6
+ # ActiveRecord: where.first 8.970000 0.040000 9.010000 ( 9.029544)
7
+ # ActiveRecord: where.take 8.100000 0.030000 8.130000 ( 8.157024)
8
+ # ActiveRecord: find 2.720000 0.010000 2.730000 ( 2.733527)
9
+ # ActiveRecord: find_by(:id) 2.920000 0.000000 2.920000 ( 2.926318)
10
+ # ActiveRecord: find_by(:slug) 2.650000 0.020000 2.670000 ( 2.662677)
11
+ # FriendlyId: find (in-table slug w/ finders) 9.820000 0.030000 9.850000 ( 9.873358)
12
+ # FriendlyId: friendly.find (in-table slug) 12.890000 0.050000 12.940000 ( 12.951156)
13
+
14
+ N = 50000
15
+
16
+ def transaction
17
+ ActiveRecord::Base.transaction { yield ; raise ActiveRecord::Rollback }
18
+ end
19
+
20
+ class Array
21
+ def rand
22
+ self[Kernel.rand(length)]
23
+ end
24
+ end
25
+
26
+ Book = Class.new ActiveRecord::Base
27
+
28
+ class Journalist < ActiveRecord::Base
29
+ extend FriendlyId
30
+ friendly_id :name, :use => :slugged
31
+ end
32
+
33
+ class Manual < ActiveRecord::Base
34
+ extend FriendlyId
35
+ friendly_id :name, :use => :history
36
+ end
37
+
38
+ class Restaurant < ActiveRecord::Base
39
+ extend FriendlyId
40
+ friendly_id :name, :use => :finders
41
+ end
42
+
43
+
44
+ BOOKS = []
45
+ JOURNALISTS = []
46
+ MANUALS = []
47
+ RESTAURANTS = []
48
+
49
+ 100.times do
50
+ name = FFaker::Name.name
51
+ BOOKS << (Book.create! :name => name).id
52
+ JOURNALISTS << (Journalist.create! :name => name).friendly_id
53
+ MANUALS << (Manual.create! :name => name).friendly_id
54
+ RESTAURANTS << (Restaurant.create! :name => name).friendly_id
55
+ end
56
+
57
+ ActiveRecord::Base.connection.execute "UPDATE manuals SET slug = NULL"
58
+
59
+ Benchmark.bmbm do |x|
60
+ x.report 'ActiveRecord: where.first' do
61
+ N.times {Book.where(:id=>BOOKS.rand).first}
62
+ end
63
+
64
+ x.report 'ActiveRecord: where.take' do
65
+ N.times {Book.where(:id=>BOOKS.rand).take}
66
+ end
67
+
68
+ x.report 'ActiveRecord: find' do
69
+ N.times {Book.find BOOKS.rand}
70
+ end
71
+
72
+ x.report 'ActiveRecord: find_by(:id)' do
73
+ N.times {Book.find_by(:id=>BOOKS.rand)}
74
+ end
75
+
76
+ x.report 'ActiveRecord: find_by(:slug)' do
77
+ N.times {Restaurant.find_by(:slug=>RESTAURANTS.rand)}
78
+ end
79
+
80
+ x.report 'FriendlyId: find (in-table slug w/ finders)' do
81
+ N.times {Restaurant.find RESTAURANTS.rand}
82
+ end
83
+
84
+ x.report 'FriendlyId: friendly.find (in-table slug)' do
85
+ N.times {Restaurant.friendly.find RESTAURANTS.rand}
86
+ end
87
+
88
+ end
@@ -0,0 +1,56 @@
1
+ require File.expand_path("../../helper", __FILE__)
2
+
3
+ # This benchmark compares the timings of the friendly_id? and unfriendly_id? on various objects
4
+ #
5
+ # integer friendly_id? 6.370000 0.000000 6.370000 ( 6.380925)
6
+ # integer unfriendly_id? 6.640000 0.010000 6.650000 ( 6.646057)
7
+ # AR::Base friendly_id? 2.340000 0.000000 2.340000 ( 2.340743)
8
+ # AR::Base unfriendly_id? 2.560000 0.000000 2.560000 ( 2.560039)
9
+ # hash friendly_id? 5.090000 0.010000 5.100000 ( 5.097662)
10
+ # hash unfriendly_id? 5.430000 0.000000 5.430000 ( 5.437160)
11
+ # nil friendly_id? 5.610000 0.010000 5.620000 ( 5.611487)
12
+ # nil unfriendly_id? 5.870000 0.000000 5.870000 ( 5.880484)
13
+ # numeric string friendly_id? 9.270000 0.030000 9.300000 ( 9.308452)
14
+ # numeric string unfriendly_id? 9.190000 0.040000 9.230000 ( 9.252890)
15
+ # test_string friendly_id? 8.380000 0.010000 8.390000 ( 8.411762)
16
+ # test_string unfriendly_id? 8.450000 0.010000 8.460000 ( 8.463662)
17
+
18
+ # From the ObjectUtils docs...
19
+ # 123.friendly_id? #=> false
20
+ # :id.friendly_id? #=> false
21
+ # {:name => 'joe'}.friendly_id? #=> false
22
+ # ['name = ?', 'joe'].friendly_id? #=> false
23
+ # nil.friendly_id? #=> false
24
+ # "123".friendly_id? #=> nil
25
+ # "abc123".friendly_id? #=> true
26
+
27
+ Book = Class.new ActiveRecord::Base
28
+
29
+ test_integer = 123
30
+ test_active_record_object = Book.new
31
+ test_hash = {:name=>'joe'}
32
+ test_nil = nil
33
+ test_numeric_string = "123"
34
+ test_string = "abc123"
35
+
36
+ N = 5_000_000
37
+
38
+ Benchmark.bmbm do |x|
39
+ x.report('integer friendly_id?') { N.times {test_integer.friendly_id?} }
40
+ x.report('integer unfriendly_id?') { N.times {test_integer.unfriendly_id?} }
41
+
42
+ x.report('AR::Base friendly_id?') { N.times {test_active_record_object.friendly_id?} }
43
+ x.report('AR::Base unfriendly_id?') { N.times {test_active_record_object.unfriendly_id?} }
44
+
45
+ x.report('hash friendly_id?') { N.times {test_hash.friendly_id?} }
46
+ x.report('hash unfriendly_id?') { N.times {test_hash.unfriendly_id?} }
47
+
48
+ x.report('nil friendly_id?') { N.times {test_nil.friendly_id?} }
49
+ x.report('nil unfriendly_id?') { N.times {test_nil.unfriendly_id?} }
50
+
51
+ x.report('numeric string friendly_id?') { N.times {test_numeric_string.friendly_id?} }
52
+ x.report('numeric string unfriendly_id?') { N.times {test_numeric_string.unfriendly_id?} }
53
+
54
+ x.report('test_string friendly_id?') { N.times {test_string.friendly_id?} }
55
+ x.report('test_string unfriendly_id?') { N.times {test_string.unfriendly_id?} }
56
+ end
data/test/history_test.rb CHANGED
@@ -1,15 +1,15 @@
1
1
  require "helper"
2
2
 
3
- class Manual < ActiveRecord::Base
4
- extend FriendlyId
5
- friendly_id :name, :use => [:slugged, :history]
6
- end
7
-
8
3
  class HistoryTest < TestCaseClass
9
4
 
10
5
  include FriendlyId::Test
11
6
  include FriendlyId::Test::Shared::Core
12
7
 
8
+ class Manual < ActiveRecord::Base
9
+ extend FriendlyId
10
+ friendly_id :name, :use => [:slugged, :history]
11
+ end
12
+
13
13
  def model_class
14
14
  Manual
15
15
  end
@@ -172,6 +172,45 @@ class HistoryTestWithAutomaticSlugRegeneration < HistoryTest
172
172
  end
173
173
  end
174
174
 
175
+ class DependentDestroyTest < HistoryTest
176
+
177
+ include FriendlyId::Test
178
+
179
+ class FalseManual < ActiveRecord::Base
180
+ self.table_name = 'manuals'
181
+
182
+ extend FriendlyId
183
+ friendly_id :name, :use => :history, :dependent => false
184
+ end
185
+
186
+ class DefaultManual < ActiveRecord::Base
187
+ self.table_name = 'manuals'
188
+
189
+ extend FriendlyId
190
+ friendly_id :name, :use => :history
191
+ end
192
+
193
+ test 'should allow disabling of dependent destroy' do
194
+ transaction do
195
+ assert FriendlyId::Slug.find_by_slug('foo').nil?
196
+ l = FalseManual.create! :name => 'foo'
197
+ assert FriendlyId::Slug.find_by_slug('foo').present?
198
+ l.destroy
199
+ assert FriendlyId::Slug.find_by_slug('foo').present?
200
+ end
201
+ end
202
+
203
+ test 'should dependently destroy by default' do
204
+ transaction do
205
+ assert FriendlyId::Slug.find_by_slug('baz').nil?
206
+ l = DefaultManual.create! :name => 'baz'
207
+ assert FriendlyId::Slug.find_by_slug('baz').present?
208
+ l.destroy
209
+ assert FriendlyId::Slug.find_by_slug('baz').nil?
210
+ end
211
+ end
212
+ end
213
+
175
214
  class HistoryTestWithSti < HistoryTest
176
215
  class Journalist < ActiveRecord::Base
177
216
  extend FriendlyId
@@ -217,6 +256,36 @@ class HistoryTestWithFriendlyFinders < HistoryTest
217
256
  end
218
257
  end
219
258
 
259
+ class HistoryTestWithFindersBeforeHistory < HistoryTest
260
+ class Novelist < ActiveRecord::Base
261
+ has_many :novels
262
+ end
263
+
264
+ class Novel < ActiveRecord::Base
265
+ extend FriendlyId
266
+
267
+ belongs_to :novelist
268
+
269
+ friendly_id :name, :use => [:finders, :history]
270
+
271
+ def should_generate_new_friendly_id?
272
+ slug.blank? || name_changed?
273
+ end
274
+ end
275
+
276
+ test "should be findable by old slug through has_many association" do
277
+ transaction do
278
+ novelist = Novelist.create!(:name => "Stephen King")
279
+ novel = novelist.novels.create(:name => "Rita Hayworth and Shawshank Redemption")
280
+ slug = novel.slug
281
+ novel.name = "Shawshank Redemption"
282
+ novel.save!
283
+ assert_equal novel, Novel.find(slug)
284
+ assert_equal novel, novelist.novels.find(slug)
285
+ end
286
+ end
287
+ end
288
+
220
289
  class City < ActiveRecord::Base
221
290
  has_many :restaurants
222
291
  end
@@ -89,6 +89,22 @@ class SequentiallySluggedTest < TestCaseClass
89
89
  end
90
90
  end
91
91
 
92
+ test "should not generate a slug when canidates set is empty" do
93
+ model_class = Class.new(ActiveRecord::Base) do
94
+ self.table_name = "cities"
95
+ extend FriendlyId
96
+ friendly_id :slug_candidates, :use => [ :sequentially_slugged ]
97
+
98
+ def slug_candidates
99
+ [name, [name, code]]
100
+ end
101
+ end
102
+ transaction do
103
+ record = model_class.create!(:name => nil, :code => nil)
104
+ assert_nil record.slug
105
+ end
106
+ end
107
+
92
108
  test "should not generate a slug when the sluggable attribute is blank" do
93
109
  record = model_class.create!(:name => '')
94
110
  assert_nil record.slug
data/test/slugged_test.rb CHANGED
@@ -373,3 +373,35 @@ class FailedValidationAfterUpdateRegressionTest < TestCaseClass
373
373
  end
374
374
 
375
375
  end
376
+
377
+ class ConfigurableRoutesTest < TestCaseClass
378
+ include FriendlyId::Test
379
+
380
+ class Article < ActiveRecord::Base
381
+ extend FriendlyId
382
+
383
+ friendly_id :name, :use => :slugged, :routes => :friendly
384
+ end
385
+
386
+ class Novel < ActiveRecord::Base
387
+ extend FriendlyId
388
+
389
+ friendly_id :name, :use => :slugged, :routes => :default
390
+ end
391
+
392
+ test "to_param should return a friendly id when the routes option is set to :friendly" do
393
+ transaction do
394
+ article = Article.create! :name => "Titanic Hits; Iceberg Sinks"
395
+
396
+ assert_equal "titanic-hits-iceberg-sinks", article.to_param
397
+ end
398
+ end
399
+
400
+ test "to_param should return the id when the routes option is set to anything but friendly" do
401
+ transaction do
402
+ novel = Novel.create! :name => "Don Quixote"
403
+
404
+ assert_equal novel.id.to_s, novel.to_param
405
+ end
406
+ end
407
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: friendly_id
3
3
  version: !ruby/object:Gem::Version
4
- version: 5.2.0.beta.1
4
+ version: 5.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Norman Clarke
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2015-06-01 00:00:00.000000000 Z
12
+ date: 2016-12-01 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -163,6 +163,7 @@ files:
163
163
  - gemfiles/Gemfile.rails-4.0.rb
164
164
  - gemfiles/Gemfile.rails-4.1.rb
165
165
  - gemfiles/Gemfile.rails-4.2.rb
166
+ - gemfiles/Gemfile.rails-5.0.rb
166
167
  - guide.rb
167
168
  - lib/friendly_id.rb
168
169
  - lib/friendly_id/.gitattributes
@@ -185,6 +186,8 @@ files:
185
186
  - lib/friendly_id/version.rb
186
187
  - lib/generators/friendly_id_generator.rb
187
188
  - test/base_test.rb
189
+ - test/benchmarks/finders.rb
190
+ - test/benchmarks/object_utils.rb
188
191
  - test/candidates_test.rb
189
192
  - test/configuration_test.rb
190
193
  - test/core_test.rb
@@ -202,7 +205,7 @@ files:
202
205
  - test/simple_i18n_test.rb
203
206
  - test/slugged_test.rb
204
207
  - test/sti_test.rb
205
- homepage: http://github.com/norman/friendly_id
208
+ homepage: https://github.com/norman/friendly_id
206
209
  licenses:
207
210
  - MIT
208
211
  metadata: {}
@@ -217,14 +220,13 @@ required_ruby_version: !ruby/object:Gem::Requirement
217
220
  version: 1.9.3
218
221
  required_rubygems_version: !ruby/object:Gem::Requirement
219
222
  requirements:
220
- - - ">"
223
+ - - ">="
221
224
  - !ruby/object:Gem::Version
222
- version: 1.3.1
225
+ version: '0'
223
226
  requirements: []
224
227
  rubyforge_project: friendly_id
225
- rubygems_version: 2.4.5
228
+ rubygems_version: 2.5.2
226
229
  signing_key:
227
230
  specification_version: 4
228
231
  summary: A comprehensive slugging and pretty-URL plugin.
229
232
  test_files: []
230
- has_rdoc: