slugalicious 2.0.0 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 79cad2b0eaf39ef1dfb8aff6d8ae448a64ff13e2
4
+ data.tar.gz: cc1b3ce56cb2a89e02534e47daeaafeea411cda7
5
+ SHA512:
6
+ metadata.gz: de5185ea3c49a8a7d6bdc5dccf37c9d71f027b2dc24e28fa82733ee423e39fcc114875f7dfd9e9797e59901742bdc03356c7df5d0d5a91dbd066ab207cf625ff
7
+ data.tar.gz: 9996a8eda4f63d23bfa5c71a9f05d08c68871f91a0ba95d32ead34e6fa8698baa5bda5435ddbfc05d19f1ba8257c78e1bf36b0617c888a553c672a5f385af855
@@ -1,23 +1,27 @@
1
- h1. Slugalicious -- Easy and powerful URL slugging for Rails 3
1
+ Slugalicious -- Easy and powerful URL slugging for Rails 4
2
+ ==========================================================
2
3
 
3
- _*(no monkey-patching required)*_
4
+ _(no monkey-patching required)_
4
5
 
5
- | *Author* | Tim Morgan |
6
- | *Version* | 2.0 (Jun 5, 2012) |
7
- | *License* | Released under the MIT license. |
6
+ | | |
7
+ |:------------|:--------------------------------|
8
+ | **Author** | Tim Morgan |
9
+ | **Version** | 2.1 (Jul 9, 2013) |
10
+ | **License** | Released under the MIT license. |
8
11
 
9
- h3. Note about version 2.0
12
+ ### Note about version 2.0
10
13
 
11
14
  Version 2.0 is so-versioned because it breaks the API for previous versions.
12
15
  Previously, where you would have used
