friendly_id 4.0.2 → 4.0.3

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.
@@ -1,8 +1,8 @@
1
1
  rvm:
2
2
  - 1.9.3
3
3
  - 1.8.7
4
- - jruby
5
- - rbx
4
+ # - jruby
5
+ # - rbx
6
6
 
7
7
  branches:
8
8
  only:
data/.yardopts CHANGED
@@ -1,3 +1,4 @@
1
1
  --files=WhatsNew.md,Changelog.md,Guide.rdoc
2
+ --private
2
3
  --protected
3
4
  --exclude lib/friendly_id/migration
@@ -6,6 +6,13 @@ suggestions, ideas and improvements to FriendlyId.
6
6
  * Table of Contents
7
7
  {:toc}
8
8
 
9
+ ## 4.0.3 (2012-03-14)
10
+
11
+ * Fix escape for '%' and '_' on SQLite (Norman Clarke and Sergey Petrunin)
12
+ * Allow FriendlyId to be extended or included (Norman Clarke)
13
+ * Allow Configuration#use to accept a Module (Norman Clarke)
14
+ * Fix bugs with History module + STI (Norman Clarke and Sergey Petrunin)
15
+
9
16
  ## 4.0.2 (2012-03-12)
10
17
 
11
18
  * Improved conflict handling and performance in History module (Erik Ogan and Thomas Shafer)
data/Guide.rdoc CHANGED
@@ -38,12 +38,13 @@ with numeric ids:
38
38
 
39
39
  == Setting Up FriendlyId in Your Model
40
40
 
