slugged 0.3.2

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ .DS_Store
2
+ .bundle
3
+ *.tmproj
4
+ tmtags
5
+ *~
6
+ \#*
7
+ .\#*
8
+ *.swp
9
+ coverage
10
+ rdoc
11
+ pkg
12
+ *.gem
13
+ coverage
14
+ metrics/*
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use ree@slugged --create
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source :gemcutter
2
+
3
+ # Setup gems
4
+ gem "activerecord", "= 3.0.0"
5
+ gem "reversible_data"
6
+ gem "uuid"
7
+ gem "sqlite3-ruby", :require => "sqlite3"
8
+
9
+ gem "shoulda", :require => nil
10
+ gem "redgreen", :require => nil if RUBY_VERSION < "1.9"
11
+ gem "rcov", :require => nil
12
+ gem "reek", :require => nil
13
+ gem "roodi", :require => nil
14
+ gem "flay", :require => nil
15
+ gem "flog", :require => nil
16
+ gem "rake", :require => nil
17
+ gem "Saikuro", :require => nil
18
+ gem "jeweler", :require => nil
19
+
20
+ gem 'ruby-debug', :require => nil
data/Gemfile.lock ADDED
@@ -0,0 +1,82 @@
1
+ GEM
2
+ remote: http://rubygems.org/
3
+ specs:
4
+ Saikuro (1.1.0)
5
+ activemodel (3.0.0)
6
+ activesupport (= 3.0.0)
7
+ builder (~> 2.1.2)
8
+ i18n (~> 0.4.1)
9
+ activerecord (3.0.0)
10
+ activemodel (= 3.0.0)
11
+ activesupport (= 3.0.0)
12
+ arel (~> 1.0.0)
13
+ tzinfo (~> 0.3.23)
14
+ activesupport (3.0.0)
15
+ arel (1.0.1)
16
+ activesupport (~> 3.0.0)
17
+ builder (2.1.2)
18
+ columnize (0.3.1)
19
+ flay (1.4.1)
20
+ ruby_parser (~> 2.0)
21
+ sexp_processor (~> 3.0)
22
+ flog (2.5.0)
23
+ ruby_parser (~> 2.0)
24
+ sexp_processor (~> 3.0)
25
+ gemcutter (0.6.1)
26
+ git (1.2.5)
27
+ i18n (0.4.1)
28
+ jeweler (1.4.0)
29
+ gemcutter (>= 0.1.0)
30
+ git (>= 1.2.5)
31
+ rubyforge (>= 2.0.0)
32
+ json_pure (1.4.6)
33
+ linecache (0.43)
34
+ macaddr (1.0.0)
35
+ rake (0.8.7)
36
+ rcov (0.9.9)
37
+ redgreen (1.2.2)
38
+ reek (1.2.8)
39
+ ruby2ruby (~> 1.2)
40
+ ruby_parser (~> 2.0)
41
+ sexp_processor (~> 3.0)
42
+ reversible_data (0.1.0)
43
+ roodi (2.1.0)
44
+ ruby_parser
45
+ ruby-debug (0.10.3)
46
+ columnize (>= 0.1)
47
+ ruby-debug-base (~> 0.10.3.0)
48
+ ruby-debug-base (0.10.3)
49
+ linecache (>= 0.3)
50
+ ruby2ruby (1.2.5)
51
+ ruby_parser (~> 2.0)
52
+ sexp_processor (~> 3.0)
53
+ ruby_parser (2.0.5)
54
+ sexp_processor (~> 3.0)
55
+ rubyforge (2.0.4)
56
+ json_pure (>= 1.1.7)
57
+ sexp_processor (3.0.5)
58
+ shoulda (2.11.3)
59
+ sqlite3-ruby (1.3.1)
60
+ tzinfo (0.3.23)
61
+ uuid (2.3.1)
62
+ macaddr (~> 1.0)
63
+
64
+ PLATFORMS
65
+ ruby
66
+
67
+ DEPENDENCIES
68
+ Saikuro
69
+ activerecord (= 3.0.0)
70
+ flay
71
+ flog
72
+ jeweler
73
+ rake
74
+ rcov
75
+ redgreen
76
+ reek
77
+ reversible_data
78
+ roodi
79
+ ruby-debug
80
+ shoulda
81
+ sqlite3-ruby
82
+ uuid
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Darcy Laycock
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,125 @@
1
+ # Slugged #
2
+
3
+ ## About ###
4
+
5
+ Slugged is a simple slug library for ActiveRecord 3.0+.
6
+
7
+ It's main features are:
8
+
9
+ 1. A very simple and tested codebase
10
+ 2. Support for slug history (e.g. if a users slug changes, it will record the old slug)
11
+ 3. Simple defaulting for slugs to UUID's (to avoid showing ID's.)
12
+ 4. Built on ActiveRecord 3.0
13
+ 5. If stringex is installed, uses stringex's transliteration stuff
14
+
15
+
16
+ Slugged used to be called Pseudocephalopod - a name inspired by the Jason Wander series of
17
+ books which I just happened to be reading when I had the need for this that focuses on a
18
+ war with slug-like creatures.
19
+
20
+ ### Why? ###
21
+
22
+ I love the idea of friendly\_id, and most of the implementation but it felt bloated
23
+ to me and my experiences on getting it to work correctly with Rails 3 left a base taste
24
+ in my mouth / was altogether hacky.
25
+
26
+ Slugged is very much inspired by friendly id but with a much simpler codebase
27
+ and built to work on Rails 3 from the start.
28
+
29
+ ## Usage ##
30
+
31
+ Using Slugged is simple. In Rails, simply drop this in your Gemfile:
32
+
33
+ gem 'slugged'
34
+
35
+ Optionally restricting the version.
36
+
37
+ Next, if you wish to use slug history run:
38
+
39
+ $ rails generate slugged:slugs
40
+
41
+ Otherwise, when calling is\_sluggable make sure to include :history => false
42
+
43
+ Next, you need to add a cached slug column to your model and add an index. In your migration,
44
+ you'd usually want something like:
45
+
46
+ add_column :users, :cached_slug, :string
47
+ add_index :users, :cached_slug
48
+
49
+ Or, using our build in generator:
50
+
51
+ $ rails generate slugged:slug_migration Model
52
+
53
+ Lastly, in your model, call is\_sluggable:
54
+
55
+ class User
56
+ is_sluggable :name
57
+ end
58
+
59
+ is\_sluggable accepts the source method name as a symbol, and an optional has of options including:
60
+
61
+ * _:sync_ - when source column changes, save the result. Defaults to true.
62
+ * _:convertor_ - a symbol (for a method) or block for how to generate the base slug. Defaults to :to\_url if available, parameterize otherwise.
63
+ * _:history_ - use slug history (e.g. if the name changes, it records the previous version in a slugs table). Defaults to true
64
+ * _:uuid_ - If the slug is blank, uses a generated uuid instead. Defaults to true
65
+ * _:slug\_column_ - the column in which to store the slug. Defaults to _:cached\_slug_
66
+ * _:to\_param_ - if true (by default), overrides to_param to use the slug
67
+ * _:use\_cache_ - uses Slugged.cache if available to cache any lookups e.g. in memcache.
68
+
69
+ Once installed, it provides the following methods:
70
+
71
+ ### User.find\_using\_slug "some-slug" ###
72
+
73
+ Finds a user from a slug (which can be the record's id, it's cached slug or, if enabled, slug history)
74
+
75
+ ### User.other\_than(record) ###
76
+
77
+ Returns a relationship which returns records other than the given.
78
+
79
+ ### User.with\_cached\_slug(record) ###
80
+
81
+ Returns a relationship which returns records with the given cached slug.
82
+
83
+ ### User#generate\_slug ###
84
+
85
+ Forces the generation of a current slug
86
+
87
+ ### User#generate\_slug! ###
88
+
89
+ Forces the generation of a current slug and saves it
90
+
91
+ ### User#autogenerate\_slug ###
92
+
93
+ Generates a slug if not already present.
94
+
95
+ ### User#has\_better\_slug? ###
96
+
97
+ When found via Model.find\_using\_slug, it will return try
98
+ if there is a better slug available. Intended for use in redirects etc.
99
+
100
+ ## Working on Slugged ##
101
+
102
+ To run tests, simply do the following:
103
+
104
+ bundle install
105
+ rake
106
+
107
+ And it's ready!
108
+
109
+ ## Contributors ##
110
+
111
+ Thanks to the following who contributed functionality / bug fixes:
112
+
113
+ * [Matt Pruitt](http://github.com/guitsaru)
114
+
115
+ ## Note on Patches/Pull Requests ##
116
+
117
+ * Fork the project.
118
+ * Make your feature addition or bug fix.
119
+ * Add tests for it. This is important so I don't break it in a future version unintentionally.
120
+ * Commit, do not mess with rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
121
+ * Send me a pull request. Bonus points for topic branches.
122
+
123
+ ## Copyright ##
124
+
125
+ Copyright (c) 2010 Darcy Laycock. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,110 @@
1
+ require 'rubygems'
2
+ require 'bundler'
3
+ Bundler.setup
4
+ Bundler.require
5
+
6
+ require 'rake'
7
+
8
+ require File.expand_path('../lib/slugged/version', __FILE__)
9
+
10
+ begin
11
+ require 'jeweler'
12
+ Jeweler::Tasks.new do |gem|
13
+ gem.version = Slugged::Version::STRING
14
+ gem.name = "slugged"
15
+ gem.summary = %Q{Super simple slugs for ActiveRecord 3.0 and higher, with support for slug history}
16
+ gem.description = %Q{Super simple slugs for ActiveRecord 3.0 and higher, with support for slug history}
17
+ gem.email = "sutto@sutto.net"
18
+ gem.homepage = "http://github.com/Sutto/slugged"
19
+ gem.authors = ["Darcy Laycock"]
20
+ gem.add_dependency "activerecord", "~> 3.0.0"
21
+ gem.add_dependency "activesupport", "~> 3.0.0"
22
+ gem.add_dependency "uuid"
23
+ gem.add_development_dependency "shoulda", ">= 0"
24
+ gem.add_development_dependency "reversible_data"
25
+ end
26
+ Jeweler::GemcutterTasks.new
27
+ rescue LoadError
28
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
29
+ end
30
+
31
+ require 'rake/testtask'
32
+ Rake::TestTask.new(:test) do |test|
33
+ test.libs << 'lib' << 'test'
34
+ test.pattern = 'test/**/*_test.rb'
35
+ test.verbose = true
36
+ end
37
+
38
+ begin
39
+ require 'rcov/rcovtask'
40
+ Rcov::RcovTask.new do |test|
41
+ test.libs << 'test'
42
+ test.pattern = 'test/**/*_test.rb'
43
+ test.verbose = true
44
+ test.rcov_opts << '--exclude /gems/,/Library/,/usr/,lib/tasks,.bundle,config,/lib/rspec/,/lib/rspec-'
45
+ test.output_dir = "metrics/coverage"
46
+ end
47
+ rescue LoadError
48
+ task :rcov do
49
+ abort "Rcov isn't installed, please run via bundle exec after bundle installing"
50
+ end
51
+ end
52
+
53
+ task :metrics => [:rcov, :saikuro, :reek, :flay, :flog, :roodi]
54
+
55
+ task :test => :check_dependencies
56
+
57
+ task :flog do
58
+ system "flog lib"
59
+ end
60
+
61
+ task :saikuro do
62
+ system "rm -rf metrics/saikuro && mkdir -p metrics/saikuro && saikuro -c -t -i lib/ -y 0 -w 11 -e 16 -o metrics/saikuro/"
63
+ end
64
+
65
+ begin
66
+ require 'flay'
67
+ require 'flay_task'
68
+ FlayTask.new
69
+ rescue LoadError
70
+ task :flay do
71
+ abort "Flay isn't installed, please run via bundle exec after bundle installing"
72
+ end
73
+ end
74
+
75
+ begin
76
+ require 'reek/rake/task'
77
+ Reek::Rake::Task.new do |t|
78
+ t.fail_on_error = true
79
+ t.verbose = false
80
+ t.source_files = 'lib/**/*.rb'
81
+ end
82
+ rescue LoadError
83
+ task :reek do
84
+ abort "Reek isn't installed, please run via bundle exec after bundle installing"
85
+ end
86
+ end
87
+
88
+ begin
89
+ require 'roodi'
90
+ require 'roodi_task'
91
+ RoodiTask.new do |t|
92
+ t.verbose = false
93
+ end
94
+ rescue LoadError
95
+ task :roodi do
96
+ abort "Roodi isn't installed, please run via bundle exec after bundle installing"
97
+ end
98
+ end
99
+
100
+ task :default => :test
101
+
102
+ require 'rake/rdoctask'
103
+ Rake::RDocTask.new do |rdoc|
104
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
105
+
106
+ rdoc.rdoc_dir = 'rdoc'
107
+ rdoc.title = "slugged #{version}"
108
+ rdoc.rdoc_files.include('README*')
109
+ rdoc.rdoc_files.include('lib/**/*.rb')
110
+ end
@@ -0,0 +1,24 @@
1
+ module Slugged
2
+ module Generators
3
+ class SlugMigrationGenerator < Rails::Generators::NamedBase
4
+ include Rails::Generators::Migration
5
+
6
+ def self.source_root
7
+ @_ps_source_root ||= File.expand_path("templates", File.dirname(__FILE__))
8
+ end
9
+
10
+ def self.next_migration_number(dirname) #:nodoc:
11
+ if ActiveRecord::Base.timestamped_migrations
12
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
13
+ else
14
+ "%.3d" % (current_migration_number(dirname) + 1)
15
+ end
16
+ end
17
+
18
+ def create_migration_file
19
+ migration_template "migration.erb", "db/migrate/add_cached_slug_to_#{table_name}.rb"
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,12 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration
2
+
3
+ def self.up
4
+ add_column <%= table_name.to_sym.inspect %>, :cached_slug, :string
5
+ add_index <%= table_name.to_sym.inspect %>, :cached_slug
6
+ end
7
+
8
+ def self.down
9
+ remove_column <%= table_name.to_sym.inspect %>, :cached_slug
10
+ end
11
+
12
+ end
@@ -0,0 +1,24 @@
1
+ module Slugged
2
+ module Generators
3
+ class SlugsGenerator < Rails::Generators::Base
4
+ include Rails::Generators::Migration
5
+
6
+ def self.source_root
7
+ @_ps_source_root ||= File.expand_path("templates", File.dirname(__FILE__))
8
+ end
9
+
10
+ def self.next_migration_number(dirname) #:nodoc:
11
+ if ActiveRecord::Base.timestamped_migrations
12
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
13
+ else
14
+ "%.3d" % (current_migration_number(dirname) + 1)
15
+ end
16
+ end
17
+
18
+ def create_migration_file
19
+ migration_template "migration.erb", "db/migrate/create_slugged_slugs.rb"
20
+ end
21
+
22
+ end
23
+ end
24
+ end