13
16
  {Slugalicious::ClassMethods#find_from_slug find_from_slug}, you would now use
14
17
  {Slugalicious::ClassMethods#find_from_slug! find_from_slug!}. The old method now
15
- returns @nil@ when an object is not found, rather than raising an exception.
18
+ returns `nil` when an object is not found, rather than raising an exception.
16
19
 
17
- h2. About
20
+ About
21
+ -----
18
22
 
19
23
  Slugalicious is an easy-to-use slugging library that helps you generate pretty
20
- URLs for your ActiveRecord objects. It's built for Rails 3 and is cordoned off
24
+ URLs for your ActiveRecord objects. It's built for Rails 4 and is cordoned off
21
25
  in a monkey patching-free zone.
22
26
 
23
27
  Slugalicious is easy to use and powerful enough to cover all of the most common
@@ -31,68 +35,70 @@ generates a unique slug. If all else fails, Slugalicious will fall back on a
31
35
  less pretty but guaranteed-unique backup slug generation strategy.
32
36
 
33
37
  Slugalicious works with the Stringex Ruby library, meaning you get meaningful
34
- slugs via the @String#to_url@ method. Below are two examples of how powerful
38
+ slugs via the `String#to_url` method. Below are two examples of how powerful
35
39
  Stringex is:
36
40
 
37
- <pre><code>
41
+ ```` ruby
38
42
  "$6 Dollar Burger".to_url #=> "six-dollar-burger"
39
43
  "新年好".to_url #=> "xin-nian-hao"
40
- </code></pre>
44
+ ````
41
45
 
42
- h2. Installation
46
+ Installation
47
+ ------------
43
48
 
44
- *Important Note:* Slugalicious is written for Rails 3.0 and Ruby 1.9 only.
49
+ *Important Note:* Slugalicious is written for Rails 4.0 and Ruby 1.9 only.
45
50
 
46
- Firstly, add the gem to your Rails project's @Gemfile@:
51
+ Firstly, add the gem to your Rails project's `Gemfile`:
47
52
 
48
- <pre><code>
53
+ ```` ruby
49
54
  gem 'slugalicious'
50
- </code></pre>
55
+ ````
51
56
 
52
- Next, use the generator to add the @Slug@ model and its migration to your
57
+ Next, use the generator to add the `Slug` model and its migration to your
53
58
  project:
54
59
 
55
- <pre><code>
60
+ ```` sh
56
61
  rails generate slugalicious
57
- </code></pre>
62
+ ````
58
63
 
59
64
  Then run the migration to set up your database.
60
65
 
61
- h2. Usage
66
+ Usage
67
+ -----
62
68
 
63
- For any model you want to slug, include the @Slugalicious@ module and call
64
- @slugged@:
69
+ For any model you want to slug, include the `Slugalicious` module and call
70
+ `slugged`:
65
71
 
66
- <pre><code>
72
+ ```` ruby
67
73
  class User < ActiveRecord::Base
68
74
  include Slugalicious
69
75
  slugged ->(user) { "#{user.first_name} #{user.last_name}" }
70
76
  end
71
- </code></pre>
77
+ ````
72
78
 
73
- Doing this sets the @to_param@ method, so you can go ahead and start generating
74
- URLs using your models. You can use the @find_from_slug@ method to load a record
79
+ Doing this sets the `to_param` method, so you can go ahead and start generating
80
+ URLs using your models. You can use the `find_from_slug` method to load a record
75
81
  from a slug:
76
82
 
77
- <pre><code>
83
+ ```` ruby
78
84
  user = User.find_from_slug(params[:id])
79
- </code></pre>
85
+ ````
80
86
 
81
- h3. Multiple slug generators
87
+ ### Multiple slug generators
82
88
 
83
- The @slugged@ method takes a list of method names (as symbols) or @Procs@ that
89
+ The `slugged` method takes a list of method names (as symbols) or `Procs` that
84
90
  each attempt to generate a slug. Each of these generators is tried in order
85
91
  until a unique slug is generated. (The output of each of these generators is run
86
92
  through the slugifier to convert it to a URL-safe string. The slugifier is by
87
- default @String#to_url@, provided by the Stringex gem.)
93
+ default `String#to_url`, provided by the Stringex gem.)
88
94
 
89
- So, if we had our @User@ class, and we first wanted to slug by last name only,
95
+ So, if we had our `User` class, and we first wanted to slug by last name only,
90
96
  but then add in the first name if two people share a last name, we'd call
91
- @slugged@ like so:
97
+ `slugged` like so:
92
98
 
93
- <pre><code>
99
+ ```` ruby
94
100
  slugged :last_name, ->(user) { "#{user.first_name} #{user.last_name}" }
95
- </code></pre>
101
+ ````
96
102
 
97
103
  In the event that none of these generators manages to make a unique slug, a
98
104
  fallback generator is used. This generator prepends the ID of the record, making
@@ -102,20 +108,20 @@ another user with the same name, and that user will get the slug
102
108
  "sancho-sample;2". The semicolon is the default ID separator (and it can be
103
109
  overridden).
104
110
 
105
- h3. Scoped slugs
111
+ ### Scoped slugs
106
112
 
107
113
  Slugs must normally be unique for a single model type. Thus, if you have a
108
- @User@ named Hammer and a @Product@ named hammer, they can both share the
114
+ `User` named Hammer and a `Product` named hammer, they can both share the
109
115
  "hammer" slug.
110
116
 
111
117
  If you want to decrease the uniqueness scope of a slug, you can do so with the
112
- @:scope@ option on the @slugged@ method. Let's say you wanted to limit the scope
113
- of a @Product@'s slug to its associated @Department@; that way you could have a
118
+ `:scope` option on the `slugged` method. Let's say you wanted to limit the scope
119
+ of a `Product`'s slug to its associated `Department`; that way you could have a
114
120
  product named "keyboard" in both the Computer Supplies and the Music Supplies
115
- departments. To do so, override the @:scope@ option with a method name (as
116
- symbol) or a @Proc@ that limits the scope of the uniqueness requirement:
121
+ departments. To do so, override the `:scope` option with a method name (as
122
+ symbol) or a `Proc` that limits the scope of the uniqueness requirement:
117
123
 
118
- <pre><code>
124
+ ```` ruby
119
125
  class Product < ActiveRecord::Base
120
126
  include Slugalicious
121
127
  belongs_to :department
@@ -127,7 +133,7 @@ class Product < ActiveRecord::Base
127
133
  department.name.to_url + "/"
128
134
  end
129
135
  end
130
- </code></pre>
136
+ ````
131
137
 
132
138
  Now, your computer keyboard's slug will be "computer-supplies/keyboard" and your
133
139
  piano keyboard's slug will be "music-supplies/keyboard". There's an important
@@ -135,30 +141,30 @@ thing to notice here: The method or proc you use to scope the slug must return a
135
141
  proper URL substring. That typically means you need to URL-escape it and add a
136
142
  slash at the end, as shown in the example above.
137
143
 
138
- When you call @to_param@ on your piano keyboard, instead of just "keyboard", you
144
+ When you call `to_param` on your piano keyboard, instead of just "keyboard", you
139
145
  will get "music-supplies/keyboard". Likewise, you can use the
140
- @find_from_slug_path@ method to find a record from its full path, slug and scope
146
+ `find_from_slug_path` method to find a record from its full path, slug and scope
141
147
  included. You would usually use this method in conjunction with route globbing.
142
- For example, we could set up our @routes.rb@ file like so:
148
+ For example, we could set up our `routes.rb` file like so:
143
149
 
144
- <pre><code>
150
+ ```` ruby
145
151
  get '/products/*path', 'products#show', as: :products
146
- </code></pre>
152
+ ````
147
153
 
148
- Then, in our @ProductsController@, we load the product from the path slug like
154
+ Then, in our `ProductsController`, we load the product from the path slug like
149
155
  so:
150
156
 
151
- <pre><code>
157
+ ```` ruby
152
158
  def find_product
153
159
  @product = Product.find_from_slug_path(params[:path])
154
160
  end
155
- </code></pre>
161
+ ````
156
162
 
157
- This is why it's very convenient to have your @:scope@ method/proc not only
163
+ This is why it's very convenient to have your `:scope` method/proc not only
158
164
  return the uniqueness constraint, but also the scoped portion of the URL
159
165
  preceding the slug.
160
166
 
161
- h3. Altering and expiring slugs
167
+ ### Altering and expiring slugs
162
168
 
163
169
  When a model is created, it gets one slug, marked as the active slug (by
164
170
  default). This slug is the first generator that produces a unique slug string.
@@ -169,7 +175,7 @@ that slug is made the active slug. (Priority goes to the first slug generator
169
175
  that produces an existing slug [active or inactive]).
170
176
 
171
177
  If none of the slug generators generates a known, existing slug belonging to the
172
- object, then the first unique slug is used. A new @Slug@ instance is created and
178
+ object, then the first unique slug is used. A new `Slug` instance is created and
173
179
  marked as active, and any other slugs belonging to the object are marked as
174
180
  inactive.
175
181
 
@@ -181,9 +187,9 @@ current.
181
187
  A common application of this is to have inactive slugs 301-redirect to the
182
188
  active slug, as a way of both updating search engines' indexes and ensuring that
183
189
  people know the URL has changed. As an example of how do this, we alter the
184
- @find_product@ method shown above to be like so:
190
+ `find_product` method shown above to be like so:
185
191
 
186
- <pre><code>
192
+ ```` ruby
187
193
  def find_product
188
194
  @product = Product.find_from_slug_path(params[:path])
189
195
  unless @product.active_slug?(params[:path].split('/').last)
@@ -192,7 +198,7 @@ def find_product
192
198
  end
193
199
  return true
194
200
  end
195
- </code></pre>
201
+ ````
196
202
 
197
203
  The old URL will remain indefinitely, but users who hit it will be redirected to
198
204
  the new URL. Ideally, links to the old URL will be replaced over time with links
@@ -207,9 +213,9 @@ keyboard), you'd find its slug is "keyboard;2" or similar.
207
213
  To prevent the slug namespace from becoming more and more polluted over time,
208
214
  websites generally expire inactive slugs after a period of time. To do this in
209
215
  Slugalicious, write a task that periodically checks for and deletes old,
210
- inactive @Slug@ records. Such a task could be invoked through a cron job, for
216
+ inactive `Slug` records. Such a task could be invoked through a cron job, for
211
217
  instance. An example:
212
218
 
213
- <pre><code>
219
+ ```` ruby
214
220
  Slug.inactive.where([ "created_at < ?", 30.days.ago ]).delete_all
215
- </code></pre>
221
+ ````
@@ -1,7 +1,7 @@
1
1
  require 'slugalicious_generator'
2
2
  require 'stringex'
3
3
 
4
- # Adds the @slugged@ method to an @ActiveRecord::Base@ subclass. You can then
4
+ # Adds the `slugged` method to an `ActiveRecord::Base` subclass. You can then
5
5
  # call this method to add slugging support to your model. See the
6
6
  # {ClassMethods#slugged} method for more details.
7
7
  #
@@ -47,7 +47,7 @@ module Slugalicious
47
47
  # not found.
48
48
 
49
49
  def find_from_slug(slug, scope=nil)
50
- Slug.from_slug(self, scope, slug).first.try(:sluggable)
50
+ Slug.from_slug(self, scope, slug).first.try!(:sluggable)
51
51
  end
52
52
 
53
53
  # Locates a record from a given path, that consists of a slug and its scope,
@@ -67,17 +67,17 @@ module Slugalicious
67
67
  protected
68
68
 
69
69
  # Call this method to indicate that your model uses slugging. Pass a list of
70
- # *slug generators*: either symbols (method names) or procs that return
70
+ # **slug generators**: either symbols (method names) or procs that return
71
71
  # strings. These strings will be used to generate the slug. You must pass at
72
72
  # least one generator. If you pass more than one, the first one that returns
73
73
  # a unique slug will be used.
74
74
  #
75
75
  # The generator does not need to sanitize or parameterize its output; the
76
- # @:slugifier@ option can be used to override the default parameterization.
76
+ # `:slugifier` option can be used to override the default parameterization.
77
77
  #
78
78
  # In the event that no generator returns a unique slug, the slug returned by
79
79
  # the last generator will have the ID of the record appended to it. The ID
80
- # and the slug will be separated by the @:id_separator@ option (semicolon by
80
+ # and the slug will be separated by the `:id_separator` option (semicolon by
81
81
  # default). _This_ slug is hopefully unique, because if not, an exception is
82
82
  # raised.
83
83
  #
@@ -86,28 +86,28 @@ module Slugalicious
86
86
  #
87
87
  # h2. Scopes
88
88
  #
89
- # You can scope your slugs to certain URL subpaths using the @:scope@
90
- # option. The @:scope:@ option takes a method name or a @Proc@ that, when
89
+ # You can scope your slugs to certain URL subpaths using the `:scope`
90
+ # option. The `:scope:` option takes a method name or a `Proc` that, when
91
91
  # run, returns a string that scopes the uniqueness constraint of a slug.
92
92
  # Rather than being globally unique, the slug must only be unique among
93
93
  # other slugs that share the same scope.
94
94
  #
95
- # *Important note:* The method or @Proc@ that you use for the @:scope@
95
+ # **Important note:** The method or `Proc` that you use for the `:scope`
96
96
  # option should return the portion of the URL preceding the slug, _slash
97
- # included_. Let's say you have slugged your @User@ model's @login@ field,
97
+ # included_. Let's say you have slugged your `User` model's `login` field,
98
98
  # and you have two scopes: customers and merchants. In that case, you would
99
- # want the @:scope@ method/proc to return either "clients/" or "merchants/".
99
+ # want the `:scope` method/proc to return either "clients/" or "merchants/".
100
100
  #
101
- # The string returned by the @:scope@ option will be used to build the full
102
- # URL to an object. If you have a client @User@ with login "fancylad", a
103
- # call to @to_param@ will return "clients/fancyland". The scope portion of
101
+ # The string returned by the `:scope` option will be used to build the full
102
+ # URL to an object. If you have a client `User` with login "fancylad", a
103
+ # call to `to_param` will return "clients/fancyland". The scope portion of
104
104
  # that URL path is used un-sanitized, un-escaped, and un-processed. It is
105
105
  # therefore up to _you_ to ensure your scopes are valid URL strings, using
106
- # say @String#to_url@ (included as part of this gem).
106
+ # say `String#to_url` (included as part of this gem).
107
107
  #
108
108
  # @overload slugged(generator, ..., options={})
109
- # @param [Proc, Symbol] generator If it's a @Symbol@, indicates a method
110
- # that will be called that will return a @String@ to be used for the
109
+ # @param [Proc, Symbol] generator If it's a `Symbol`, indicates a method
110
+ # that will be called that will return a `String` to be used for the
111
111
  # slug.
112
112
  # @param [Hash] options Additonal options that control slug generation.
113
113
  # @option options [Proc] :slugifier (&:to_url) A proc that, when given a
@@ -116,13 +116,13 @@ module Slugalicious
116
116
  # the "last-resort" slug between the slug and the model ID. This should
117
117
  # be an URL-safe character that would never be produced by your
118
118
  # slugifier.
119
- # @option options [Symbol, Proc] :scope A method name or @Proc@ to run
119
+ # @option options [Symbol, Proc] :scope A method name or `Proc` to run
120
120
  # (receives the object being slugged) that returns a string. Slugs must
121
121
  # be unique across all objects for which this method/proc returns the
122
122
  # same value. If not provided, slugs must be globally unique for this
123
123
  # model. The string returned should be equal to the portion of the URL
124
124
  # path that precedes the slug.
125
- # @option options [Array<String>, String] :blacklist ([ 'new', 'edit', 'delete' ])
125
+ # @option options [Array<String>, String] :blacklist ([ 'new', 'edit', 'delete', 'destroy' ])
126
126
  # A list of slugs that are disallowed. You would use this to prevent
127
127
  # slugs from sharing the same name as actions in your resource
128
128
  # controller.
@@ -145,28 +145,28 @@ module Slugalicious
145
145
  elsif options[:scope] then
146
146
  raise ArgumentError, ":scope must be a symbol or proc"
147
147
  end
148
- self._slug_blacklist = Array.wrap(options[:blacklist] || %w( new edit delete ))
148
+ self._slug_blacklist = Array.wrap(options[:blacklist] || %w( new edit delete destroy ))
149
149
 
150
150
  after_save :make_slug
151
151
  end
152
152
  end
153
153
 
154
154
  def slug_object
155
- slugs.loaded? ? slugs.detect(&:active) : slugs.active.first
155
+ slugs.loaded? ? slugs.detect(&:active?) : slugs.active.first
156
156
  end
157
157
  private :slug_object
158
158
 
159
- # @return [String, nil] The slug for this object, or @nil@ if none has been
159
+ # @return [String, nil] The slug for this object, or `nil` if none has been
160
160
  # assigned.
161
161
 
162
162
  def slug
163
163
  Rails.cache.fetch("Slug/#{self.class.to_s}/#{id}/slug") do
164
- slug_object.try(:slug)
164
+ slug_object.try!(:slug)
165
165
  end
166
166
  end
167
167
 
168
168
  # @return [String, nil] The full slug and path for this object, with scope
169
- # included, or @nil@ if none has been assigned.
169
+ # included, or `nil` if none has been assigned.
170
170
 
171
171
  def slug_with_path
172
172
  Rails.cache.fetch("Slug/#{self.class.to_s}/#{id}/slug_with_path") do
@@ -175,9 +175,9 @@ module Slugalicious
175
175
  end
176
176
 
177
177
  # @param [String] slug A slug for this object.
178
- # @return [true, false, nil] @true@ if the slug is the currently active one
179
- # (should not redirect), @false@ if it's inactive (should redirect), and
180
- # @nil@ if it's not a known slug for the object (should 404).
178
+ # @return [true, false, nil] `true` if the slug is the currently active one
179
+ # (should not redirect), `false` if it's inactive (should redirect), and
180
+ # `nil` if it's not a known slug for the object (should 404).
181
181
 
182
182
  def active_slug?(slug)
183
183
  @active_slug ||= begin
@@ -200,7 +200,7 @@ module Slugalicious
200
200
  slugs_in_use = if slugs.loaded? then
201
201
  slugs.map(&:slug)
202
202
  else
203
- slugs.select(:slug).all.map(&:slug)
203
+ slugs.select(:slug).map(&:slug)
204
204
  end
205
205
 
206
206
  # grab a list of all potential slugs derived from the generators
@@ -232,7 +232,7 @@ module Slugalicious
232
232
  if self.class._slug_scope then
233
233
  scope = scope.where(scope: self.class._slug_scope[self])
234
234
  end
235
- taken_slug_objects = scope.all
235
+ taken_slug_objects = scope
236
236
 
237
237
  # subtract them out from all the potential slugs to make the available slugs
238
238
  available_slugs = potential_slugs - taken_slug_objects.map(&:slug)
@@ -243,7 +243,8 @@ module Slugalicious
243
243
  Slug.create!(sluggable: self,
244
244
  slug: available_slugs.first,
245
245
  active: true,
246
- scope: self.class._slug_scope.try(:call, self))
246
+ scope: self.class._slug_scope.try!(:call, self))
247
+ slugs(true)
247
248
  end