41
- To use FriendlyId in your ActiveRecord models, you must first extend the
42
- FriendlyId module, then invoke the {FriendlyId::Base#friendly_id friendly_id}
43
- method to configure your desired options:
41
+ To use FriendlyId in your ActiveRecord models, you must first either extend or
42
+ include the FriendlyId module (it makes no difference), then invoke the
43
+ {FriendlyId::Base#friendly_id friendly_id} method to configure your desired
44
+ options:
44
45
 
45
46
  class Foo < ActiveRecord::Base
46
- extend FriendlyId
47
+ include FriendlyId
47
48
  friendly_id :bar, :use => [:slugged, :simple_i18n]
48
49
  end
49
50
 
@@ -401,7 +402,7 @@ an example of one way to set this up:
401
402
  http://example.org/cities/chicago/restaurants/joes-diner
402
403
 
403
404
 
404
- == Simple I18n
405
+ == Translating Slugs Using Simple I18n
405
406
 
406
407
  The {FriendlyId::SimpleI18n SimpleI18n} module adds very basic i18n support to
407
408
  FriendlyId.
@@ -409,8 +410,12 @@ FriendlyId.
409
410
  In order to use this module, your model must have a slug column for each locale.
410
411
  By default FriendlyId looks for columns named, for example, "slug_en",
411
412
  "slug_es", etc. The first part of the name can be configured by passing the
412
- +:slug_column+ option if you choose. Note that as of 4.0.0.beta11, the column
413
- for the default locale must also include the locale in its name.
413
+ +:slug_column+ option if you choose. Note that the column for the default locale
414
+ must also include the locale in its name.
415
+
416
+ This module is most suitable to applications that need to support few locales.
417
+ If you need to support two or more locales, you may wish to use the
418
+ {FriendlyId::Globalize Globalize} module instead.
414
419
 
415
420
  === Example migration
416
421
 
@@ -462,6 +467,54 @@ current locale:
462
467
  end
463
468
 
464
469
 
470
+ == Translating Slugs Using Globalize
471
+
472
+ The {FriendlyId::Globalize Globalize} module lets you use
473
+ Globalize[https://github.com/svenfuchs/globalize3] to translate slugs. This
474
+ module is most suitable for applications that need to be localized to many
475
+ languages. If your application only needs to be localized to one or two
476
+ languages, you may wish to consider the {FriendlyId::SimpleI18n SimpleI18n}
477
+ module.
478
+
479
+ In order to use this module, your model must have a slug column and set the
480
+ field +slug+ as translable with Globalize:
481
+
482
+ class Post < ActiveRecord::Base
483
+ translates :title, :slug
484
+ extend FriendlyId
485
+ friendly_id :title, :use => :globalize
486
+ end
487
+
488
+ === Finds
489
+
490
+ Finds will take the current locale into consideration:
491
+
492
+ I18n.locale = :it
493
+ Post.find("guerre-stellari")
494
+ I18n.locale = :en
495
+ Post.find("star-wars")
496
+
497
+ To find a slug by an explicit locale, perform the find inside a block
498
+ passed to I18n's +with_locale+ method:
499
+
500
+ I18n.with_locale(:it) do
501
+ Post.find("guerre-stellari")
502
+ end
503
+
504
+ === Creating Records
505
+
506
+ When new records are created, the slug is generated for the current locale only.
507
+
508
+ === Translating Slugs
509
+
510
+ To translate an existing record's friendly_id, simply change the locale and
511
+ assign a value to the +slug+ field:
512
+
513
+ I18n.with_locale(:it) do
514
+ post.slug = "guerre-stellari"
515
+ end
516
+
517
+
465
518
  == Reserved Words
466
519
 
467
520
  The {FriendlyId::Reserved Reserved} module adds the ability to exlude a list of
data/Rakefile CHANGED
@@ -3,7 +3,14 @@ require "rake/testtask"
3
3
 
4
4
  task :default => :test
5
5
 
6
+ task :load_path do
7
+ %w(lib test).each do |path|
8
+ $LOAD_PATH.unshift(File.expand_path("../#{path}", __FILE__))
9
+ end
10
+ end
11
+
6
12
  Rake::TestTask.new do |t|
13
+ t.libs << "test"
7
14
  t.test_files = FileList['test/*_test.rb']
8
15
  t.verbose = true
9
16
  end
@@ -21,7 +28,7 @@ task :yard => :guide do
21
28
  puts %x{bundle exec yard}
22
29
  end
23
30
 
24
- task :bench do
31
+ task :bench => :load_path do
25
32
  require File.expand_path("../bench", __FILE__)
26
33
  end
27
34
 
@@ -40,6 +47,7 @@ task :guide do
40
47
  buffer << read_comments("lib/friendly_id/history.rb")
41
48
  buffer << read_comments("lib/friendly_id/scoped.rb")
42
49
  buffer << read_comments("lib/friendly_id/simple_i18n.rb")
50
+ buffer << read_comments("lib/friendly_id/globalize.rb")
43
51
  buffer << read_comments("lib/friendly_id/reserved.rb")
44
52
 
45
53
  File.open("Guide.rdoc", "w") do |file|
@@ -55,7 +63,7 @@ namespace :test do
55
63
  dir = File.expand_path("../test", __FILE__)
56
64
  Dir["#{dir}/*_test.rb"].each do |test|
57
65
  puts "Running #{test}:"
58
- puts %x{ruby #{test}}
66
+ puts %x{ruby -Ilib -Itest #{test}}
59
67
  end
60
68
  end
61
69
  end
@@ -63,8 +71,8 @@ end
63
71
  namespace :db do
64
72
 
65
73
  desc "Create the database"
66
- task :create do
67
- require File.expand_path("../test/helper", __FILE__)
74
+ task :create => :load_path do
75
+ require "helper"
68
76
  driver = FriendlyId::Test::Database.driver
69
77
  config = FriendlyId::Test::Database.config[driver]
70
78
  commands = {
@@ -75,8 +83,8 @@ namespace :db do
75
83
  end
76
84
 
77
85
  desc "Create the database"
78
- task :drop do
79
- require File.expand_path("../test/helper", __FILE__)
86
+ task :drop => :load_path do
87
+ require "helper"
80
88
  driver = FriendlyId::Test::Database.driver
81
89
  config = FriendlyId::Test::Database.config[driver]
82
90
  commands = {
@@ -87,8 +95,8 @@ namespace :db do
87
95
  end
88
96
 
89
97
  desc "Set up the database schema"
90
- task :up do
91
- require File.expand_path("../test/helper", __FILE__)
98
+ task :up => :load_path do
99
+ require "helper"
92
100
  FriendlyId::Test::Schema.up
93
101
  end
94
102
 
@@ -45,7 +45,7 @@ with numeric ids:
45
45
  module FriendlyId
46
46
 
47
47
  # The current version.
48
- VERSION = "4.0.2"
48
+ VERSION = "4.0.3"
49
49
 
50
50
  @mutex = Mutex.new
51
51
 
@@ -90,6 +90,11 @@ module FriendlyId
90
90
  end
91
91
  end
92
92
 
93
+ # Allow developers to `include` FriendlyId or `extend` it.
94
+ def self.included(model_class)
95
+ model_class.extend self
96
+ end
97
+
93
98
  # Set global defaults for all models using FriendlyId.
94
99
  #
95
100
  # The default defaults are to use the +:reserved+ module and nothing else.
@@ -3,12 +3,13 @@ module FriendlyId
3
3
 
4
4
  == Setting Up FriendlyId in Your Model
5
5
 
6
- To use FriendlyId in your ActiveRecord models, you must first extend the
7
- FriendlyId module, then invoke the {FriendlyId::Base#friendly_id friendly_id}
8
- method to configure your desired options:
6
+ To use FriendlyId in your ActiveRecord models, you must first either extend or
7
+ include the FriendlyId module (it makes no difference), then invoke the
8
+ {FriendlyId::Base#friendly_id friendly_id} method to configure your desired
9
+ options:
9
10
 
10
11
  class Foo < ActiveRecord::Base
11
- extend FriendlyId
12
+ include FriendlyId
12
13
  friendly_id :bar, :use => [:slugged, :simple_i18n]
13
14
  end
14
15
 
@@ -129,10 +130,34 @@ often better and easier to use {FriendlyId::Slugged slugs}.
129
130
  # end
130
131
  # end
131
132
  #
132
- # @option options [Symbol] :use The name of an addon to use. By default,
133
- # FriendlyId provides {FriendlyId::Slugged :slugged},
133
+ # === Including Your Own Modules
134
+ #
135
+ # Because :use can accept a name or a Module, {FriendlyId.defaults defaults}
136
+ # can be a convenient place to set up behavior common to all classes using
137
+ # FriendlyId. You can include any module, or more conveniently, define one
138
+ # on-the-fly. For example, let's say you want to make
139
+ # Babosa[http://github.com/norman/babosa] the default slugging library in
140
+ # place of Active Support, and transliterate all slugs from Russian Cyrillic
141
+ # to ASCII:
142
+ #
143
+ # require "babosa"
144
+ #
145
+ # FriendlyId.defaults do |config|
146
+ # config.base = :name
147
+ # config.use :slugged
148
+ # config.use Module.new {
149
+ # def normalize_friendly_id(text)
150
+ # text.to_slug.normalize(:transliterations => [:russian, :latin])
151
+ # end
152
+ # }
153
+ # end
154
+ #
155
+ #
156
+ # @option options [Symbol,Module] :use The addon or name of an addon to use.
157
+ # By default, FriendlyId provides {FriendlyId::Slugged :slugged},
134
158
  # {FriendlyId::History :history}, {FriendlyId::Reserved :reserved}, and
135
- # {FriendlyId::Scoped :scoped}.
159
+ # {FriendlyId::Scoped :scoped}, {FriendlyId::SimpleI18n :simple_i18n},
160
+ # and {FriendlyId::Globalize :globalize}.
136
161
  #
137
162
  # @option options [Array] :reserved_words Available when using +:reserved+,
138
163
  # which is loaded by default. Sets an array of words banned for use as
@@ -161,21 +186,24 @@ often better and easier to use {FriendlyId::Slugged slugs}.
161
186
  #
162
187
  # @yieldparam config The model class's {FriendlyId::Configuration friendly_id_config}.
163
188
  def friendly_id(base = nil, options = {}, &block)
164
- yield @friendly_id_config if block_given?
165
- @friendly_id_config.use options.delete :use
166
- @friendly_id_config.send :set, base ? options.merge(:base => base) : options
189
+ yield friendly_id_config if block_given?
190
+ friendly_id_config.use options.delete :use
191
+ friendly_id_config.send :set, base ? options.merge(:base => base) : options
167
192
  before_save {|rec| rec.instance_eval {@current_friendly_id = friendly_id}}
168
193
  include Model
169
194
  end
170
195
 
171
196
  # Returns the model class's {FriendlyId::Configuration friendly_id_config}.
172
197
  # @note In the case of Single Table Inheritance (STI), this method will
173
- # duplicate the parent class's FriendlyId::Configuration instance on first
174
- # access. If you're concerned about thread safety, then be sure to invoke
175
- # {#friendly_id} in your class for each model.
198
+ # duplicate the parent class's FriendlyId::Configuration and relation class
199
+ # on first access. If you're concerned about thread safety, then be sure
200
+ # to invoke {#friendly_id} in your class for each model.
176
201
  def friendly_id_config
177
202
  @friendly_id_config or begin
178
- @friendly_id_config = base_class.friendly_id_config.dup
203
+ @friendly_id_config = base_class.friendly_id_config.dup.tap do |config|
204
+ config.model_class = self
205
+ @relation_class = base_class.send(:relation_class)
206
+ end
179
207
  end
180
208
  end
181
209
 
@@ -32,7 +32,7 @@ module FriendlyId
32
32
 
33
33
  # The model class that this configuration belongs to.
34
34
  # @return ActiveRecord::Base
35
- attr_reader :model_class
35
+ attr_accessor :model_class
36
36
 
37
37
  def initialize(model_class, values = nil)
38
38
  @model_class = model_class
@@ -51,13 +51,14 @@ module FriendlyId
51
51
  # extend FriendlyId
52
52
  # friendly_id :name, :use => :slugged
53
53
  # end
54
- # @param [#to_s] *modules Arguments should be a symbols or strings that
55
- # correspond with the name of a module inside the FriendlyId namespace. By
56
- # default FriendlyId provides +:slugged+, +:history+, +:simple_i18n+ and +:scoped+.
54
+ # @param [#to_s,Module] *modules Arguments should be Modules, or symbols or
55
+ # strings that correspond with the name of a module inside the FriendlyId
56
+ # namespace. By default FriendlyId provides +:slugged+, +:history+,
57
+ # +:simple_i18n+, +:globalize+, and +:scoped+.
57
58
  def use(*modules)
58
- modules.to_a.flatten.compact.map do |name|
59
- mod = FriendlyId.const_get(name.to_s.classify)
60
- model_class.send(:include, mod) unless model_class < mod
59
+ modules.to_a.flatten.compact.map do |object|
60
+ mod = object.kind_of?(Module) ? object : FriendlyId.const_get(object.to_s.classify)
61
+ model_class.send(:include, mod)
61
62
  end
62
63
  end
63
64
 
@@ -4,13 +4,17 @@ module FriendlyId
4
4
 
5
5
  =begin
6
6
 
7
- == Translate slug db column using Globalize
7
+ == Translating Slugs Using Globalize
8
8
 
9
- The {FriendlyId::Globalize Globalize} module allow to use
10
- Globalize (https://github.com/svenfuchs/globalize3) to translate slugs.
9
+ The {FriendlyId::Globalize Globalize} module lets you use
10
+ Globalize[https://github.com/svenfuchs/globalize3] to translate slugs. This
11
+ module is most suitable for applications that need to be localized to many
12
+ languages. If your application only needs to be localized to one or two
13
+ languages, you may wish to consider the {FriendlyId::SimpleI18n SimpleI18n}
14
+ module.
11
15
 
12
16
  In order to use this module, your model must have a slug column and set the
13
- field +slug+ translable with Globalize:
17
+ field +slug+ as translable with Globalize:
14
18
 
15
19
  class Post < ActiveRecord::Base
16
20
  translates :title, :slug
@@ -20,7 +24,7 @@ field +slug+ translable with Globalize:
20
24
 
21
25
  === Finds
22
26
 
23
- Finds will take into consideration the current locale:
27
+ Finds will take the current locale into consideration:
24
28
 
25
29
  I18n.locale = :it
26
30
  Post.find("guerre-stellari")
@@ -40,8 +44,8 @@ When new records are created, the slug is generated for the current locale only.
40
44
 
41
45
  === Translating Slugs
42
46
 
43
- To translate an existing record's friendly_id, simply change locale and assign
44
- +slug+ field:
47
+ To translate an existing record's friendly_id, simply change the locale and
48
+ assign a value to the +slug+ field:
45
49
 
46
50
  I18n.with_locale(:it) do
47
51
  post.slug = "guerre-stellari"
@@ -74,12 +74,15 @@ method.
74
74
  private
75
75
 
76
76
  def create_slug
77
+ return unless friendly_id
77
78
  return if slugs.first.try(:slug) == friendly_id
78
79
  # Allow reversion back to a previously used slug
79
80
  relation = slugs.where(:slug => friendly_id)
80
81
  result = relation.select("id").lock(true).all
81
82
  relation.delete_all unless result.empty?
82
- slugs.create! :slug => friendly_id
83
+ slugs.create! do |record|
84
+ record.slug = friendly_id
85
+ end
83
86
  end
84
87
 
85
88
  # Adds a finder that explictly uses slugs from the slug table.
@@ -106,7 +109,7 @@ method.
106
109
  # Accepts a slug, and yields a corresponding sluggable_id into the block.
107
110
  def with_old_friendly_id(slug, &block)
108
111
  sql = "SELECT sluggable_id FROM #{Slug.quoted_table_name} WHERE sluggable_type = %s AND slug = %s"
109
- sql = sql % [@klass.base_class.name, slug].map {|x| connection.quote(x)}
112
+ sql = sql % [@klass.base_class.to_s, slug].map {|x| connection.quote(x)}
110
113
  sluggable_id = connection.select_values(sql).first
111
114
  yield sluggable_id if sluggable_id
112
115
  end
@@ -117,17 +120,14 @@ method.
117
120
  module SlugGenerator
118
121
 
119
122
  private
120
- def last_in_sequence
121
- @_last_in_sequence ||= extract_sequence_from_slug(conflict.slug)
122
- end
123
123
 
124
124
  def conflicts
125
- sluggable_class = friendly_id_config.model_class
125
+ sluggable_class = friendly_id_config.model_class.base_class
126
126
  pkey = sluggable_class.primary_key
127
127
  value = sluggable.send pkey
128
128
 
129
129
  scope = Slug.where("slug = ? OR slug LIKE ?", normalized, wildcard)
130
- scope = scope.where(:sluggable_type => sluggable_class.name)
130
+ scope = scope.where(:sluggable_type => sluggable_class.to_s)
131
131
  scope = scope.where("sluggable_id <> ?", value) unless sluggable.new_record?
132
132
  scope.order("LENGTH(slug) DESC, slug DESC")
133
133
  end
@@ -4,7 +4,7 @@ module FriendlyId
4
4
 
5
5
  =begin
6
6
 
7
- == Simple I18n
7
+ == Translating Slugs Using Simple I18n
8
8
 
9
9
  The {FriendlyId::SimpleI18n SimpleI18n} module adds very basic i18n support to
10
10
  FriendlyId.
@@ -12,8 +12,12 @@ FriendlyId.
12
12
  In order to use this module, your model must have a slug column for each locale.
13
13
  By default FriendlyId looks for columns named, for example, "slug_en",
14
14
  "slug_es", etc. The first part of the name can be configured by passing the
15
- +:slug_column+ option if you choose. Note that as of 4.0.0.beta11, the column
16
- for the default locale must also include the locale in its name.
15
+ +:slug_column+ option if you choose. Note that the column for the default locale
16
+ must also include the locale in its name.
17
+
18
+ This module is most suitable to applications that need to support few locales.
19
+ If you need to support two or more locales, you may wish to use the
20
+ {FriendlyId::Globalize Globalize} module instead.
17
21
 
18
22
  === Example migration
19
23
 
@@ -5,5 +5,10 @@ module FriendlyId
5
5
  class Slug < ActiveRecord::Base
6
6
  self.table_name = "friendly_id_slugs"
7
7
  belongs_to :sluggable, :polymorphic => true
8
+
9
+ def to_param
10
+ slug
11
+ end
12
+
8
13
  end
9
14
  end
@@ -51,11 +51,14 @@ module FriendlyId
51
51
  end
52
52
 
53
53
  def conflicts
54
- sluggable_class = friendly_id_config.model_class
54
+ sluggable_class = friendly_id_config.model_class.base_class
55
55
 
56
56
  pkey = sluggable_class.primary_key
57
57
  value = sluggable.send pkey
58
- scope = sluggable_class.unscoped.where("#{column} = ? OR #{column} LIKE ?", normalized, wildcard)
58
+ base = "#{column} = ? OR #{column} LIKE ?"
59
+ # Awful hack for SQLite3, which does not pick up '\' as the escape character without this.
60
+ base << "ESCAPE '\\'" if sluggable.connection.adapter_name =~ /sqlite/i
61
+ scope = sluggable_class.unscoped.where(base, normalized, wildcard)
59
62
  scope = scope.where("#{pkey} <> ?", value) unless sluggable.new_record?
60
63
  scope = scope.order("LENGTH(#{column}) DESC, #{column} DESC")
61
64
  end
@@ -1,8 +1,22 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class CoreTest < MiniTest::Unit::TestCase
4
4
  include FriendlyId::Test
5
5
 
6
+ test "friendly_id can be added using 'extend'" do
7
+ klass = Class.new(ActiveRecord::Base) do
8
+ extend FriendlyId
9
+ end
10
+ assert klass.respond_to? :friendly_id
11
+ end
12
+
13
+ test "friendly_id can be added using 'include'" do
14
+ klass = Class.new(ActiveRecord::Base) do
15
+ include FriendlyId
16
+ end
17
+ assert klass.respond_to? :friendly_id
18
+ end
19
+
6
20
  test "friendly_id should accept a base and a hash" do
7
21
  klass = Class.new(ActiveRecord::Base) do
8
22
  self.abstract_class = true
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class ConfigurationTest < MiniTest::Unit::TestCase
4
4
 
@@ -26,4 +26,23 @@ class ConfigurationTest < MiniTest::Unit::TestCase
26
26
  end
27
27
  end
28
28
 
29
+ test "#use should accept a name that resolves to a module" do
30
+ refute @model_class < FriendlyId::Slugged
31
+ @model_class.class_eval do
32
+ extend FriendlyId
33
+ friendly_id :hello, :use => :slugged
34
+ end
35
+ assert @model_class < FriendlyId::Slugged
36
+ end
37
+
38
+ test "#use should accept a module" do
39
+ my_module = Module.new
40
+ refute @model_class < my_module
41
+ @model_class.class_eval do
42
+ extend FriendlyId
43
+ friendly_id :hello, :use => my_module
44
+ end
45
+ assert @model_class < my_module
46
+ end
47
+
29
48
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class Author < ActiveRecord::Base
4
4
  extend FriendlyId
@@ -1,5 +1,4 @@
1
- require File.expand_path("../helper", __FILE__)
2
-
1
+ require "helper"
3
2
  require "rails/generators"
4
3
  require "generators/friendly_id_generator"
5
4
 
@@ -1,7 +1,3 @@
1
- $: << File.expand_path("../../lib", __FILE__)
2
- $: << File.expand_path("../", __FILE__)
3
- $:.uniq!
4
-
5
1
  require "rubygems"
6
2
  require "bundler/setup"
7
3
  require "mocha"
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class Manual < ActiveRecord::Base
4
4
  extend FriendlyId
@@ -133,3 +133,17 @@ class HistoryTest < MiniTest::Unit::TestCase
133
133
  end
134
134
 
135
135
  end
136
+
137
+ class HistoryTestWithSti < HistoryTest
138
+ class Journalist < ActiveRecord::Base
139
+ extend FriendlyId
140
+ friendly_id :name, :use => [:slugged, :history]
141
+ end
142
+
143
+ class Editorialist < Journalist
144
+ end
145
+
146
+ def model_class
147
+ Editorialist
148
+ end
149
+ end
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class I18nTest < MiniTest::Unit::TestCase
4
4
  include FriendlyId::Test
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
 
4
4
  class ObjectUtilsTest < MiniTest::Unit::TestCase
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class ReservedTest < MiniTest::Unit::TestCase
4
4
 
@@ -32,6 +32,7 @@ module FriendlyId
32
32
  add_column :novels, :novelist_id, :integer
33
33
  add_column :novels, :publisher_id, :integer
34
34
  remove_index :novels, :slug
35
+ add_index :novels, [:slug, :publisher_id, :novelist_id], :unique => true
35
36
 
36
37
  # This will be used to test column name quoting
37
38
  add_column :journalists, "strange name", :string
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class Novelist < ActiveRecord::Base
4
4
  extend FriendlyId
@@ -46,7 +46,7 @@ module FriendlyId
46
46
  record.slug = nil
47
47
  record.save!
48
48
  assert_nil record.slug
49
- record.save
49
+ record.save!
50
50
  refute_nil record.slug
51
51
  end
52
52
  end
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class Journalist < ActiveRecord::Base
4
4
  extend FriendlyId
@@ -202,6 +202,26 @@ class SluggedRegressionsTest < MiniTest::Unit::TestCase
202
202
  end
203
203
  end
204
204
 
205
+ class UnderscoreAsSequenceSeparatorRegressionTest < MiniTest::Unit::TestCase
206
+ include FriendlyId::Test
207
+
208
+ class Manual < ActiveRecord::Base
209
+ extend FriendlyId
210
+ friendly_id :name, :use => :slugged, :sequence_separator => "_"
211
+ end
212
+
213
+ test "should not create duplicate slugs" do
214
+ 3.times do
215
+ begin
216
+ assert Manual.create! :name => "foo"
217
+ rescue
218
+ flunk "Tried to insert duplicate slug"
219
+ end
220
+ end
221
+ end
222
+
223
+ end
224
+
205
225
  # https://github.com/norman/friendly_id/issues/148
206
226
  class FailedValidationAfterUpdateRegressionTest < MiniTest::Unit::TestCase
207
227
  include FriendlyId::Test
@@ -1,4 +1,4 @@
1
- require File.expand_path("../helper.rb", __FILE__)
1
+ require "helper"
2
2
 
3
3
  class StiTest < MiniTest::Unit::TestCase
4
4
 
@@ -30,6 +30,10 @@ class StiTest < MiniTest::Unit::TestCase
30
30
  assert_equal :bar, klass.friendly_id_config.slug_column
31
31
  end
32
32
 
33
+ test "the configuration's model_class should be the class, not the base_class" do
34
+ assert_equal model_class, model_class.friendly_id_config.model_class
35
+ end
36
+
33
37
  test "friendly_id should accept a block with single table inheritance" do
34
38
  abstract_klass = Class.new(ActiveRecord::Base) do
35
39
  def self.table_exists?; false end
@@ -47,11 +51,27 @@ class StiTest < MiniTest::Unit::TestCase
47
51
  end
48
52
 
49
53
  test "friendly_id slugs should not clash with eachother" do
50
- journalist = Journalist.create! :name => 'foo bar'
51
- editoralist = Editorialist.create! :name => 'foo bar'
54
+ transaction do
55
+ journalist = model_class.base_class.create! :name => 'foo bar'
56
+ editoralist = model_class.create! :name => 'foo bar'
52
57
 
53
- assert_equal 'foo-bar', journalist.slug
54
- assert_equal 'foo-bar--2', editoralist.slug
58
+ assert_equal 'foo-bar', journalist.slug
59
+ assert_equal 'foo-bar--2', editoralist.slug
60
+ end
55
61
  end
56
62
 
57
63
  end
64
+
65
+ class StiTestWithHistory < StiTest
66
+ class Journalist < ActiveRecord::Base
67
+ extend FriendlyId
68
+ friendly_id :name, :use => [:slugged, :history]
69
+ end
70
+
71
+ class Editorialist < Journalist
72
+ end
73
+
74
+ def model_class
75
+ Editorialist
76
+ end
77
+ 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: 4.0.2
4
+ version: 4.0.3
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-03-12 00:00:00.000000000 Z
12
+ date: 2012-03-14 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: railties
16
- requirement: &70322875898160 !ruby/object:Gem::Requirement
16
+ requirement: &70135168764860 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ~>
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: 3.2.0
22
22
  type: :development
23
23
  prerelease: false
24
- version_requirements: *70322875898160
24
+ version_requirements: *70135168764860
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: activerecord
27
- requirement: &70322875893740 !ruby/object:Gem::Requirement
27
+ requirement: &70135168764100 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ~>
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: 3.2.0
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70322875893740
35
+ version_requirements: *70135168764100
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: minitest
38
- requirement: &70322875889580 !ruby/object:Gem::Requirement
38
+ requirement: &70135168763460 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70322875889580
46
+ version_requirements: *70135168763460
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: mocha
49
- requirement: &70322875886660 !ruby/object:Gem::Requirement
49
+ requirement: &70135171790060 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '0'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70322875886660
57
+ version_requirements: *70135171790060
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: maruku
60
- requirement: &70322875883700 !ruby/object:Gem::Requirement
60
+ requirement: &70135171789640 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70322875883700
68
+ version_requirements: *70135171789640
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: yard
71
- requirement: &70322875857480 !ruby/object:Gem::Requirement
71
+ requirement: &70135171789220 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,10 +76,10 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70322875857480
79
+ version_requirements: *70135171789220
80
80
  - !ruby/object:Gem::Dependency
81
81
  name: i18n
82
- requirement: &70322875830720 !ruby/object:Gem::Requirement
82
+ requirement: &70135171788800 !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
85
  - - ! '>='
@@ -87,10 +87,10 @@ dependencies:
87
87
  version: '0'
88
88
  type: :development
89
89
  prerelease: false
90
- version_requirements: *70322875830720
90
+ version_requirements: *70135171788800
91
91
  - !ruby/object:Gem::Dependency
92
92
  name: ffaker
93
- requirement: &70322875828040 !ruby/object:Gem::Requirement
93
+ requirement: &70135171788380 !ruby/object:Gem::Requirement
94
94
  none: false
95
95
  requirements:
96
96
  - - ! '>='
@@ -98,10 +98,10 @@ dependencies:
98
98
  version: '0'
99
99
  type: :development
100
100
  prerelease: false
101
- version_requirements: *70322875828040
101
+ version_requirements: *70135171788380
102
102
  - !ruby/object:Gem::Dependency
103
103
  name: simplecov
104
- requirement: &70322875809660 !ruby/object:Gem::Requirement
104
+ requirement: &70135171787960 !ruby/object:Gem::Requirement
105
105
  none: false
106
106
  requirements:
107
107
  - - ! '>='
@@ -109,7 +109,7 @@ dependencies:
109
109
  version: '0'
110
110
  type: :development
111
111
  prerelease: false
112
- version_requirements: *70322875809660
112
+ version_requirements: *70135171787960
113
113
  description: ! 'FriendlyId is the "Swiss Army bulldozer" of slugging and permalink
114
114
  plugins for
115
115