slugger 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in slugger.gemspec
4
+ gemspec
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Seth Faxon
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.rdoc ADDED
@@ -0,0 +1,43 @@
1
+ = Slugger
2
+
3
+ Slugger is yet another slug generator. It makes pretty urls for Active Record models. It jumps through some hoops to make sure every slug is unique.
4
+
5
+ == Installation
6
+
7
+ It's a gem. Either run `gem install slugger` at the command line, or add `gem 'slugger'` to your Gemfile.
8
+
9
+ == Usage
10
+
11
+ has_slug :source_column, [options]
12
+
13
+ The default source column is title.
14
+
15
+ :source_column can also be an array, for example, if you wanted to create slugs for an Author model on first and last name:
16
+
17
+ has_slug [:first_name, :last_name]
18
+
19
+ == Options
20
+
21
+ Say you have an Episode model that belongs to TVSeries. Every episode will have a pilot, but you don't want the unique validation to build silly looking urls:
22
+
23
+ class Episode << ActiveRecord::Base
24
+ belongs_to :series
25
+
26
+ has_slug :title, :scope => :series_id
27
+ end
28
+
29
+
30
+ == Example
31
+
32
+ create_table "collection" do |t|
33
+ t.string "title"
34
+ t.string "slug"
35
+ end
36
+
37
+ class Project < ActiveRecord::Base
38
+ has_slug
39
+ end
40
+
41
+ Collection.create(:title => 'Quick foxes jumping')
42
+ Collection.first.slug => 'quick-foxes-jumping'
43
+
data/Rakefile ADDED
@@ -0,0 +1,5 @@
1
+ require "bundler/gem_tasks"
2
+
3
+ Dir["#{File.dirname(__FILE__)}/tasks/*.rake"].sort.each { |ext| load ext }
4
+
5
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.0.1
@@ -0,0 +1,3 @@
1
+ module Slugger
2
+ VERSION = File.read(File.dirname(__FILE__) + "/../../VERSION").chomp
3
+ end
data/lib/slugger.rb ADDED
@@ -0,0 +1,81 @@
1
+ require 'slugger/version'
2
+ require 'active_record'
3
+ require 'iconv'
4
+
5
+ module Slugger
6
+ def self.included(base)
7
+ base.extend(ClassMethods)
8
+ end
9
+ module ClassMethods
10
+ def acts_as_sluggable(title_column=nil,sluger_options={})
11
+ class_inheritable_accessor :sluger_options
12
+ sluger_options[:title_column] ||= title_column || 'title'
13
+ # sluger_options[:title_column] ||= 'title'
14
+ sluger_options[:slug_column] ||= 'slug'
15
+ sluger_options[:as_param] ||= true
16
+ sluger_options[:substitution_char] ||= '-'
17
+ self.sluger_options = sluger_options
18
+
19
+ # if columns_hash[sluger_options[:title_column].to_s].nil?
20
+ #
21
+ # raise ArgumentError, "#{self.name} is missing source column"
22
+ # end
23
+ raise ArgumentError, "#{self.name} is missing required slug column" if columns_hash[sluger_options[:slug_column]].nil?
24
+
25
+ before_validation :create_slug, :on => :create
26
+
27
+ validates sluger_options[:slug_column].to_sym, :presence => true
28
+ if sluger_options[:scope]
29
+ validates sluger_options[:slug_column].to_sym, :uniqueness => {:scope => sluger_options[:scope]}
30
+ else
31
+ validates sluger_options[:slug_column].to_sym, :uniqueness => true
32
+ end
33
+
34
+ send :define_method, :column_to_slug, lambda { self.send(sluger_options[:title_column]) }
35
+
36
+ class << self
37
+ def find(*args)
38
+ if self.sluger_options[:as_param] && args.first.is_a?(String)
39
+ find_by_slug(args)
40
+ else
41
+ super(*args)
42
+ end
43
+ end
44
+ end
45
+
46
+ include InstanceMethods
47
+ end
48
+ end
49
+ module InstanceMethods
50
+
51
+ def to_param
52
+ sluger_options[:as_param] ? self.slug : self.id
53
+ end
54
+
55
+ protected
56
+
57
+ def permalize
58
+ return if !self.send("#{self.sluggable_conf[:slug_column]}").blank?
59
+ s = Iconv.iconv('ascii//ignore//translit', 'utf-8', self.send("#{self.sluggable_conf[:title_column]}")).to_s
60
+ s.gsub!(/\'/, '') # remove '
61
+ s.gsub!(/\W+/, ' ') # all non-word chars to spaces
62
+ s.strip! # ohh la la
63
+ s.downcase! #
64
+ s.gsub!(/\ +/, '-') # spaces to dashes, preferred separator char everywhere
65
+ self.send("#{self.sluggable_conf[:slug_column]}=", s)
66
+ end
67
+ def strip_title
68
+ self.send("#{self.sluggable_conf[:title_column]}").strip!
69
+ end
70
+
71
+ def create_slug
72
+ self.slug ||= clean("#{column_to_slug}")
73
+ end
74
+
75
+ def clean(string)
76
+ string.downcase.gsub(/[^\w\s\d\_\-]/,'').gsub(/\s\s+/,' ').gsub(/[^\w\d]/, sluger_options[:substitution_char])
77
+ end
78
+ end
79
+ end
80
+
81
+ ActiveRecord::Base.send(:include, Slugger)
data/slugger.gemspec ADDED
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "slugger/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "slugger"
7
+ s.version = Slugger::VERSION
8
+ s.authors = ["Seth Faxon"]
9
+ s.email = ["seth.faxon@gmail.com"]
10
+ s.homepage = "https://github.com/sfaxon/slugger"
11
+ s.summary = %q{Slugger is yet another slug generator.}
12
+ s.description = %q{Slugger is yet another slug generator.}
13
+
14
+ s.rubyforge_project = "slugger"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ s.extra_rdoc_files = [
22
+ "MIT-LICENSE",
23
+ "README.rdoc"
24
+ ]
25
+
26
+ # specify any dependencies here; for example:
27
+ s.add_dependency "activerecord", ">= 3.0.0"
28
+ s.add_development_dependency "rspec", ">= 2.0.0"
29
+ s.add_development_dependency "sqlite3", "~> 1.3.0"
30
+ # s.add_runtime_dependency "rest-client"
31
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Post do
4
+ it "should set slug on create" do
5
+ p = Post.create(:title => "hello world")
6
+ p.slug.should == "hello-world"
7
+ end
8
+ end
data/spec/schema.rb ADDED
@@ -0,0 +1,44 @@
1
+ require 'active_record'
2
+ require 'sqlite3'
3
+
4
+ ActiveRecord::Base.establish_connection(
5
+ :adapter => defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' ? 'jdbcsqlite3' : 'sqlite3',
6
+ :database => File.join(File.dirname(__FILE__), 'test.db')
7
+ )
8
+
9
+ class CreateSchema < ActiveRecord::Migration
10
+ def self.up
11
+ create_table :posts, :force => true do |t|
12
+ t.string :title
13
+ t.string :slug
14
+ t.timestamps
15
+ end
16
+
17
+ create_table :users, :force => true do |t|
18
+ t.string :first_name
19
+ t.string :last_name
20
+ t.string :slug
21
+ t.timestamps
22
+ end
23
+ end
24
+ end
25
+
26
+ CreateSchema.suppress_messages do
27
+ CreateSchema.migrate(:up)
28
+ end
29
+
30
+ class Post < ActiveRecord::Base
31
+ acts_as_sluggable
32
+ end
33
+
34
+ class User < ActiveRecord::Base
35
+ acts_as_sluggable [:first_name, :last_name]
36
+
37
+ def name
38
+ [first_name, last_name].compact.join(' ')
39
+ end
40
+
41
+ def name=(names)
42
+ self[:first_name], self[:last_name] = names.split(' ', 2)
43
+ end
44
+ end
@@ -0,0 +1,18 @@
1
+ # Requires supporting ruby files with custom matchers and macros, etc,
2
+ # in spec/support/ and its subdirectories.
3
+ require 'slugger'
4
+ require 'schema'
5
+
6
+ Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each {|f| require f}
7
+
8
+
9
+ RSpec.configure do |config|
10
+ # == Mock Framework
11
+ #
12
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
13
+ #
14
+ # config.mock_with :mocha
15
+ # config.mock_with :flexmock
16
+ # config.mock_with :rr
17
+ config.mock_with :rspec
18
+ end
data/tasks/spec.rake ADDED
@@ -0,0 +1,34 @@
1
+ ENV['BUNDLE_GEMFILE'] = File.dirname(__FILE__) + '/../Gemfile'
2
+
3
+ require 'rake'
4
+ require 'rake/testtask'
5
+ require 'rspec'
6
+ require 'rspec/core/rake_task'
7
+
8
+ desc "Run the test suite"
9
+ task :spec => ['spec:setup', 'spec:slugger_lib', 'spec:cleanup']
10
+
11
+ namespace :spec do
12
+ desc "Setup the test environment"
13
+ task :setup do
14
+ end
15
+
16
+ desc "Cleanup the test environment"
17
+ task :cleanup do
18
+ File.delete(File.expand_path(File.dirname(__FILE__) + '/../spec/test.db'))
19
+ end
20
+
21
+ desc "Test slugger"
22
+ RSpec::Core::RakeTask.new(:slugger_lib) do |task|
23
+ slugger_root = File.expand_path(File.dirname(__FILE__) + '/..')
24
+ task.pattern = slugger_root + '/spec/lib/**/*_spec.rb'
25
+ end
26
+
27
+ desc "Run the coverage report"
28
+ RSpec::Core::RakeTask.new(:rcov) do |task|
29
+ slugger_root = File.expand_path(File.dirname(__FILE__) + '/..')
30
+ task.pattern = slugger_root + '/spec/lib/**/*_spec.rb'
31
+ task.rcov=true
32
+ task.rcov_opts = %w{--rails --exclude osx\/objc,gems\/,spec\/,features\/}
33
+ end
34
+ end
metadata ADDED
@@ -0,0 +1,128 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: slugger
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Seth Faxon
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-08-23 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: activerecord
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 7
29
+ segments:
30
+ - 3
31
+ - 0
32
+ - 0
33
+ version: 3.0.0
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: rspec
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 15
45
+ segments:
46
+ - 2
47
+ - 0
48
+ - 0
49
+ version: 2.0.0
50
+ type: :development
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: sqlite3
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
56
+ none: false
57
+ requirements:
58
+ - - ~>
59
+ - !ruby/object:Gem::Version
60
+ hash: 27
61
+ segments:
62
+ - 1
63
+ - 3
64
+ - 0
65
+ version: 1.3.0
66
+ type: :development
67
+ version_requirements: *id003
68
+ description: Slugger is yet another slug generator.
69
+ email:
70
+ - seth.faxon@gmail.com
71
+ executables: []
72
+
73
+ extensions: []
74
+
75
+ extra_rdoc_files:
76
+ - MIT-LICENSE
77
+ - README.rdoc
78
+ files:
79
+ - .gitignore
80
+ - Gemfile
81
+ - MIT-LICENSE
82
+ - README.rdoc
83
+ - Rakefile
84
+ - VERSION
85
+ - lib/slugger.rb
86
+ - lib/slugger/version.rb
87
+ - slugger.gemspec
88
+ - spec/lib/slugger_spec.rb
89
+ - spec/schema.rb
90
+ - spec/spec_helper.rb
91
+ - tasks/spec.rake
92
+ homepage: https://github.com/sfaxon/slugger
93
+ licenses: []
94
+
95
+ post_install_message:
96
+ rdoc_options: []
97
+
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ none: false
102
+ requirements:
103
+ - - ">="
104
+ - !ruby/object:Gem::Version
105
+ hash: 3
106
+ segments:
107
+ - 0
108
+ version: "0"
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ">="
113
+ - !ruby/object:Gem::Version
114
+ hash: 3
115
+ segments:
116
+ - 0
117
+ version: "0"
118
+ requirements: []
119
+
120
+ rubyforge_project: slugger
121
+ rubygems_version: 1.8.8
122
+ signing_key:
123
+ specification_version: 3
124
+ summary: Slugger is yet another slug generator.
125
+ test_files:
126
+ - spec/lib/slugger_spec.rb
127
+ - spec/schema.rb
128
+ - spec/spec_helper.rb