friendly_id 3.2.0.beta1 → 3.2.0.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -8,8 +8,10 @@ suggestions, ideas and improvements to FriendlyId.
8
8
 
9
9
  ## 3.2.0 (NOT RELEASED YET)
10
10
 
11
+ * Fixed deprecation on Rails edge. Thanks [slbug](http://github.com/slbug)
11
12
  * Removes `:scope` as a find parameter, allowing more flexible finds with
12
13
  scoped records.
14
+ * Improve logic of `friendly_id:redo_slugs` to support models with non-numeric ids. (thanks Oleksandr Petrov)
13
15
 
14
16
  ## 3.1.8 (2010-11-22)
15
17
 
data/Guide.md CHANGED
@@ -425,12 +425,16 @@ Note that this method is **not** used by slugged models.
425
425
 
426
426
  ## Scoped Slugs
427
427
 
428
+ _Note that in FriendlyId prior to 3.2.0, you could specify a non-standard
429
+ `:scope` argument on finds. This feature has been removed in 3.2.0 in favor of
430
+ the query stategies described below._
431
+
428
432
  FriendlyId can generate unique slugs within a given scope. For example, assume
429
- you have an application that displays restaurants. Without scoped slugs, if
430
- two restaurants are named "Joe's Diner," the second one will end up with
431
- "joes-diner--2" as its friendly_id. Using scoped allows you to keep the
432
- slug names unique for each city, so that the second "Joe's Diner" could have
433
- the slug "joes-diner" if it's located in a different city:
433
+ you have an application that displays restaurants. Without scoped slugs, if two
434
+ restaurants are named "Joe's Diner," the second one will end up with
435
+ "joes-diner--2" as its friendly_id. Using scoped allows you to keep the slug
436
+ names unique for each city, so that the second "Joe's Diner" can also have the
437
+ slug "joes-diner", as long as it's located in a different city:
434
438
 
435
439
  class Restaurant < ActiveRecord::Base
436
440
  belongs_to :city
@@ -442,11 +446,9 @@ the slug "joes-diner" if it's located in a different city:
442
446
  has_friendly_id :name, :use_slug => true
443
447
  end
444
448
 
445
- http://example.org/cities/seattle/restaurants/joes-diner
446
- http://example.org/cities/chicago/restaurants/joes-diner
449
+ City.find("seattle").restaurants.find("joes-diner")
450
+ City.find("chicago").restaurants.find("joes-diner")
447
451
 
448
- City.find("seattle").restaurants.find("joes-diner") # returns 1 record
449
- City.find("chicago").restaurants.find("joes-diner") # returns 1 record
450
452
 
451
453
  The value for the `:scope` key in your model can be a custom method you
452
454
  define, or the name of a relation. If it's the name of a relation, then the
@@ -456,6 +458,12 @@ its `to_param` method returns its friendly_id: "chicago" or "seattle".
456
458
 
457
459
  ### Complications with Scoped Slugs
458
460
 
461
+ #### Scoped Models and Cached Slugs
462
+
463
+ If you want to use cached slugs with scoped models, be sure not to create a unique index on the
464
+ `cached_slug` column.
465
+
466
+
459
467
  #### Finding Records by friendly\_id
460
468
 
461
469
  If you are using scopes your friendly ids may not be unique, so a simple find like
@@ -475,12 +483,10 @@ either query as a relation, or specify the scope in your query conditions:
475
483
 
476
484
  #### Finding All Records That Match a Scoped ID
477
485
 
478
- If you want to find all records with a partular friendly\_id regardless of scope,
486
+ If you want to find all records with a particular friendly\_id regardless of scope,
479
487
  the easiest way is to use cached slugs and query this column directly:
480
488
 
481
489
  Restaurant.find_all_by_cached_slug("joes-diner")
482
- # Another option, with Active Record 3.x
483
- Restaurant.where(:cached_slug => "joes-diner")
484
490
 
485
491
 
486
492
  If you're not using cached slugs, then this is slightly more complicated, but
@@ -494,38 +500,31 @@ still doable:
494
500
 
495
501
  #### Updating a Relation's Scoped Slugs
496
502
 
497
- When using a relation as the scope, updating the relation will update the
498
- slugs, but only if both models have specified the relationship. In the above
499
- example, updates to City will update the slugs for Restaurant because City
500
- specifies that it `has_many :restaurants`.
503
+ When using a relation as the scope, updating the relation will update the slugs,
504
+ but only if both models have specified the relationship. In the above example,
505
+ updates to City will update the slugs for Restaurant because City specifies that
506
+ it `has_many :restaurants`.
501
507
 
502
508
  ### Routes for Scoped Models
503
509
 
504
- Note that FriendlyId does not set up any routes for scoped models; you must
505
- do this yourself in your application. Here's an example of one way to set
506
- this up:
510
+ Note that FriendlyId does not set up any routes for scoped models; you must do
511
+ this yourself in your application. Here's an example of one way to set this up:
507
512
 
508
513
  # in routes.rb
509
- map.resources :restaurants
510
- map.restaurant "/restaurants/:city_id/:id", :controller => "restaurants"
514
+ resources :cities do
515
+ resources :restaurants
516
+ end
511
517
 
512
518
  # in views
513
- link_to 'Show', restaurant_path(restaurant.city, restaurant)
519
+ <%= link_to 'Show', [@city, @restaurant] %>
514
520
 
515
521
  # in controllers
516
522
  @city = City.find(params[:city_id])
517
- @restaurant = @city.resaturants.find(params[:id])
518
-
519
- ### Scoped Models and Cached Slugs
520
-
521
- If you want to use cached slugs with scoped models, be sure not to create a unique index on the
522
- `cached_slug` column.
523
-
524
- ### Scoped Models in FriendyId Before 3.2.0
523
+ @restaurant = @city.restaurants.find(params[:id])
525
524
 
526
- In older versions of FriendlyId, you could specify a non-standard `:scope`
527
- argument to finds. This feature has been removed in 3.2.0 in favor of the query
528
- stategies described above.
525
+ # URL's:
526
+ http://example.org/cities/seattle/restaurants/joes-diner
527
+ http://example.org/cities/chicago/restaurants/joes-diner
529
528
 
530
529
 
531
530
  ## FriendlyId Rake Tasks
@@ -10,8 +10,14 @@ module FriendlyId
10
10
  include FriendlyId::Base
11
11
 
12
12
  def has_friendly_id(method, options = {})
13
- class_inheritable_accessor :friendly_id_config
14
- write_inheritable_attribute :friendly_id_config, Configuration.new(self, method, options)
13
+ if FriendlyId.on_ar3?
14
+ class_attribute :friendly_id_config
15
+ self.friendly_id_config = Configuration.new(self, method, options)
16
+ else
17
+ class_inheritable_accessor :friendly_id_config
18
+ write_inheritable_attribute :friendly_id_config, Configuration.new(self, method, options)
19
+ end
20
+
15
21
  if friendly_id_config.use_slug?
16
22
  include SluggedModel
17
23
  else
@@ -20,6 +20,10 @@ module FriendlyId
20
20
  @klass = klass
21
21
  @id = id
22
22
  @options = options
23
+ if options[:scope]
24
+ raise "The :scope finder option has been removed from FriendlyId 3.2.0 " +
25
+ "https://github.com/norman/friendly_id/issues#issue/88"
26
+ end
23
27
  end
24
28
 
25
29
  def find_one
@@ -133,6 +133,14 @@ module FriendlyId
133
133
  end
134
134
  end
135
135
 
136
+ def apply_finder_options(options)
137
+ if options[:scope]
138
+ raise "The :scope finder option has been removed from FriendlyId 3.2.0 " +
139
+ "https://github.com/norman/friendly_id/issues#issue/88"
140
+ end
141
+ super
142
+ end
143
+
136
144
  protected
137
145
 
138
146
  def find_one(id)
@@ -154,4 +162,4 @@ module FriendlyId
154
162
  end
155
163
  end
156
164
  end
157
- end
165
+ end
@@ -26,15 +26,20 @@ module FriendlyId
26
26
 
27
27
  def make_slugs
28
28
  validate_uses_slugs
29
- cond = "slugs.id IS NULL"
30
- options = {:limit => 100, :include => :slugs, :conditions => cond, :order => "#{klass.table_name}.id ASC"}.merge(task_options || {})
29
+ options = {
30
+ :include => :slug,
31
+ :limit => (ENV["LIMIT"] || 100).to_i,
32
+ :offset => 0,
33
+ :order => ENV["ORDER"] || "#{klass.table_name}.id ASC",
34
+ }.merge(task_options || {})
35
+
31
36
  while records = find(:all, options) do
32
37
  break if records.size == 0
33
38
  records.each do |record|
34
- record.save(:validate => false)
39
+ record.save(:validate => false) unless record.slug?
35
40
  yield(record) if block_given?
36
41
  end
37
- options[:conditions] = cond + " and #{klass.table_name}.id > #{records.last.id}"
42
+ options[:offset] += options[:limit]
38
43
  end
39
44
  end
40
45
 
@@ -17,7 +17,7 @@ module FriendlyId
17
17
  # @raise FriendlyId::ReservedError
18
18
  def validate_for!(config)
19
19
  truncate_bytes!(config.max_length)
20
- raise FriendlyId::BlankError if blank?
20
+ raise FriendlyId::BlankError if empty?
21
21
  raise FriendlyId::ReservedError if config.reserved?(self)
22
22
  self
23
23
  end
@@ -3,7 +3,7 @@ module FriendlyId
3
3
  MAJOR = 3
4
4
  MINOR = 2
5
5
  TINY = 0
6
- BUILD = "beta1"
6
+ BUILD = "rc1"
7
7
  STRING = [MAJOR, MINOR, TINY, BUILD].compact.join('.')
8
8
  end
9
9
  end
@@ -2,7 +2,7 @@ namespace :friendly_id do
2
2
  desc "Make slugs for a model."
3
3
  task :make_slugs => :environment do
4
4
  FriendlyId::TaskRunner.new.make_slugs do |record|
5
- puts "%s(%d): friendly_id set to '%s'" % [record.class.to_s, record.id, record.slug.name] if record.slug
5
+ puts "#{record.class}(#{record.id}): friendly_id set to '#{record.slug.name}'" if record.slug
6
6
  end
7
7
  end
8
8
 
@@ -16,4 +16,4 @@ namespace :friendly_id do
16
16
  task :remove_old_slugs => :environment do
17
17
  FriendlyId::TaskRunner.new.delete_old_slugs
18
18
  end
19
- end
19
+ end
@@ -26,6 +26,12 @@ module FriendlyId
26
26
  Tourist.delete_all
27
27
  end
28
28
 
29
+ test "As of 3.2.0, should raise error if :scope option is passed" do
30
+ assert_raise(RuntimeError) do
31
+ Tourist.find("hello", :scope => "usa")
32
+ end
33
+ end
34
+
29
35
  test "should not use cached slug column with scopes" do
30
36
  @tourist = Tourist.create!(:name => "John Smith", :country => @usa)
31
37
  @tourist2 = Tourist.create!(:name => "John Smith", :country => @canada)
metadata CHANGED
@@ -6,8 +6,8 @@ version: !ruby/object:Gem::Version
6
6
  - 3
7
7
  - 2
8
8
  - 0
9
- - beta1
10
- version: 3.2.0.beta1
9
+ - rc1
10
+ version: 3.2.0.rc1
11
11
  platform: ruby
12
12
  authors:
13
13
  - Norman Clarke
@@ -17,7 +17,7 @@ autorequire:
17
17
  bindir: bin
18
18
  cert_chain: []
19
19
 
20
- date: 2010-11-23 00:00:00 -03:00
20
+ date: 2011-01-12 00:00:00 -03:00
21
21
  default_executable:
22
22
  dependencies:
23
23
  - !ruby/object:Gem::Dependency
@@ -30,8 +30,8 @@ dependencies:
30
30
  segments:
31
31
  - 0
32
32
  - 2
33
- - 0
34
- version: 0.2.0
33
+ - 1
34
+ version: 0.2.1
35
35
  type: :runtime
36
36
  prerelease: false
37
37
  version_requirements: *id001
@@ -160,7 +160,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
160
160
  requirements:
161
161
  - - ">="
162
162
  - !ruby/object:Gem::Version
163
- hash: -2292774950521045189
163
+ hash: -1225128914130125951
164
164
  segments:
165
165
  - 0
166
166
  version: "0"