rs3vans-dm-is-sluggable 0.3.1

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.
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Ryan Evans
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.
@@ -0,0 +1,17 @@
1
+ = dm-is-sluggable
2
+
3
+ Adds slug support to DataMapper models. Slugs are clean, human-readable identifiers that can be used in-place of a more traditional number-based id.
4
+
5
+ == Note on Patches/Pull Requests
6
+
7
+ * Fork the project.
8
+ * Make your feature addition or bug fix.
9
+ * Add tests for it. This is important so I don't break it in a
10
+ future version unintentionally.
11
+ * Commit, do not mess with rakefile, version, or history.
12
+ (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)
13
+ * Send me a pull request. Bonus points for topic branches.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2010 Ryan Evans. See LICENSE for details.
@@ -0,0 +1,54 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "rs3vans-dm-is-sluggable"
8
+ gem.summary = %Q{Adds slug support to DataMapper models.}
9
+ gem.description = %Q{Adds slug support to DataMapper models. Slugs are clean, human-readable identifiers that can be used in-place of a more traditional number-based id.}
10
+ gem.email = "rs3vans@gmail.com"
11
+ gem.homepage = "http://github.com/rs3vans/dm-is-sluggable"
12
+ gem.authors = ["Ryan Evans"]
13
+ gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
14
+ gem.add_dependency "dm-core", ">= 0.10.2"
15
+ gem.add_dependency "unidecode", "~> 1.0.0"
16
+ end
17
+ Jeweler::GemcutterTasks.new
18
+ rescue LoadError
19
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
20
+ end
21
+
22
+ require 'rake/testtask'
23
+ Rake::TestTask.new(:test) do |test|
24
+ test.libs << 'lib' << 'test'
25
+ test.pattern = 'test/**/test_*.rb'
26
+ test.verbose = true
27
+ end
28
+
29
+ begin
30
+ require 'rcov/rcovtask'
31
+ Rcov::RcovTask.new do |test|
32
+ test.libs << 'test'
33
+ test.pattern = 'test/**/test_*.rb'
34
+ test.verbose = true
35
+ end
36
+ rescue LoadError
37
+ task :rcov do
38
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
39
+ end
40
+ end
41
+
42
+ task :test => :check_dependencies
43
+
44
+ task :default => :test
45
+
46
+ require 'rake/rdoctask'
47
+ Rake::RDocTask.new do |rdoc|
48
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
49
+
50
+ rdoc.rdoc_dir = 'rdoc'
51
+ rdoc.title = "dm-is-sluggable #{version}"
52
+ rdoc.rdoc_files.include('README*')
53
+ rdoc.rdoc_files.include('lib/**/*.rb')
54
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.3.1
@@ -0,0 +1,6 @@
1
+ require 'pathname'
2
+ require 'dm-core'
3
+
4
+ require Pathname(__FILE__).dirname.expand_path / 'dm-is-sluggable' / 'is'/ 'sluggable'
5
+
6
+ DataMapper::Model.append_extensions DataMapper::Is::Sluggable
@@ -0,0 +1,38 @@
1
+ module DataMapper
2
+ module Is
3
+ module ClassMethods
4
+
5
+ def slug_property
6
+ sp = properties[slug_property_name]
7
+ sp && (sp.type == String ? sp : nil)
8
+ end
9
+
10
+ def slug_property_name
11
+ slug_options[:property_name]
12
+ end
13
+
14
+ def slug_source
15
+ slug_options[:source]
16
+ end
17
+
18
+ def slug_permanent?
19
+ slug_options[:permanent?]
20
+ end
21
+
22
+ def slug_max_length
23
+ slug_options[:max_length]
24
+ end
25
+
26
+ def get slug #_with_slug slug
27
+ first(slug_property_name => slug)
28
+ end
29
+
30
+ private
31
+
32
+ def slug_options
33
+ class_variable_get(:@@dm_is_sluggable_options)
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,70 @@
1
+ require 'unidecode'
2
+
3
+ module DataMapper
4
+ module Is
5
+ module InstanceMethods
6
+
7
+ def slug_property
8
+ self.class.slug_property
9
+ end
10
+
11
+ def slug_property_name
12
+ self.class.slug_property_name
13
+ end
14
+
15
+ def slug_source
16
+ self.class.slug_source
17
+ end
18
+
19
+ def slug_permanent?
20
+ self.class.slug_permanent?
21
+ end
22
+
23
+ def slug_max_length
24
+ self.class.slug_max_length
25
+ end
26
+
27
+ def slug_value
28
+ send slug_property_name
29
+ end
30
+ alias_method :to_param, :slug_value
31
+
32
+ private
33
+
34
+ def truncate_slug(slug, extra = 0)
35
+ length = (slug_max_length ? [slug.length, slug_max_length].min : slug.length) - extra
36
+ slug[0..length - 1]
37
+ end
38
+
39
+ def sluggify
40
+ old_slug = slug_value
41
+ DataMapper.logger.debug ['(dm-is-sluggable) old_slug = ', old_slug].join
42
+ DataMapper.logger.debug ['(dm-is-sluggable) slugs are permanent?: ', slug_permanent?].join
43
+ return if slug_permanent? && old_slug
44
+ new_raw_slug = [slug_source].flatten.map do |ss|
45
+ send ss.to_sym
46
+ end.join(' ')
47
+ attribute_set(slug_property_name, nil) and return unless new_raw_slug
48
+ base_new_slug = new_raw_slug.to_ascii.downcase.gsub(/\W+/, ' ').strip.gsub(/ +/, '-')
49
+ if base_new_slug != old_slug
50
+ exists_opts = {}
51
+ self.class.key.each do |k|
52
+ exists_opts[k.name.not] = send(k.name)
53
+ end unless new?
54
+ extra = 0
55
+ new_slug = truncate_slug(base_new_slug)
56
+ lambda do
57
+ clash = self.class.first(exists_opts.merge(slug_property_name => new_slug))
58
+ if clash
59
+ extra = extra.next
60
+ new_slug = [truncate_slug(base_new_slug, (extra.to_s.length + 1)), extra].join('-')
61
+ redo
62
+ end
63
+ end.call
64
+ attribute_set(slug_property_name, new_slug)
65
+ end
66
+ end
67
+
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,36 @@
1
+ require Pathname(__FILE__).dirname.expand_path / 'class_methods'
2
+ require Pathname(__FILE__).dirname.expand_path / 'instance_methods'
3
+
4
+ module DataMapper
5
+ module Is
6
+ module Sluggable
7
+ class InvalidSlugError < StandardError; end
8
+
9
+ def is_sluggable(source = :to_slug, opts = {})
10
+ class_variable_set(:@@dm_is_sluggable_options, {})
11
+
12
+ extend ClassMethods
13
+ include InstanceMethods
14
+
15
+ slug_options[:source] = source
16
+
17
+ property_name = if opts[:property].is_a?(Hash)
18
+ opts[:property].delete(:name).to_sym
19
+ else
20
+ (opts[:property] || :slug).to_sym
21
+ end
22
+ property_opts = opts[:property].is_a?(Hash) ? opts[:property] : {}
23
+ slug_options[:property_name] = property_name
24
+ property property_name, String, property_opts.merge(:unique_index => true) unless slug_property
25
+
26
+ slug_options[:permanent?] = opts[:permanent?] || false
27
+ slug_options[:max_length] = opts[:max_length]
28
+
29
+ DataMapper.logger.debug(slug_options.inspect)
30
+
31
+ before :save, :sluggify
32
+ end
33
+
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,73 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{rs3vans-dm-is-sluggable}
8
+ s.version = "0.3.1"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Ryan Evans"]
12
+ s.date = %q{2010-05-31}
13
+ s.description = %q{Adds slug support to DataMapper models. Slugs are clean, human-readable identifiers that can be used in-place of a more traditional number-based id.}
14
+ s.email = %q{rs3vans@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".document",
21
+ ".gitignore",
22
+ "LICENSE",
23
+ "README.rdoc",
24
+ "Rakefile",
25
+ "VERSION",
26
+ "lib/dm-is-sluggable.rb",
27
+ "lib/dm-is-sluggable/is/class_methods.rb",
28
+ "lib/dm-is-sluggable/is/instance_methods.rb",
29
+ "lib/dm-is-sluggable/is/sluggable.rb",
30
+ "rs3vans-dm-is-sluggable.gemspec",
31
+ "test/helper.rb",
32
+ "test/model_1.rb",
33
+ "test/model_2.rb",
34
+ "test/model_3.rb",
35
+ "test/model_4.rb",
36
+ "test/model_5.rb",
37
+ "test/test_dm-is-sluggable.rb"
38
+ ]
39
+ s.homepage = %q{http://github.com/rs3vans/dm-is-sluggable}
40
+ s.rdoc_options = ["--charset=UTF-8"]
41
+ s.require_paths = ["lib"]
42
+ s.rubygems_version = %q{1.3.6}
43
+ s.summary = %q{Adds slug support to DataMapper models.}
44
+ s.test_files = [
45
+ "test/model_1.rb",
46
+ "test/model_2.rb",
47
+ "test/model_3.rb",
48
+ "test/helper.rb",
49
+ "test/test_dm-is-sluggable.rb",
50
+ "test/model_4.rb",
51
+ "test/model_5.rb"
52
+ ]
53
+
54
+ if s.respond_to? :specification_version then
55
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
56
+ s.specification_version = 3
57
+
58
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
59
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
60
+ s.add_runtime_dependency(%q<dm-core>, [">= 0.10.2"])
61
+ s.add_runtime_dependency(%q<unidecode>, ["~> 1.0.0"])
62
+ else
63
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
64
+ s.add_dependency(%q<dm-core>, [">= 0.10.2"])
65
+ s.add_dependency(%q<unidecode>, ["~> 1.0.0"])
66
+ end
67
+ else
68
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
69
+ s.add_dependency(%q<dm-core>, [">= 0.10.2"])
70
+ s.add_dependency(%q<unidecode>, ["~> 1.0.0"])
71
+ end
72
+ end
73
+
@@ -0,0 +1,13 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ require 'dm-core'
6
+ require 'do_sqlite3'
7
+
8
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
9
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
10
+ require 'dm-is-sluggable'
11
+
12
+ class Test::Unit::TestCase
13
+ end
@@ -0,0 +1,8 @@
1
+ class Model1
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :name, String
6
+
7
+ is :sluggable, :name
8
+ end
@@ -0,0 +1,9 @@
1
+ class Model2
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :name, String
6
+ property :tag, String
7
+
8
+ is :sluggable, [:name, :tag]
9
+ end
@@ -0,0 +1,8 @@
1
+ class Model3
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :name, String
6
+
7
+ is :sluggable, :name, :max_length => 9
8
+ end
@@ -0,0 +1,8 @@
1
+ class Model4
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :name, String
6
+
7
+ is :sluggable, :name, :permanent? => true
8
+ end
@@ -0,0 +1,8 @@
1
+ class Model5
2
+ include DataMapper::Resource
3
+
4
+ property :id, Serial
5
+ property :name, String
6
+
7
+ is :sluggable, :name
8
+ end
@@ -0,0 +1,63 @@
1
+ require 'helper'
2
+
3
+ DataMapper::Logger.new($stdout, :debug)
4
+ DataMapper.setup(:default, 'sqlite3::memory:')
5
+ Dir[File.join(File.dirname(__FILE__), 'model_*.rb')].each {|m| require m}
6
+ DataMapper.auto_migrate!
7
+
8
+ class TestDmIsSluggable < Test::Unit::TestCase
9
+
10
+ context 'With Model 1' do
11
+ setup do
12
+ @m = Model1.create :name => 'Test THIS slugger!'
13
+ end
14
+
15
+ should 'return true if #slug is correct' do
16
+ assert 'test-this-slugger' == @m.slug
17
+ end
18
+ end
19
+
20
+ context 'With Model 2' do
21
+ setup do
22
+ @m = Model2.create :name => 'Test THIS slugger!', :tag => 'SLUG A'
23
+ end
24
+
25
+ should 'return true if #slug is correct' do
26
+ assert 'test-this-slugger-slug-a' == @m.slug
27
+ end
28
+ end
29
+
30
+ context 'With Model 3' do
31
+ setup do
32
+ @m = Model3.create :name => 'Test THIS slugger!'
33
+ end
34
+
35
+ should 'return true if #slug is correct' do
36
+ assert 'test-this' == @m.slug
37
+ end
38
+ end
39
+
40
+ context 'With Model 4' do
41
+ setup do
42
+ @m = Model4.create :name => 'Test THIS slugger!'
43
+ @m.name = 'Not the same!'
44
+ @m.save
45
+ end
46
+
47
+ should 'return true if #slug and #name are correct' do
48
+ assert 'test-this-slugger' == @m.slug
49
+ assert 'Not the same!' == @m.name
50
+ end
51
+ end
52
+
53
+ context 'With Model 5 (modified get)' do
54
+ setup do
55
+ Model5.create :name => 'Test THIS slugger!'
56
+ end
57
+
58
+ should 'return true if "test-this-slugger" is found using #get' do
59
+ assert !!Model5.get('test-this-slugger')
60
+ end
61
+ end
62
+
63
+ end
metadata ADDED
@@ -0,0 +1,125 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rs3vans-dm-is-sluggable
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 3
8
+ - 1
9
+ version: 0.3.1
10
+ platform: ruby
11
+ authors:
12
+ - Ryan Evans
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-05-31 00:00:00 -05:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: thoughtbot-shoulda
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :development
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: dm-core
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ">="
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 0
41
+ - 10
42
+ - 2
43
+ version: 0.10.2
44
+ type: :runtime
45
+ version_requirements: *id002
46
+ - !ruby/object:Gem::Dependency
47
+ name: unidecode
48
+ prerelease: false
49
+ requirement: &id003 !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ~>
52
+ - !ruby/object:Gem::Version
53
+ segments:
54
+ - 1
55
+ - 0
56
+ - 0
57
+ version: 1.0.0
58
+ type: :runtime
59
+ version_requirements: *id003
60
+ description: Adds slug support to DataMapper models. Slugs are clean, human-readable identifiers that can be used in-place of a more traditional number-based id.
61
+ email: rs3vans@gmail.com
62
+ executables: []
63
+
64
+ extensions: []
65
+
66
+ extra_rdoc_files:
67
+ - LICENSE
68
+ - README.rdoc
69
+ files:
70
+ - .document
71
+ - .gitignore
72
+ - LICENSE
73
+ - README.rdoc
74
+ - Rakefile
75
+ - VERSION
76
+ - lib/dm-is-sluggable.rb
77
+ - lib/dm-is-sluggable/is/class_methods.rb
78
+ - lib/dm-is-sluggable/is/instance_methods.rb
79
+ - lib/dm-is-sluggable/is/sluggable.rb
80
+ - rs3vans-dm-is-sluggable.gemspec
81
+ - test/helper.rb
82
+ - test/model_1.rb
83
+ - test/model_2.rb
84
+ - test/model_3.rb
85
+ - test/model_4.rb
86
+ - test/model_5.rb
87
+ - test/test_dm-is-sluggable.rb
88
+ has_rdoc: true
89
+ homepage: http://github.com/rs3vans/dm-is-sluggable
90
+ licenses: []
91
+
92
+ post_install_message:
93
+ rdoc_options:
94
+ - --charset=UTF-8
95
+ require_paths:
96
+ - lib
97
+ required_ruby_version: !ruby/object:Gem::Requirement
98
+ requirements:
99
+ - - ">="
100
+ - !ruby/object:Gem::Version
101
+ segments:
102
+ - 0
103
+ version: "0"
104
+ required_rubygems_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ segments:
109
+ - 0
110
+ version: "0"
111
+ requirements: []
112
+
113
+ rubyforge_project:
114
+ rubygems_version: 1.3.6
115
+ signing_key:
116
+ specification_version: 3
117
+ summary: Adds slug support to DataMapper models.
118
+ test_files:
119
+ - test/model_1.rb
120
+ - test/model_2.rb
121
+ - test/model_3.rb
122
+ - test/helper.rb
123
+ - test/test_dm-is-sluggable.rb
124
+ - test/model_4.rb
125
+ - test/model_5.rb