friendly_id 5.0.0.beta3 → 5.0.0.beta4

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: b7dc57b3098c5b155bf109e9cefccf404bce14e5
4
- data.tar.gz: 2958d34628cca3ae7c93fc828d10ec11da863a47
3
+ metadata.gz: 04766b0ed96f1b271571b983cf3b73cf9385406c
4
+ data.tar.gz: 5881c90dc07cf35780402d04211cc93ebd597d01
5
5
  SHA512:
6
- metadata.gz: aa871391245ae44af48c1e6676681f169ebf25a4d922a871e1d68344cab69705c5f63464caf1bfa0f4bb37f80ff6be45569005ea5b26fb1629477046285834b2
7
- data.tar.gz: 2c4658fea02b39fea957a833ce3e533abaa9273c29d77af9a7f720099130fe3c63e6c4f4394217af2166d1477a1ff83251a3cab5c670fb6861f748c5718b6c11
6
+ metadata.gz: 06b4a78391d3a6f9ca7a42e4769087e4dbf70a559e29313147b48b655dbc59ffddfbaf3f91e78854d64c8b1cedf1bf2e088280c9747fcb9fc45318ec7243d925
7
+ data.tar.gz: 2e66f50e25d14cf807e2f2719c49e13e2936656ac50a6842f1225357089e0561b2ec39effad76571558999d04d905715f365649cd1119b7a2a8765dd81084c79
data/Changelog.md CHANGED
@@ -3,6 +3,12 @@
3
3
  We would like to think our many {file:Contributors contributors} for
4
4
  suggestions, ideas and improvements to FriendlyId.
5
5
 
