cmassimo-friendly_id 3.0.4.2

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.
Files changed (56) hide show
  1. data/Changelog.md +277 -0
  2. data/Contributors.md +39 -0
  3. data/Guide.md +561 -0
  4. data/LICENSE +19 -0
  5. data/README.md +83 -0
  6. data/Rakefile +66 -0
  7. data/extras/README.txt +3 -0
  8. data/extras/bench.rb +36 -0
  9. data/extras/extras.rb +38 -0
  10. data/extras/prof.rb +14 -0
  11. data/extras/template-gem.rb +26 -0
  12. data/extras/template-plugin.rb +28 -0
  13. data/generators/friendly_id/friendly_id_generator.rb +30 -0
  14. data/generators/friendly_id/templates/create_slugs.rb +18 -0
  15. data/lib/friendly_id.rb +73 -0
  16. data/lib/friendly_id/active_record.rb +52 -0
  17. data/lib/friendly_id/active_record_adapter/configuration.rb +67 -0
  18. data/lib/friendly_id/active_record_adapter/finders.rb +156 -0
  19. data/lib/friendly_id/active_record_adapter/simple_model.rb +123 -0
  20. data/lib/friendly_id/active_record_adapter/slug.rb +66 -0
  21. data/lib/friendly_id/active_record_adapter/slugged_model.rb +238 -0
  22. data/lib/friendly_id/active_record_adapter/tasks.rb +69 -0
  23. data/lib/friendly_id/configuration.rb +113 -0
  24. data/lib/friendly_id/finders.rb +109 -0
  25. data/lib/friendly_id/railtie.rb +20 -0
  26. data/lib/friendly_id/sequel.rb +5 -0
  27. data/lib/friendly_id/slug_string.rb +391 -0
  28. data/lib/friendly_id/slugged.rb +102 -0
  29. data/lib/friendly_id/status.rb +35 -0
  30. data/lib/friendly_id/test.rb +291 -0
  31. data/lib/friendly_id/version.rb +9 -0
  32. data/lib/generators/friendly_id_generator.rb +25 -0
  33. data/lib/tasks/friendly_id.rake +19 -0
  34. data/rails/init.rb +2 -0
  35. data/test/active_record_adapter/ar_test_helper.rb +119 -0
  36. data/test/active_record_adapter/basic_slugged_model_test.rb +14 -0
  37. data/test/active_record_adapter/cached_slug_test.rb +61 -0
  38. data/test/active_record_adapter/core.rb +98 -0
  39. data/test/active_record_adapter/custom_normalizer_test.rb +20 -0
  40. data/test/active_record_adapter/custom_table_name_test.rb +22 -0
  41. data/test/active_record_adapter/scoped_model_test.rb +118 -0
  42. data/test/active_record_adapter/simple_test.rb +76 -0
  43. data/test/active_record_adapter/slug_test.rb +34 -0
  44. data/test/active_record_adapter/slugged.rb +30 -0
  45. data/test/active_record_adapter/slugged_status_test.rb +25 -0
  46. data/test/active_record_adapter/sti_test.rb +22 -0
  47. data/test/active_record_adapter/support/database.jdbcsqlite3.yml +2 -0
  48. data/test/active_record_adapter/support/database.mysql.yml +4 -0
  49. data/test/active_record_adapter/support/database.postgres.yml +6 -0
  50. data/test/active_record_adapter/support/database.sqlite3.yml +2 -0
  51. data/test/active_record_adapter/support/models.rb +87 -0
  52. data/test/active_record_adapter/tasks_test.rb +82 -0
  53. data/test/friendly_id_test.rb +55 -0
  54. data/test/slug_string_test.rb +88 -0
  55. data/test/test_helper.rb +15 -0
  56. metadata +168 -0
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright (c) 2008-2010 Norman Clarke, Adrian Mugnolo and Emilio Tagua.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy
4
+ of this software and associated documentation files (the "Software"), to deal
5
+ in the Software without restriction, including without limitation the rights
6
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7
+ copies of the Software, and to permit persons to whom the Software is
8
+ furnished to do so, subject to the following conditions:
9
+
10
+ The above copyright notice and this permission notice shall be included in all
11
+ copies or substantial portions of the Software.
12
+
13
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
19
+ SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ # FriendlyId
2
+
3
+ FriendlyId is the "Swiss Army bulldozer" of slugging and permalink plugins for
4
+ Ruby on Rails. It allows you to create pretty URL's and work with
5
+ human-friendly strings as if they were numeric ids for ActiveRecord models.
6
+
7
+ Using FriendlyId, it's easy to make your application use URL's like:
8
+
9
+ http://example.com/states/washington
10
+
11
+ instead of:
12
+
13
+ http://example.com/states/4323454
14
+
15
+ ## This particular fork...
16
+
17
+ ...has been created to allow slug creation only on after save and slug update only when
18
+ the cached column on the model gets updated (existence of the latter is recommended)
19
+
20
+ ## FriendlyId Features
21
+
22
+ FriendlyId offers many advanced features, including: slug history and
23
+ versioning, scoped slugs, reserved words, custom slug generators, and
24
+ excellent Unicode support. For complete information on using FriendlyId,
25
+ please see the {http://norman.github.com/friendly_id/file.Guide.html FriendlyId Guide}.
26
+
27
+ FriendlyId is compatible with Rails 2.2.x - 3.0.
28
+
29
+ ## Rails Quickstart
30
+
31
+ gem install friendly_id
32
+
33
+ rails my_app
34
+
35
+ cd my_app
36
+
37
+ # add to Gemfile
38
+ gem "friendly_id", "~> 3.0"
39
+
40
+ rails generate friendly_id
41
+ rails generate scaffold user name:string cached_slug:string
42
+
43
+ rake db:migrate
44
+
45
+ # edit app/models/user.rb
46
+ class User < ActiveRecord::Base
47
+ has_friendly_id :name, :use_slug => true
48
+ end
49
+
50
+ User.create! :name => "Joe Schmoe"
51
+
52
+ ./script/server
53
+
54
+ GET http://0.0.0.0:3000/users/joe-schmoe
55
+
56
+ ## Docs, Info and Support
57
+
58
+ * [FriendlyId Guide](http://norman.github.com/friendly_id/file.Guide.html)
59
+ * [API Docs](http://norman.github.com/friendly_id)
60
+ * [Google Group](http://groups.google.com/group/friendly_id)
61
+ * [Source Code](http://github.com/norman/friendly_id/)
62
+ * [Issue Tracker](http://github.com/norman/friendly_id/issues)
63
+
64
+ ## Bugs:
65
+
66
+ Please report them on the [Github issue tracker](http://github.com/norman/friendly_id/issues)
67
+ for this project.
68
+
69
+ If you have a bug to report, please include the following information:
70
+
71
+ * Stack trace and error message.
72
+ * Version information for FriendlyId, Rails and Ruby.
73
+ * Any snippets of relevant model, view or controller code that shows how your
74
+ are using FriendlyId.
75
+
76
+ If you are able to, it helps even more if you can fork FriendlyId on Github,
77
+ and add a test that reproduces the error you are experiencing.
78
+
79
+ ## Credits:
80
+
81
+ FriendlyId was created by Norman Clarke, Adrian Mugnolo, and Emilio Tagua.
82
+
83
+ Copyright (c) 2008-2010, released under the MIT license.
data/Rakefile ADDED
@@ -0,0 +1,66 @@
1
+ require "rake"
2
+ require "rake/testtask"
3
+ require "rake/gempackagetask"
4
+ require "rake/rdoctask"
5
+ require "rake/clean"
6
+
7
+ task :default => :test
8
+
9
+ CLEAN << "pkg" << "doc" << "coverage" << ".yardoc"
10
+ Rake::GemPackageTask.new(eval(File.read("friendly_id.gemspec"))) { |pkg| }
11
+ Rake::RDocTask.new do |r|
12
+ r.rdoc_dir = "doc"
13
+ r.rdoc_files.include "lib/**/*.rb"
14
+ end
15
+
16
+ begin
17
+ require "yard"
18
+ YARD::Rake::YardocTask.new do |t|
19
+ t.options = ["--output-dir=doc"]
20
+ t.options << "--files" << ["Guide.md", "Contributors.md", "Changelog.md"].join(",")
21
+ end
22
+ rescue LoadError
23
+ end
24
+
25
+ begin
26
+ require "rcov/rcovtask"
27
+ Rcov::RcovTask.new do |r|
28
+ r.test_files = FileList["test/**/*_test.rb"]
29
+ r.verbose = true
30
+ r.rcov_opts << "--exclude gems/*"
31
+ end
32
+ rescue LoadError
33
+ end
34
+
35
+
36
+ Rake::TestTask.new(:test) { |t| t.pattern = "test/**/*_test.rb" }
37
+
38
+ namespace :test do
39
+ task :rails do
40
+ rm_rf "fid"
41
+ sh "rails --template extras/template-gem.rb fid"
42
+ sh "cd fid; rake test"
43
+ end
44
+ Rake::TestTask.new(:friendly_id) { |t| t.pattern = "test/*_test.rb" }
45
+ Rake::TestTask.new(:ar) { |t| t.pattern = "test/active_record_adapter/*_test.rb" }
46
+
47
+ namespace :rails do
48
+ task :plugin do
49
+ rm_rf "fid"
50
+ sh "rails --template extras/template-plugin.rb fid"
51
+ sh "cd fid; rake test"
52
+ end
53
+ end
54
+
55
+ end
56
+
57
+ task :pushdocs do
58
+ branch = `git branch | grep "*"`.chomp.gsub("* ", "")
59
+ sh "git stash"
60
+ sh "git checkout gh-pages"
61
+ sh "cp -rp doc/* ."
62
+ sh 'git commit -a -m "Regenerated docs"'
63
+ sh "git push origin gh-pages"
64
+ sh "git checkout #{branch}"
65
+ sh "git stash apply"
66
+ end
data/extras/README.txt ADDED
@@ -0,0 +1,3 @@
1
+ These templates are here to generate FriendlyId-enabled Rails apps for
2
+ testing. They are for developers, they are not intended for generating
3
+ "real" applications.
data/extras/bench.rb ADDED
@@ -0,0 +1,36 @@
1
+ require File.expand_path('../extras', __FILE__)
2
+ require 'rbench'
3
+ FACTOR = 10
4
+
5
+ RBench.run(TIMES) do
6
+
7
+ column :times
8
+ column :default
9
+ column :no_slug
10
+ column :slug
11
+ column :cached_slug
12
+
13
+ report 'find model by id', (TIMES * FACTOR).ceil do
14
+ default { User.find(get_id) }
15
+ no_slug { User.find(USERS.rand) }
16
+ slug { Post.find(POSTS.rand) }
17
+ cached_slug { District.find(DISTRICTS.rand) }
18
+ end
19
+
20
+ report 'find model using array of ids', (TIMES * FACTOR).ceil do
21
+ default { User.find(get_id(2)) }
22
+ no_slug { User.find(USERS.rand(2)) }
23
+ slug { Post.find(POSTS.rand(2)) }
24
+ cached_slug { District.find(DISTRICTS.rand(2)) }
25
+ end
26
+
27
+ report 'find model using id, then to_param', (TIMES * FACTOR).ceil do
28
+ default { User.find(get_id).to_param }
29
+ no_slug { User.find(USERS.rand).to_param }
30
+ slug { Post.find(POSTS.rand).to_param }
31
+ cached_slug { District.find(DISTRICTS.rand).to_param }
32
+ end
33
+
34
+ summary 'Total'
35
+
36
+ end
data/extras/extras.rb ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env ruby -KU
2
+ require File.dirname(__FILE__) + '/../test/test_helper'
3
+ require File.dirname(__FILE__) + '/../test/active_record_adapter/ar_test_helper'
4
+ require 'ffaker'
5
+
6
+ TIMES = (ENV['N'] || 100).to_i
7
+ POSTS = []
8
+ DISTRICTS = []
9
+ USERS = []
10
+
11
+ User.delete_all
12
+ Post.delete_all
13
+ District.delete_all
14
+ Slug.delete_all
15
+
16
+ 100.times do
17
+ name = Faker::Name.name
18
+ USERS << (User.create! :name => name).friendly_id
19
+ POSTS << (Post.create! :name => name).friendly_id
20
+ DISTRICTS << (District.create! :name => name).friendly_id
21
+ end
22
+
23
+ def get_id(returns = 1)
24
+ (1..100).to_a.rand(returns)
25
+ end
26
+
27
+ class Array
28
+ def rand(returns = 1)
29
+ @return = []
30
+ returns.times do
31
+ until @return.length == returns do
32
+ val = self[Kernel.rand(length)]
33
+ @return << val unless @return.include? val
34
+ end
35
+ end
36
+ return returns == 1 ? @return.first : @return
37
+ end
38
+ end
data/extras/prof.rb ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby -KU
2
+ require File.dirname(__FILE__) + '/extras'
3
+ require 'ruby-prof'
4
+
5
+ # RubyProf.measure_mode = RubyProf::MEMORY
6
+ GC.disable
7
+ RubyProf.start
8
+ 100.times do
9
+ Post.find(slug = POSTS.rand)
10
+ end
11
+ result = RubyProf.stop
12
+ GC.enable
13
+ printer = RubyProf::CallTreePrinter.new(result)
14
+ printer.print(File.new("prof.txt", "w"))
@@ -0,0 +1,26 @@
1
+ run "rm public/index.html"
2
+ gem "friendly_id"
3
+ gem "haml"
4
+ gem "will_paginate"
5
+ run "haml --rails ."
6
+ generate "friendly_id"
7
+ generate :haml_scaffold, "post title:string"
8
+ route "map.root :controller => 'posts', :action => 'index'"
9
+ rake "db:migrate"
10
+ rake "db:fixtures:load"
11
+ file 'app/models/post.rb',
12
+ %q{class Post < ActiveRecord::Base
13
+ has_friendly_id :title, :use_slug => true
14
+ end}
15
+ file 'test/fixtures/slugs.yml',
16
+ %q{
17
+ one:
18
+ name: mystring
19
+ sequence: 1
20
+ sluggable: one (Post)
21
+
22
+ two:
23
+ name: mystring
24
+ sequence: 1
25
+ sluggable: two (Post)
26
+ }
@@ -0,0 +1,28 @@
1
+ run "rm public/index.html"
2
+ inside 'vendor/plugins' do
3
+ run "git clone ../../../ friendly_id"
4
+ end
5
+ gem "haml"
6
+ gem "will_paginate"
7
+ run "haml --rails ."
8
+ generate "friendly_id"
9
+ generate :haml_scaffold, "post title:string"
10
+ route "map.root :controller => 'posts', :action => 'index'"
11
+ rake "db:migrate"
12
+ rake "db:fixtures:load"
13
+ file 'app/models/post.rb',
14
+ %q{class Post < ActiveRecord::Base
15
+ has_friendly_id :title, :use_slug => true
16
+ end}
17
+ file 'test/fixtures/slugs.yml',
18
+ %q{
19
+ one:
20
+ name: mystring
21
+ sequence: 1
22
+ sluggable: one (Post)
23
+
24
+ two:
25
+ name: mystring
26
+ sequence: 2
27
+ sluggable: two (Post)
28
+ }
@@ -0,0 +1,30 @@
1
+ class FriendlyIdGenerator < Rails::Generator::Base
2
+
3
+ RAKE_TASKS = File.join("..", "..", "..", "lib", "tasks", "friendly_id.rake")
4
+
5
+ def manifest
6
+ record do |m|
7
+ unless options[:skip_migration]
8
+ m.migration_template('create_slugs.rb', 'db/migrate', :migration_file_name => 'create_slugs')
9
+ end
10
+ unless options[:skip_tasks]
11
+ m.directory "lib/tasks"
12
+ m.file RAKE_TASKS, "lib/tasks/friendly_id.rake"
13
+ end
14
+ end
15
+ end
16
+
17
+ protected
18
+
19
+ def add_options!(opt)
20
+ opt.separator ''
21
+ opt.separator 'Options:'
22
+ opt.on("--skip-migration", "Don't generate a migration for the slugs table") do |value|
23
+ options[:skip_migration] = value
24
+ end
25
+ opt.on("--skip-tasks", "Don't add friendly_id Rake tasks to lib/tasks") do |value|
26
+ options[:skip_tasks] = value
27
+ end
28
+ end
29
+
30
+ end
@@ -0,0 +1,18 @@
1
+ class CreateSlugs < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :slugs do |t|
4
+ t.string :name
5
+ t.integer :sluggable_id
6
+ t.integer :sequence, :null => false, :default => 1
7
+ t.string :sluggable_type, :limit => 40
8
+ t.string :scope
9
+ t.datetime :created_at
10
+ end
11
+ add_index :slugs, :sluggable_id
12
+ add_index :slugs, [:name, :sluggable_type, :sequence, :scope], :name => "index_slugs_on_n_s_s_and_s", :unique => true
13
+ end
14
+
15
+ def self.down
16
+ drop_table :slugs
17
+ end
18
+ end
@@ -0,0 +1,73 @@
1
+ require "forwardable"
2
+ require "active_support/core_ext/class/attribute_accessors"
3
+ begin
4
+ require "active_support/core_ext/object/blank"
5
+ rescue MissingSourceFile
6
+ # support for ActiveSupport < 2.3.5
7
+ require "active_support/core_ext/blank"
8
+ end
9
+
10
+ require File.join(File.dirname(__FILE__), "friendly_id", "slug_string")
11
+ require File.join(File.dirname(__FILE__), "friendly_id", "configuration")
12
+ require File.join(File.dirname(__FILE__), "friendly_id", "status")
13
+ require File.join(File.dirname(__FILE__), "friendly_id", "finders")
14
+ require File.join(File.dirname(__FILE__), "friendly_id", "slugged")
15
+
16
+ # FriendlyId is a comprehensive Ruby library for slugging and permalinks with
17
+ # ActiveRecord.
18
+ # @author Norman Clarke
19
+ # @author Emilio Tagua
20
+ # @author Adrian Mugnolo
21
+ module FriendlyId
22
+
23
+ # An error based on this class is raised when slug generation fails
24
+ class SlugGenerationError < StandardError ; end
25
+
26
+ # Raised when the slug text is blank.
27
+ class BlankError < SlugGenerationError ; end
28
+
29
+ # Raised when the slug text is reserved.
30
+ class ReservedError < SlugGenerationError ; end
31
+
32
+ module Base
33
+ # Set up a model to use a friendly_id. This method accepts a hash with
34
+ # {FriendlyId::Configuration several possible options}.
35
+ #
36
+ # @param [#to_sym] method The column or method that should be used as the
37
+ # basis of the friendly_id string.
38
+ #
39
+ # @param [Hash] options For valid configuration options, see
40
+ # {FriendlyId::Configuration}.
41
+ #
42
+ # @example
43
+ #
44
+ # class User < ActiveRecord::Base
45
+ # has_friendly_id :user_name
46
+ # end
47
+ #
48
+ # class Post < ActiveRecord::Base
49
+ # has_friendly_id :title, :use_slug => true, :approximate_ascii => true
50
+ # end
51
+ #
52
+ # @see FriendlyId::Configuration
53
+ def has_friendly_id(method, options = {})
54
+ raise NotImplementedError
55
+ end
56
+
57
+ # Does the model class use the FriendlyId plugin?
58
+ def uses_friendly_id?
59
+ respond_to? :friendly_id_config
60
+ end
61
+ end
62
+
63
+ end
64
+
65
+ class String
66
+ def parse_friendly_id(separator = nil)
67
+ separator ||= FriendlyId::Configuration::DEFAULTS[:sequence_separator]
68
+ name, sequence = split(/#{Regexp.escape(separator)}(\d+)?\z/)
69
+ return name, sequence ||= "1"
70
+ end
71
+ end
72
+
73
+ require File.join(File.dirname(__FILE__), "friendly_id", "railtie") if defined?(Rails) && Rails.version >= "3"