248
249
 
249
250
  @active_slug = nil
@@ -5,20 +5,19 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "slugalicious"
8
- s.version = "2.0.0"
8
+ s.version = "2.1.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Tim Morgan"]
12
- s.date = "2012-06-06"
12
+ s.date = "2013-07-09"
13
13
  s.description = "Slugalicious adds simple and powerful slugging to your ActiveRecord models."
14
14
  s.email = "git@timothymorgan.info"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.textile"
17
+ "README.md"
18
18
  ]
19
19
  s.files = [
20
20
  "LICENSE",
21
- "README.textile",
22
21
  "lib/slugalicious.rb",
23
22
  "lib/slugalicious_generator.rb",
24
23
  "slugalicious.gemspec",
@@ -28,37 +27,43 @@ Gem::Specification.new do |s|
28
27
  s.homepage = "http://github.com/riscfuture/slugalicious"
29
28
  s.require_paths = ["lib"]
30
29
  s.required_ruby_version = Gem::Requirement.new(">= 1.9")
31
- s.rubygems_version = "1.8.24"
30
+ s.rubygems_version = "2.0.3"
32
31
  s.summary = "Easy-to-use and powerful slugging for Rails 3"
33
32
 
34
33
  if s.respond_to? :specification_version then
35
- s.specification_version = 3
34
+ s.specification_version = 4
36
35
 
37
36
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
38
- s.add_runtime_dependency(%q<rails>, [">= 3.1"])
37
+ s.add_runtime_dependency(%q<rails>, [">= 4.0"])
39
38
  s.add_runtime_dependency(%q<stringex>, [">= 0"])
40
39
  s.add_development_dependency(%q<jeweler>, [">= 0"])
41
40
  s.add_development_dependency(%q<yard>, [">= 0"])
41
+ s.add_development_dependency(%q<redcarpet>, [">= 0"])
42
42
  s.add_development_dependency(%q<RedCloth>, [">= 0"])
43
43
  s.add_development_dependency(%q<sqlite3>, [">= 0"])
44
44
  s.add_development_dependency(%q<rspec>, [">= 0"])
45
+ s.add_development_dependency(%q<factory_girl>, [">= 0"])
45
46
  else
46
- s.add_dependency(%q<rails>, [">= 3.1"])
47
+ s.add_dependency(%q<rails>, [">= 4.0"])
47
48
  s.add_dependency(%q<stringex>, [">= 0"])
48
49
  s.add_dependency(%q<jeweler>, [">= 0"])
49
50
  s.add_dependency(%q<yard>, [">= 0"])
51
+ s.add_dependency(%q<redcarpet>, [">= 0"])
50
52
  s.add_dependency(%q<RedCloth>, [">= 0"])
51
53
  s.add_dependency(%q<sqlite3>, [">= 0"])
52
54
  s.add_dependency(%q<rspec>, [">= 0"])
55
+ s.add_dependency(%q<factory_girl>, [">= 0"])
53
56
  end
54
57
  else
55
- s.add_dependency(%q<rails>, [">= 3.1"])
58
+ s.add_dependency(%q<rails>, [">= 4.0"])
56
59
  s.add_dependency(%q<stringex>, [">= 0"])
57
60
  s.add_dependency(%q<jeweler>, [">= 0"])
58
61
  s.add_dependency(%q<yard>, [">= 0"])
62
+ s.add_dependency(%q<redcarpet>, [">= 0"])
59
63
  s.add_dependency(%q<RedCloth>, [">= 0"])
60
64
  s.add_dependency(%q<sqlite3>, [">= 0"])
61
65
  s.add_dependency(%q<rspec>, [">= 0"])
66
+ s.add_dependency(%q<factory_girl>, [">= 0"])
62
67
  end
63
68
  end
64
69
 
@@ -5,15 +5,21 @@
5
5
  # redirect purposes. Once a slug is old enough, it is deleted and its value can
6
6
  # be used for new records (no longer redirects).
7
7
  #
8
- # h2. Associations
8
+ # Associations
9
+ # ============
9
10
  #
10
- # | @sluggable@ | The record that this slug references. |
11
+ # | | |
12
+ # |:------------|:--------------------------------------|
13
+ # | `sluggable` | The record that this slug references. |
11
14
  #
12
- # h2. Properties
15
+ # Properties
16
+ # ==========
13
17
  #
14
- # | @slug@ | The slug, lowercased and normalized. Slugs must be unique to their @sluggable_type@ and @scope@. |
15
- # | @active@ | Whether this is the most recently generated slug for the sluggable. |
16
- # | @scope@ | Freeform data scoping this slug to a certain subset of records within the model. |
18
+ # | | |
19
+ # |:---------|:-------------------------------------------------------------------------------------------------|
20
+ # | `slug` | The slug, lowercased and normalized. Slugs must be unique to their `sluggable_type` and `scope`. |
21
+ # | `active` | Whether this is the most recently generated slug for the sluggable. |
22
+ # | `scope` | Freeform data scoping this slug to a certain subset of records within the model. |
17
23
 
18
24
  class Slug < ActiveRecord::Base
19
25
  belongs_to :sluggable, polymorphic: true
@@ -27,8 +33,8 @@ class Slug < ActiveRecord::Base
27
33
  scope :from_slug, ->(klass, scope, slug) {
28
34
  where(sluggable_type: klass.to_s, slug: slug, scope: scope)
29
35
  }
30
- scope :active, where(active: true)
31
- scope :inactive, where(active: false)
36
+ scope :active, -> { where(active: true) }
37
+ scope :inactive, -> { where(active: false) }
32
38
 
33
39
  validates :sluggable_type,
34
40
  presence: true
@@ -38,22 +44,22 @@ class Slug < ActiveRecord::Base
38
44
  validates :slug,
39
45
  presence: true,
40
46
  length: { maximum: 126 },
41
- uniqueness: { case_sensitive: false, scope: [ :scope, :sluggable_type ] } #TODO validate scope case-insensitively
47
+ uniqueness: { case_sensitive: false, scope: [ :scope, :sluggable_type ] }
42
48
  validates :scope,
43
49
  length: { maximum: 126 },
44
- allow_blank: true
50
+ allow_nil: true
45
51
  validate :one_active_slug_per_object
46
-
52
+
47
53
  after_save :invalidate_cache
48
54
  after_destroy :invalidate_cache
49
-
55
+
50
56
  # Marks a slug as active and deactivates all other slugs assigned to the
51
57
  # record.
52
58
 
53
59
  def activate!
54
60
  self.class.transaction do
55
61
  Slug.for(sluggable_type, sluggable_id).update_all(active: false)
56
- update_attribute :active, true
62
+ update_column :active, true
57
63
  end
58
64
  end
59
65
 
@@ -63,7 +69,7 @@ class Slug < ActiveRecord::Base
63
69
  return unless new_record? or (active? and active_changed?)
64
70
  errors.add(:active, :one_per_sluggable) if active? and Slug.active.for(sluggable_type, sluggable_id).count > 0
65
71
  end
66
-
72
+
67
73
  def invalidate_cache
68
74
  Rails.cache.delete "Slug/#{sluggable_type}/#{sluggable_id}/slug"
69
75
  Rails.cache.delete "Slug/#{sluggable_type}/#{sluggable_id}/slug_with_path"
metadata CHANGED
@@ -1,126 +1,139 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: slugalicious
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.0
5
- prerelease:
4
+ version: 2.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Tim Morgan
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2012-06-06 00:00:00.000000000 Z
11
+ date: 2013-07-09 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: rails
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ! '>='
17
+ - - '>='
20
18
  - !ruby/object:Gem::Version
21
- version: '3.1'
19
+ version: '4.0'
22
20
  type: :runtime
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ! '>='
24
+ - - '>='
28
25
  - !ruby/object:Gem::Version
29
- version: '3.1'
26
+ version: '4.0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: stringex
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ! '>='
31
+ - - '>='
36
32
  - !ruby/object:Gem::Version
37
33
  version: '0'
38
34
  type: :runtime
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ! '>='
38
+ - - '>='
44
39
  - !ruby/object:Gem::Version
45
40
  version: '0'
46
41
  - !ruby/object:Gem::Dependency
47
42
  name: jeweler
48
43
  requirement: !ruby/object:Gem::Requirement
49
- none: false
50
44
  requirements:
51
- - - ! '>='
45
+ - - '>='
52
46
  - !ruby/object:Gem::Version
53
47
  version: '0'
54
48
  type: :development
55
49
  prerelease: false
56
50
  version_requirements: !ruby/object:Gem::Requirement
57
- none: false
58
51
  requirements:
59
- - - ! '>='
52
+ - - '>='
60
53
  - !ruby/object:Gem::Version
61
54
  version: '0'
62
55
  - !ruby/object:Gem::Dependency
63
56
  name: yard
64
57
  requirement: !ruby/object:Gem::Requirement
65
- none: false
66
58
  requirements:
67
- - - ! '>='
59
+ - - '>='
68
60
  - !ruby/object:Gem::Version
69
61
  version: '0'
70
62
  type: :development
71
63
  prerelease: false
72
64
  version_requirements: !ruby/object:Gem::Requirement
73
- none: false
74
65
  requirements:
75
- - - ! '>='
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: redcarpet
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
76
81
  - !ruby/object:Gem::Version
77
82
  version: '0'
78
83
  - !ruby/object:Gem::Dependency
79
84
  name: RedCloth
80
85
  requirement: !ruby/object:Gem::Requirement
81
- none: false
82
86
  requirements:
83
- - - ! '>='
87
+ - - '>='
84
88
  - !ruby/object:Gem::Version
85
89
  version: '0'
86
90
  type: :development
87
91
  prerelease: false
88
92
  version_requirements: !ruby/object:Gem::Requirement
89
- none: false
90
93
  requirements:
91
- - - ! '>='
94
+ - - '>='
92
95
  - !ruby/object:Gem::Version
93
96
  version: '0'
94
97
  - !ruby/object:Gem::Dependency
95
98
  name: sqlite3
96
99
  requirement: !ruby/object:Gem::Requirement
97
- none: false
98
100
  requirements:
99
- - - ! '>='
101
+ - - '>='
100
102
  - !ruby/object:Gem::Version
101
103
  version: '0'
102
104
  type: :development
103
105
  prerelease: false
104
106
  version_requirements: !ruby/object:Gem::Requirement
105
- none: false
106
107
  requirements:
107
- - - ! '>='
108
+ - - '>='
108
109
  - !ruby/object:Gem::Version
109
110
  version: '0'
110
111
  - !ruby/object:Gem::Dependency
111
112
  name: rspec
112
113
  requirement: !ruby/object:Gem::Requirement
113
- none: false
114
114
  requirements:
115
- - - ! '>='
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: factory_girl
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
116
130
  - !ruby/object:Gem::Version
117
131
  version: '0'
118
132
  type: :development
119
133
  prerelease: false
120
134
  version_requirements: !ruby/object:Gem::Requirement
121
- none: false
122
135
  requirements:
123
- - - ! '>='
136
+ - - '>='
124
137
  - !ruby/object:Gem::Version
125
138
  version: '0'
126
139
  description: Slugalicious adds simple and powerful slugging to your ActiveRecord models.
@@ -129,37 +142,36 @@ executables: []
129
142
  extensions: []
130
143
  extra_rdoc_files:
131
144
  - LICENSE
132
- - README.textile
145
+ - README.md
133
146
  files:
134
147
  - LICENSE
135
- - README.textile
136
148
  - lib/slugalicious.rb
137
149
  - lib/slugalicious_generator.rb
138
150
  - slugalicious.gemspec
139
151
  - templates/create_slugs.rb
140
152
  - templates/slug.rb
153
+ - README.md
141
154
  homepage: http://github.com/riscfuture/slugalicious
142
155
  licenses: []
156
+ metadata: {}
143
157
  post_install_message:
144
158
  rdoc_options: []
145
159
  require_paths:
146
160
  - lib
147
161
  required_ruby_version: !ruby/object:Gem::Requirement
148
- none: false
149
162
  requirements:
150
- - - ! '>='
163
+ - - '>='
151
164
  - !ruby/object:Gem::Version
152
165
  version: '1.9'
153
166
  required_rubygems_version: !ruby/object:Gem::Requirement
154
- none: false
155
167
  requirements:
156
- - - ! '>='
168
+ - - '>='
157
169
  - !ruby/object:Gem::Version
158
170
  version: '0'
159
171
  requirements: []
160
172
  rubyforge_project:
161
- rubygems_version: 1.8.24
173
+ rubygems_version: 2.0.3
162
174
  signing_key:
163
- specification_version: 3
175
+ specification_version: 4
164
176
  summary: Easy-to-use and powerful slugging for Rails 3
165
177
  test_files: []