6
+ ## 5.0.0.beta4 (2013-08-21)
7
+
8
+ * Add an initializer to the generator; move the default reserved words there.
9
+ * Allow assignment from {FriendlyId::Configuration#base}.
10
+ * Fix bug whereby records could not reuse their own slugs.
11
+
6
12
  ## 5.0.0.beta3 (2013-08-20)
7
13
 
8
14
  * Update gemspec to ensure FriendlyId 5.0 is only used with AR 4.0.x.
data/README.md CHANGED
@@ -3,12 +3,14 @@
3
3
  **VERSION NOTE**
4
4
 
5
5
  **Rails 4**:
6
- Master branch of this repository contains FriendlyId 5 which is compatible with Rails 4.
7
- This version is in beta and will be released soon.
6
+
7
+ The master branch of this repository contains FriendlyId 5, which is compatible
8
+ with Rails 4. This version is in beta and will be released soon.
8
9
 
9
10
  **Rails 3**:
10
- If you wish to use this gem with Rails 3.1 or 3.2 you need to use FriendlyId version 4, which is the current stable release.
11
- Please see [4.0-stable
11
+
12
+ If you wish to use this gem with Rails 3.1 or 3.2 you must use FriendlyId 4,
13
+ which is the current stable release. Please see the [4.0-stable
12
14
  branch](https://github.com/norman/friendly_id/tree/4.0-stable).
13
15
 
14
16
  # FriendlyId
@@ -16,10 +18,10 @@ branch](https://github.com/norman/friendly_id/tree/4.0-stable).
16
18
  <em>For the most complete, user-friendly documentation, see the [FriendlyId Guide](http://rubydoc.info/github/norman/friendly_id/master/file/Guide.md).</em>
17
19
 
18
20
  FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
19
- Ruby on Rails. It allows you to create pretty URLs and work with human-friendly
20
- strings as if they were numeric ids for Active Record models.
21
+ Active Record. It lets you create pretty URLs and work with human-friendly
22
+ strings as if they were numeric ids.
21
23
 
22
- Using FriendlyId, it's easy to make your application use URLs like:
24
+ With FriendlyId, it's easy to make your application use URLs like:
23
25
 
24
26
  http://example.com/states/washington
25
27
 
@@ -33,49 +35,41 @@ instead of:
33
35
  FriendlyId offers many advanced features, including: slug history and
34
36
  versioning, i18n, scoped slugs, reserved words, and custom slug generators.
35
37
 
36
- Note: FriendlyId 5.0 is compatible with Active Record **4.0** and higher only.
37
- For Rails 3.x, please use FriendlyId 4.x.
38
-
39
-
40
- ## Version 5.x
38
+ ### What Changed in Version 5.0
41
39
 
42
40
  As of version 5.0, FriendlyId uses semantic versioning. Therefore, as you might
43
- infer from the version number, FriendlyId 5.0 introduces changes incompatible
44
- with 4.x.
41
+ infer from the version number, 5.0 introduces changes incompatible with 4.0.
45
42
 
46
- Here's a summary of the most important changes:
43
+ The most important changes are:
47
44
 
48
- * FriendlyId no longer overrides `find` by default. If you want to do friendly finds,
49
- you must do `Model.friendly.find` rather than `Model.find`. You can however easily
45
+ * Finders are no longer overridden by default. If you want to do friendly finds,
46
+ you must do `Model.friendly.find` rather than `Model.find`. You can however
50
47
  restore FriendlyId 4-style finders by using the `:finders` addon:
51
48
 
52
- ```ruby
53
- friendly_id :foo, use: :slugged # you must do MyClass.friendly.find('bar')
54
- # or...
55
- friendly_id :foo, use: [:slugged, :finders] # you can now do MyClass.find('bar')
56
- ```
49
+ friendly_id :foo, use: :slugged # you must do MyClass.friendly.find('bar')
50
+ # or...
51
+ friendly_id :foo, use: [:slugged, :finders] # you can now do MyClass.find('bar')
57
52
 
58
- * Version 5.0 offers a new "candidates" functionality which makes it easy to
59
- set up a list of alternate slugs that can be used to uniquely distinguish
60
- records, rather than appending a sequence. For example:
61
53
 
62
- ```ruby
63
- class Restaurant < ActiveRecord::Base
64
- extend FriendlyId
65
- friendly_id :slug_candidates, use: :slugged
66
-
67
- # Try building a slug based on the following fields in
68
- # increasing order of specificity.
69
- def slug_candidates
70
- [
71
- :name,
72
- [:name, :city],
73
- [:name, :street, :city],
74
- [:name, :street_number, :street, :city]
75
- ]
76
- end
77
- end
78
- ```
54
+ * A new "candidates" functionality which makes it easy to set up a list of
55
+ alternate slugs that can be used to uniquely distinguish records, rather than
56
+ appending a sequence. For example:
57
+
58
+ class Restaurant < ActiveRecord::Base
59
+ extend FriendlyId
60
+ friendly_id :slug_candidates, use: :slugged
61
+
62
+ # Try building a slug based on the following fields in
63
+ # increasing order of specificity.
64
+ def slug_candidates
65
+ [
66
+ :name,
67
+ [:name, :city],
68
+ [:name, :street, :city],
69
+ [:name, :street_number, :street, :city]
70
+ ]
71
+ end
72
+ end
79
73
 
80
74
  * Now that candidates have been added, FriendlyId no longer uses a numeric
81
75
  sequence to differentiate conflicting slug, but rather a UUID (e.g. something
@@ -83,26 +77,56 @@ end
83
77
  codebase simpler and more reliable when running concurrently, at the expense
84
78
  of uglier ids being generated when there are conflicts.
85
79
 
86
- * The default sequence separator is now `-` rather than `--`.
80
+ * The default sequence separator has been changed from two dashes to one dash.
87
81
 
88
82
  * Slugs are no longer regenerated when a record is saved. If you want to regenerate
89
83
  a slug, you must explicitly set the slug column to nil:
90
84
 
91
- ```ruby
92
- restaurant.friendly_id # joes-diner
93
- restaurant.name = "The Plaza Diner"
94
- restaurant.save!
95
- restaurant.friendly_id # joes-diner
96
- restaurant.slug = nil
97
- restaurant.save!
98
- restaurant.friendly_id # the-plaza-diner
99
- ```
85
+ restaurant.friendly_id # joes-diner
86
+ restaurant.name = "The Plaza Diner"
87
+ restaurant.save!
88
+ restaurant.friendly_id # joes-diner
89
+ restaurant.slug = nil
90
+ restaurant.save!
91
+ restaurant.friendly_id # the-plaza-diner
92
+
93
+ You can restore some of the old behavior by overriding the
94
+ `should_generate_new_friendly_id` method.
95
+
96
+ * The `friendly_id` Rails generator now generates an initializer showing you
97
+ how to do some commmon global configuration.
98
+
99
+ * The `:reserved` module no longer includes any default reserved words.
100
+ Previously it blocked "edit" and "new" everywhere. The default word list has
101
+ been moved to `config/initializers/friendly_id.rb` and now includes many more
102
+ words.
103
+
104
+ * The `:history` and `:scoped` addons can now be used together.
105
+
106
+ * Since it now requires Rails 4, FriendlyId also now requires Ruby 1.9.3 or
107
+ higher.
108
+
109
+ #### Upgrading from FriendlyId 4.0
110
+
111
+ Run `rails generate friendly_id --skip-migration` and edit the initializer
112
+ generated in `config/initializers/friendly_id.rb`. This file contains notes
113
+ describing how to restore (or not) some of the defaults from FriendlyId 4.0.
114
+
115
+ If you want to use the `:history` and `:scoped` addons together, you must add a
116
+ `:scope` column to your friendly_id slugs table and replace the unique index on
117
+ `:slug` and `:sluggable_type` with a unique index on those two columns, plus
118
+ the new `:scope` column.
119
+
120
+ A migration like this should be sufficient:
100
121
 
101
- * Like Rails 4, FriendlyId now requires Ruby 1.9.3 or higher.
122
+ add_column :friendly_id_slugs, :scope, :string
123
+ remove_index :friendly_id_slugs, [:slug, :sluggable_type]
124
+ add_index :friendly_id_slugs, [:slug, :sluggable_type]
125
+ add_index :friendly_id_slugs, [:slug, :sluggable_type, :scope], unique: true
102
126
 
103
127
  ## Docs
104
128
 
105
- The current docs can always be found
129
+ The most current docs from the master branch can always be found
106
130
  [here](http://rubydoc.info/github/norman/friendly_id/master/frames).
107
131
 
108
132
  The best place to start is with the
@@ -110,7 +134,7 @@ The best place to start is with the
110
134
  which compiles the top-level RDocs into one outlined document.
111
135
 
112
136
  You might also want to watch Ryan Bates's [Railscast on FriendlyId](http://railscasts.com/episodes/314-pretty-urls-with-friendlyid),
113
- which is now somewhat outdated but still mostly relevant.
137
+ which is now somewhat outdated but still relevant.
114
138
 
115
139
  ## Rails Quickstart
116
140
 
@@ -120,7 +144,7 @@ cd my_app
120
144
  ```
121
145
  ```ruby
122
146
  # Gemfile
123
- gem 'friendly_id', '5.0.0.beta1' # Note: You MUST use 5.0.0 or greater for Rails 4.0+
147
+ gem 'friendly_id', '5.0.0.beta4' # Note: You MUST use 5.0.0 or greater for Rails 4.0+
124
148
  ```
125
149
  ```shell
126
150
  rails generate friendly_id
data/lib/friendly_id.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  # encoding: utf-8
2
- require "thread"
3
2
  require "friendly_id/base"
4
3
  require "friendly_id/object_utils"
5
4
  require "friendly_id/configuration"
@@ -43,8 +42,6 @@ with numeric ids:
43
42
  =end
44
43
  module FriendlyId
45
44
 
46
- @mutex = Mutex.new
47
-
48
45
  autoload :History, "friendly_id/history"
49
46
  autoload :Slug, "friendly_id/slug"
50
47
  autoload :SimpleI18n, "friendly_id/simple_i18n"
@@ -95,18 +92,16 @@ module FriendlyId
95
92
 
96
93
  # Set global defaults for all models using FriendlyId.
97
94
  #
98
- # The default defaults are to use the +:reserved+ module and nothing else.
95
+ # The default defaults are to use the `:reserved` module and nothing else.
99
96
  #
100
97
  # @example
101
98
  # FriendlyId.defaults do |config|
102
- # config.base = :name
99
+ # config.base :name
103
100
  # config.use :slugged
104
101
  # end
105
102
  def self.defaults(&block)
106
- @mutex.synchronize do
107
- @defaults = block if block_given?
108
- @defaults ||= lambda {|config| config.use :reserved}
109
- end
103
+ @defaults = block if block_given?
104
+ @defaults ||= ->(config) {config.use :reserved}
110
105
  end
111
106
 
112
107
  # Set the ActiveRecord table name prefix to friendly_id_
@@ -55,10 +55,10 @@ often better and easier to use {FriendlyId::Slugged slugs}.
55
55
 
56
56
  # Configure FriendlyId's behavior in a model.
57
57
  #
58
- # class Post < ActiveRecord::Base
59
- # extend FriendlyId
60
- # friendly_id :title, :use => :slugged
61
- # end
58
+ # class Post < ActiveRecord::Base
59
+ # extend FriendlyId
60
+ # friendly_id :title, :use => :slugged
61
+ # end
62
62
  #
63
63
  # When given the optional block, this method will yield the class's instance
64
64
  # of {FriendlyId::Configuration} to the block before evaluating other
@@ -67,36 +67,36 @@ often better and easier to use {FriendlyId::Slugged slugs}.
67
67
  # multiple models, while being able to override the values it sets. Here is
68
68
  # a contrived example:
69
69
  #
70
- # $friendly_id_config_proc = Proc.new do |config|
71
- # config.base = :name
72
- # config.use :slugged
73
- # end
70
+ # $friendly_id_config_proc = Proc.new do |config|
71
+ # config.base = :name
72
+ # config.use :slugged
73
+ # end
74
74
  #
75
- # class Foo < ActiveRecord::Base
76
- # extend FriendlyId
77
- # friendly_id &$friendly_id_config_proc
78
- # end
75
+ # class Foo < ActiveRecord::Base
76
+ # extend FriendlyId
77
+ # friendly_id &$friendly_id_config_proc
78
+ # end
79
79
  #
80
- # class Bar < ActiveRecord::Base
81
- # extend FriendlyId
82
- # friendly_id :title, &$friendly_id_config_proc
83
- # end
80
+ # class Bar < ActiveRecord::Base
81
+ # extend FriendlyId
82
+ # friendly_id :title, &$friendly_id_config_proc
83
+ # end
84
84
  #
85
85
  # However, it's usually better to use {FriendlyId.defaults} for this:
86
86
  #
87
- # FriendlyId.defaults do |config|
88
- # config.base = :name
89
- # config.use :slugged
90
- # end
87
+ # FriendlyId.defaults do |config|
88
+ # config.base = :name
89
+ # config.use :slugged
90
+ # end
91
91
  #
92
- # class Foo < ActiveRecord::Base
93
- # extend FriendlyId
94
- # end
92
+ # class Foo < ActiveRecord::Base
93
+ # extend FriendlyId
94
+ # end
95
95
  #
96
- # class Bar < ActiveRecord::Base
97
- # extend FriendlyId
98
- # friendly_id :title
99
- # end
96
+ # class Bar < ActiveRecord::Base
97
+ # extend FriendlyId
98
+ # friendly_id :title
99
+ # end
100
100
  #
101
101
  # In general you should use the block syntax either because of your personal
102
102
  # aesthetic preference, or because you need to share some functionality
@@ -114,21 +114,21 @@ often better and easier to use {FriendlyId::Slugged slugs}.
114
114
  # modules into your class, and these modules in turn may add required
115
115
  # configuration options to the `@friendly_id_configuraton`'s class:
116
116
  #
117
- # class Person < ActiveRecord::Base
118
- # friendly_id do |config|
119
- # # This will work
120
- # config.use :slugged
121
- # config.sequence_separator = ":"
117
+ # class Person < ActiveRecord::Base
118
+ # friendly_id do |config|
119
+ # # This will work
120
+ # config.use :slugged
121
+ # config.sequence_separator = ":"
122
+ # end
122
123
  # end
123
- # end
124
124
  #
125
- # class Person < ActiveRecord::Base
126
- # friendly_id do |config|
127
- # # This will fail
128
- # config.sequence_separator = ":"
129
- # config.use :slugged
125
+ # class Person < ActiveRecord::Base
126
+ # friendly_id do |config|
127
+ # # This will fail
128
+ # config.sequence_separator = ":"
129
+ # config.use :slugged
130
+ # end
130
131
  # end
131
- # end
132
132
  #
133
133
  # ### Including Your Own Modules
134
134
  #
@@ -136,21 +136,21 @@ often better and easier to use {FriendlyId::Slugged slugs}.
136
136
  # can be a convenient place to set up behavior common to all classes using
137
137
  # FriendlyId. You can include any module, or more conveniently, define one
138
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
139
+ # [Babosa](http://github.com/norman/babosa) the default slugging library in
140
140
  # place of Active Support, and transliterate all slugs from Russian Cyrillic
141
141
  # to ASCII:
142
142
  #
143
- # require "babosa"
143
+ # require "babosa"
144
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
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
154
  #
155
155
  #
156
156
  # @option options [Symbol,Module] :use The addon or name of an addon to use.
@@ -1,31 +1,9 @@
1
1
  module FriendlyId
2
- # The configuration paramters passed to +friendly_id+ will be stored in
2
+ # The configuration paramters passed to {Base#friendly_id} will be stored in
3
3
  # this object.
4
4
  class Configuration
5
5
 
6
- # The base column or method used by FriendlyId as the basis of a friendly id
7
- # or slug.
8
- #
9
- # For models that don't use FriendlyId::Slugged, the base is the column that
10
- # is used as the FriendlyId directly. For models using FriendlyId::Slugged,
11
- # the base is a column or method whose value is used as the basis of the
12
- # slug.
13
- #
14
- # For example, if you have a model representing blog posts and that uses
15
- # slugs, you likely will want to use the "title" attribute as the base, and
16
- # FriendlyId will take care of transforming the human-readable title into
17
- # something suitable for use in a URL.
18
- #
19
- # A symbol referencing a column or method in the model. This
20
- # value is usually set by passing it as the first argument to
21
- # {FriendlyId::Base#friendly_id friendly_id}:
22
- #
23
- # @example
24
- # class Book < ActiveRecord::Base
25
- # extend FriendlyId
26
- # friendly_id :name
27
- # end
28
- attr_accessor :base
6
+ attr_writer :base
29
7
 
30
8
  # The default configuration options.
31
9
  attr_reader :defaults
@@ -44,10 +22,10 @@ module FriendlyId
44
22
  set values
45
23
  end
46
24
 
47
- # Lets you specify the modules to use with FriendlyId.
25
+ # Lets you specify the addon modules to use with FriendlyId.
48
26
  #
49
27
  # This method is invoked by {FriendlyId::Base#friendly_id friendly_id} when
50
- # passing the +:use+ option, or when using {FriendlyId::Base#friendly_id
28
+ # passing the `:use` option, or when using {FriendlyId::Base#friendly_id
51
29
  # friendly_id} with a block.
52
30
  #
53
31
  # @example
@@ -55,10 +33,11 @@ module FriendlyId
55
33
  # extend FriendlyId
56
34
  # friendly_id :name, :use => :slugged
57
35
  # end
36
+ #
58
37
  # @param [#to_s,Module] modules Arguments should be Modules, or symbols or
59
- # strings that correspond with the name of a module inside the FriendlyId
60
- # namespace. By default FriendlyId provides +:slugged+, +:history+,
61
- # +:simple_i18n+, and +:scoped+.
38
+ # strings that correspond with the name of an addon to use with FriendlyId.
39
+ # By default FriendlyId provides `:slugged`, `:history`, `:simple_i18n`,
40
+ # and `:scoped`.
62
41
  def use(*modules)
63
42
  modules.to_a.flatten.compact.map do |object|
64
43
  mod = get_module(object)
@@ -81,6 +60,33 @@ module FriendlyId
81
60
  base.to_s
82
61
  end
83
62
 
63
+ # The base column or method used by FriendlyId as the basis of a friendly id
64
+ # or slug.
65
+ #
66
+ # For models that don't use {FriendlyId::Slugged}, this is the column that
67
+ # is used to store the friendly id. For models using {FriendlyId::Slugged},
68
+ # the base is a column or method whose value is used as the basis of the
69
+ # slug.
70
+ #
71
+ # For example, if you have a model representing blog posts and that uses
72
+ # slugs, you likely will want to use the "title" attribute as the base, and
73
+ # FriendlyId will take care of transforming the human-readable title into
74
+ # something suitable for use in a URL.
75
+ #
76
+ # If you pass an argument, it will be used as the base. Otherwise the current
77
+ # value is returned.
78
+ #
79
+ # @param value A symbol referencing a column or method in the model. This
80
+ # value is usually set by passing it as the first argument to
81
+ # {FriendlyId::Base#friendly_id friendly_id}.
82
+ def base(*value)
83
+ if value.empty?
84
+ @base
85
+ else
86
+ self.base = value.first
87
+ end
88
+ end
89
+
84
90
  private
85
91
 
86
92
  def get_module(object)
@@ -0,0 +1,84 @@
1
+ # FriendlyId Global Configuration
2
+ #
3
+ # Use this to set up shared configuration options for your entire application.
4
+ # Any of the configuration options shown here can also be applied to single
5
+ # models by passing arguments to the `friendly_id` class method or defining
6
+ # methods in your model.
7
+ #
8
+ # To learn more, check out the guide:
9
+ #
10
+ # http://rubydoc.info/github/norman/friendly_id/master/file/Guide.md
11
+
12
+ FriendlyId.defaults do |config|
13
+ # ## Reserved Words
14
+ #
15
+ # Some words could conflict with Rails's routes when used as slugs, or are
16
+ # undesirable to allow as slugs. Edit this list as needed for your app.
17
+ config.use :reserved
18
+
19
+ config.reserved_words = %w(new edit index session login logout users admin
20
+ stylesheets assets javascripts images)
21
+
22
+ # ## Friendly Finders
23
+ #
24
+ # Uncomment this to use friendly finders in all models. By default, if
25
+ # you wish to find a record by its friendly id, you must do:
26
+ #
27
+ # MyModel.friendly.find('foo')
28
+ #
29
+ # If you uncomment this, you can do:
30
+ #
31
+ # MyModel.find('foo')
32
+ #
33
+ # This is significantly more convenient but may not be appropriate for
34
+ # all applications, so you must explicity opt-in to this behavior. You can
35
+ # always also configure it on a per-model basis if you prefer.
36
+ #
37
+ # config.use :finders
38
+ #
39
+ # ## Slugs
40
+ #
41
+ # Most applications will use the :slugged module everywhere. If you wish
42
+ # to do so, uncomment the following line.
43
+ #
44
+ # config.use :slugged
45
+ #
46
+ # By default, FriendlyId's :slugged addon expects the slug column to be named
47
+ # 'slug', but you can change it if you wish.
48
+ #
49
+ # config.slug_column = 'slug'
50
+ #
51
+ # When FriendlyId can not generate a unique ID from your base method, it appends
52
+ # a UUID, separated by a single dash. You can configure the character used as the
53
+ # separator. If you're upgrading from FriendlyId 4, you may wish to replace this
54
+ # with two dashes.
55
+ #
56
+ # config.sequence_separator = '-'
57
+ #
58
+ # ## Tips and Tricks
59
+ #
60
+ # ### Controlling when slugs are generated
61
+ #
62
+ # As of FriendlyId 5.0, new slugs are generated only when the slug field is
63
+ # nil, but you if you're using a column as your base method can change this
64
+ # behavior by overriding the `should_generate_new_friendly_id` method that
65
+ # FriendlyId adds to your model. The change below makes FriendlyId 5.0 behave
66
+ # more like 4.0.
67
+ #
68
+ # config.use Module.new {
69
+ # def should_generate_new_friendly_id?
70
+ # slug.blank? || <your_column_name_here>_changed?
71
+ # end
72
+ # }
73
+ #
74
+ # FriendlyId uses Rails's `parameterize` method to generate slugs, but for
75
+ # languages that don't use the Roman alphabet, that's not usually suffient. Here
76
+ # we use the Babosa library to transliterate Russian Cyrillic slugs to ASCII. If
77
+ # you use this, don't forget to add "babosa" to your Gemfile.
78
+ #
79
+ # config.use Module.new {
80
+ # def normalize_friendly_id(text)
81
+ # text.to_slug.normalize! :transliterations => [:russian, :latin]
82
+ # end
83
+ # }
84
+ end
@@ -7,21 +7,15 @@ module FriendlyId
7
7
  The {FriendlyId::Reserved Reserved} module adds the ability to exlude a list of
8
8
  words from use as FriendlyId slugs.
9
9
 
10
- By default, FriendlyId reserves the words "new" and "edit" when this module is
11
- included. You can configure this globally by using {FriendlyId.defaults
12
- FriendlyId.defaults}:
10
+ With Ruby on Rails, FriendlyId's generator generates an initializer that
11
+ reserves some words such as "new" and "edit" using {FriendlyId.defaults
12
+ FriendlyId.defaults}.
13
13
 
14
- FriendlyId.defaults do |config|
15
- config.use :reserved
16
- # Reserve words for English and Spanish URLs
17
- config.reserved_words = %w(new edit nueva nuevo editar)
18
- end
19
-
20
- Note that the error message will appear on the field `:friendly_id`. If you are
21
- using Rails's scaffolded form errors display, then it will have no field to
22
- highlight. If you'd like to change this so that scaffolding works as expected,
23
- one way to accomplish this is to move the error message to a different field.
24
- For example:
14
+ Note that the error messages for fields will appear on the field
15
+ `:friendly_id`. If you are using Rails's scaffolded form errors display, then
16
+ it will have no field to highlight. If you'd like to change this so that
17
+ scaffolding works as expected, one way to accomplish this is to move the error
18
+ message to a different field. For example:
25
19
 
26
20
  class Person < ActiveRecord::Base
27
21
  extend FriendlyId
@@ -42,27 +36,16 @@ For example:
42
36
  def self.included(model_class)
43
37
  model_class.class_eval do
44
38
  friendly_id_config.class.send :include, Reserved::Configuration
45
- friendly_id_config.defaults[:reserved_words] ||= ["new", "edit"]
39
+ validates_exclusion_of :friendly_id, :in => ->(_) {
40
+ friendly_id_config.reserved_words || []
41
+ }
46
42
  end
47
43
  end
48
44
 
49
45
  # This module adds the `:reserved_words` configuration option to
50
46
  # {FriendlyId::Configuration FriendlyId::Configuration}.
51
47
  module Configuration
52
- attr_writer :reserved_words
53
-
54
- # Overrides {FriendlyId::Configuration#base} to add a validation to the
55
- # model class.
56
- def base=(base)
57
- super
58
- reserved_words = model_class.friendly_id_config.reserved_words
59
- model_class.validates_exclusion_of :friendly_id, :in => reserved_words
60
- end
61
-
62
- # An array of words forbidden as slugs.
63
- def reserved_words
64
- @reserved_words ||= @defaults[:reserved_words]
65
- end
48
+ attr_accessor :reserved_words
66
49
  end
67
50
  end
68
51
  end
@@ -298,7 +298,12 @@ Github issue](https://github.com/norman/friendly_id/issues/185) for discussion.
298
298
  private :set_slug
299
299
 
300
300
  def slug_generator
301
- friendly_id_config.slug_generator_class.new(self.class.base_class.unscoped.friendly)
301
+ scope = self.class.base_class.unscoped.friendly
302
+ if changed.include?(friendly_id_config.slug_column)
303
+ column = self.class.quoted_table_name + '.' + self.class.quoted_primary_key
304
+ scope = scope.where("#{column} <> ?", send(self.class.primary_key))
305
+ end
306
+ friendly_id_config.slug_generator_class.new(scope)
302
307
  end
303
308
  private :slug_generator
304
309
 
@@ -1,3 +1,3 @@
1
1
  module FriendlyId
2
- VERSION = "5.0.0.beta3"
2
+ VERSION = "5.0.0.beta4"
3
3
  end
@@ -8,11 +8,19 @@ class FriendlyIdGenerator < ActiveRecord::Generators::Base
8
8
  # new table name. Our generator always uses 'friendly_id_slugs', so we just set a random name here.
9
9
  argument :name, type: :string, default: 'random_name'
10
10
 
11
+ class_option :'skip-migration', :type => :boolean, :desc => "Don't generate a migration for the slugs table"
12
+ class_option :'skip-initializer', :type => :boolean, :desc => "Don't generate an initializer"
13
+
11
14
  source_root File.expand_path('../../friendly_id', __FILE__)
12
15
 
13
16
  # Copies the migration template to db/migrate.
14
17
  def copy_files
18
+ return if options['skip-migration']
15
19
  migration_template 'migration.rb', 'db/migrate/create_friendly_id_slugs.rb'
16
20
  end
17
21
 
22
+ def create_initializer
23
+ return if options['skip-initializer']
24
+ copy_file 'initializer.rb', 'config/initializers/friendly_id.rb'
25
+ end
18
26
  end
@@ -45,4 +45,20 @@ class ConfigurationTest < MiniTest::Unit::TestCase
45
45
  assert @model_class < my_module
46
46
  end
47
47
 
48
+ test "#base should optionally set a value" do
49
+ config = FriendlyId::Configuration.new @model_class
50
+ assert_nil config.base
51
+ config.base = 'foo'
52
+ assert_equal 'foo', config.base
53
+ end
54
+
55
+ test "#base can set the value to nil" do
56
+ config = FriendlyId::Configuration.new @model_class
57
+ config.base 'foo'
58
+ config.base nil
59
+ assert_nil config.base
60
+
61
+ end
62
+
63
+
48
64
  end
@@ -17,4 +17,32 @@ class FriendlyIdGeneratorTest < Rails::Generators::TestCase
17
17
  FileUtils.rm_rf self.destination_root
18
18
  end
19
19
  end
20
+
21
+ test "should skip the migration when told to do so" do
22
+ begin
23
+ run_generator ['--skip-migration']
24
+ assert_no_migration "db/migrate/create_friendly_id_slugs"
25
+ ensure
26
+ FileUtils.rm_rf self.destination_root
27
+ end
28
+ end
29
+
30
+ test "should generate an initializer" do
31
+ begin
32
+ run_generator
33
+ assert_file "config/initializers/friendly_id.rb"
34
+ ensure
35
+ FileUtils.rm_rf self.destination_root
36
+ end
37
+ end
38
+
39
+ test "should skip the initializer when told to do so" do
40
+ begin
41
+ run_generator ['--skip-initializer']
42
+ assert_no_file "config/initializers/friendly_id.rb"
43
+ ensure
44
+ FileUtils.rm_rf self.destination_root
45
+ end
46
+ end
47
+
20
48
  end
@@ -6,7 +6,7 @@ class ReservedTest < MiniTest::Unit::TestCase
6
6
 
7
7
  class Journalist < ActiveRecord::Base
8
8
  extend FriendlyId
9
- friendly_id :name
9
+ friendly_id :name, :use => [:slugged, :reserved], :reserved_words => %w(new edit)
10
10
 
11
11
  after_validation :move_friendly_id_error_to_name
12
12
 
@@ -19,8 +19,8 @@ class ReservedTest < MiniTest::Unit::TestCase
19
19
  Journalist
20
20
  end
21
21
 
22
- test "should reserve 'new' and 'edit' by default" do
23
- %w(new edit).each do |word|
22
+ test "should reserve words" do
23
+ %w(new edit NEW Edit).each do |word|
24
24
  transaction do
25
25
  assert_raises(ActiveRecord::RecordInvalid) {model_class.create! :name => word}
26
26
  end
data/test/slugged_test.rb CHANGED
@@ -29,14 +29,6 @@ class SluggedTest < MiniTest::Unit::TestCase
29
29
  Journalist
30
30
  end
31
31
 
32
- test "should not allow reserved words in resulting slug" do
33
- ["new", "New", "NEW"].each do |word|
34
- transaction do
35
- assert_raises(ActiveRecord::RecordInvalid) {model_class.create! :name => word}
36
- end
37
- end
38
- end
39
-
40
32
  test "should allow validations on the slug" do
41
33
  model_class = Class.new(ActiveRecord::Base) do
42
34
  self.table_name = "articles"
@@ -76,6 +68,15 @@ class SluggedTest < MiniTest::Unit::TestCase
76
68
  refute instance2.valid?
77
69
  end
78
70
  end
71
+
72
+ test 'should allow a record to reuse its own slug' do
73
+ with_instance_of(model_class) do |record|
74
+ old_id = record.friendly_id
75
+ record.slug = nil
76
+ record.save!
77
+ assert_equal old_id, record.friendly_id
78
+ end
79
+ end
79
80
  end
80
81
 
81
82
  class SlugGeneratorTest < MiniTest::Unit::TestCase
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.0.0.beta3
4
+ version: 5.0.0.beta4
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: 2013-08-20 00:00:00.000000000 Z
12
+ date: 2013-08-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -170,6 +170,7 @@ files:
170
170
  - lib/friendly_id/finder_methods.rb
171
171
  - lib/friendly_id/finders.rb
172
172
  - lib/friendly_id/history.rb
173
+ - lib/friendly_id/initializer.rb
173
174
  - lib/friendly_id/migration.rb
174
175
  - lib/friendly_id/object_utils.rb
175
176
  - lib/friendly_id/reserved.rb