dm-is-slug 0.10.2 → 1.0.0

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.
data/.gitignore CHANGED
@@ -1,3 +1,7 @@
1
+ Gemfile.lock
1
2
  pkg
2
3
  coverage
3
4
  tmp
5
+ *.gem
6
+ .yardoc
7
+ doc
data/Gemfile ADDED
@@ -0,0 +1,142 @@
1
+ # If you're working on more than one datamapper gem at a time, then it's
2
+ # recommended to create a local Gemfile and use this instead of the git
3
+ # sources. This will make sure that you are developing against your
4
+ # other local datamapper sources that you currently work on. Gemfile.local
5
+ # will behave identically to the standard Gemfile apart from the fact that
6
+ # it fetches the datamapper gems from local paths. This means that you can use
7
+ # the same environment variables, like ADAPTER(S) or PLUGIN(S) when running
8
+ # bundle commands. Gemfile.local is added to .gitignore, so you don't need to
9
+ # worry about accidentally checking local development paths into git.
10
+ # In order to create a local Gemfile, all you need to do is run:
11
+ #
12
+ # bundle exec rake local_gemfile
13
+ #
14
+ # This will give you a Gemfile.local file that points to your local clones of
15
+ # the various datamapper gems. It's assumed that all datamapper repo clones
16
+ # reside in the same directory. You can use the Gemfile.local like so for
17
+ # running any bundle command:
18
+ #
19
+ # BUNDLE_GEMFILE=Gemfile.local bundle foo
20
+ #
21
+ # You can also specify which adapter(s) should be part of the bundle by setting
22
+ # an environment variable. This of course also works when using the Gemfile.local
23
+ #
24
+ # bundle foo # dm-sqlite-adapter
25
+ # ADAPTER=mysql bundle foo # dm-mysql-adapter
26
+ # ADAPTERS=sqlite,mysql bundle foo # dm-sqlite-adapter and dm-mysql-adapter
27
+ #
28
+ # Of course you can also use the ADAPTER(S) variable when using the Gemfile.local
29
+ # and running specs against selected adapters.
30
+ #
31
+ # For easily working with adapters supported on your machine, it's recommended
32
+ # that you first install all adapters that you are planning to use or work on
33
+ # by doing something like
34
+ #
35
+ # ADAPTERS=sqlite,mysql,postgres bundle install
36
+ #
37
+ # This will clone the various repositories and make them available to bundler.
38
+ # Once you have them installed you can easily switch between adapters for the
39
+ # various development tasks. Running something like
40
+ #
41
+ # ADAPTER=mysql bundle exec rake spec
42
+ #
43
+ # will make sure that the dm-mysql-adapter is part of the bundle, and will be used
44
+ # when running the specs.
45
+ #
46
+ # You can also specify which plugin(s) should be part of the bundle by setting
47
+ # an environment variable. This also works when using the Gemfile.local
48
+ #
49
+ # bundle foo # dm-migrations
50
+ # PLUGINS=dm-validations bundle foo # dm-migrations and dm-validations
51
+ # PLUGINS=dm-validations,dm-types bundle foo # dm-migrations, dm-validations and dm-types
52
+ #
53
+ # Of course you can combine the PLUGIN(S) and ADAPTER(S) env vars to run specs
54
+ # for certain adapter/plugin combinations.
55
+ #
56
+ # Finally, to speed up running specs and other tasks, it's recommended to run
57
+ #
58
+ # bundle lock
59
+ #
60
+ # after running 'bundle install' for the first time. This will make 'bundle exec' run
61
+ # a lot faster compared to the unlocked version. With an unlocked bundle you would
62
+ # typically just run 'bundle install' from time to time to fetch the latest sources from
63
+ # upstream. When you locked your bundle, you need to run
64
+ #
65
+ # bundle install --relock
66
+ #
67
+ # to make sure to fetch the latest updates and then lock the bundle again. Gemfile.lock
68
+ # is added to the .gitignore file, so you don't need to worry about accidentally checking
69
+ # it into version control.
70
+
71
+ source 'http://rubygems.org'
72
+
73
+ DATAMAPPER = 'git://github.com/datamapper'
74
+ DM_VERSION = '~> 1.0.2'
75
+
76
+ group :runtime do # Runtime dependencies (as in the gemspec)
77
+
78
+ if ENV['EXTLIB']
79
+ gem 'extlib', '~> 0.9.15', :git => "#{DATAMAPPER}/extlib.git"
80
+ else
81
+ gem 'activesupport', '~> 3.0.0', :git => 'git://github.com/rails/rails.git', :branch => '3-0-stable', :require => nil
82
+ end
83
+
84
+ gem 'dm-core', DM_VERSION, :git => "#{DATAMAPPER}/dm-core.git"
85
+
86
+ gem 'unidecode', '~> 1.0.0'
87
+
88
+ end
89
+
90
+ group(:development) do # Development dependencies (as in the gemspec)
91
+
92
+ gem 'rake', '~> 0.8.7'
93
+ gem 'rspec', '~> 1.3', :git => 'git://github.com/snusnu/rspec', :branch => 'heckle_fix_plus_gemfile'
94
+ gem 'jeweler', '~> 1.4'
95
+
96
+ end
97
+
98
+ group :quality do # These gems contain rake tasks that check the quality of the source code
99
+
100
+ gem 'metric_fu', '~> 1.3'
101
+ gem 'rcov', '~> 0.9.8'
102
+ gem 'reek', '~> 1.2.8'
103
+ gem 'roodi', '~> 2.1'
104
+ gem 'yard', '~> 0.5'
105
+ gem 'yardstick', '~> 0.1'
106
+
107
+ end
108
+
109
+ group :datamapper do # We need this because we want to pin these dependencies to their git master sources
110
+
111
+ adapters = ENV['ADAPTER'] || ENV['ADAPTERS']
112
+ adapters = adapters.to_s.tr(',', ' ').split.uniq - %w[ in_memory ]
113
+
114
+ DO_VERSION = '~> 0.10.2'
115
+ DM_DO_ADAPTERS = %w[ sqlite postgres mysql oracle sqlserver ]
116
+
117
+ if (do_adapters = DM_DO_ADAPTERS & adapters).any?
118
+ options = {}
119
+ options[:git] = "#{DATAMAPPER}/do.git" if ENV['DO_GIT'] == 'true'
120
+
121
+ gem 'data_objects', DO_VERSION, options.dup
122
+
123
+ do_adapters.each do |adapter|
124
+ adapter = 'sqlite3' if adapter == 'sqlite'
125
+ gem "do_#{adapter}", DO_VERSION, options.dup
126
+ end
127
+
128
+ gem 'dm-do-adapter', DM_VERSION, :git => "#{DATAMAPPER}/dm-do-adapter.git"
129
+ end
130
+
131
+ adapters.each do |adapter|
132
+ gem "dm-#{adapter}-adapter", DM_VERSION, :git => "#{DATAMAPPER}/dm-#{adapter}-adapter.git"
133
+ end
134
+
135
+ plugins = ENV['PLUGINS'] || ENV['PLUGIN']
136
+ plugins = plugins.to_s.tr(',', ' ').split.push('dm-migrations').uniq
137
+
138
+ plugins.each do |plugin|
139
+ gem plugin, DM_VERSION, :git => "#{DATAMAPPER}/#{plugin}.git"
140
+ end
141
+
142
+ end
@@ -0,0 +1,58 @@
1
+ = dm-is-slug
2
+
3
+ DataMapper plugin for creating and slugs(permalinks).
4
+
5
+ == Installation
6
+
7
+ > gem install dm-is-slug
8
+
9
+ == Usage
10
+
11
+ === Creating a slug from property
12
+
13
+ class Post
14
+ include DataMapper::Resource
15
+
16
+ property :id, Serial
17
+ property :title, String
18
+ property :content, String
19
+
20
+ # here we define that it should have a slug that uses title as the permalink
21
+ # it will generate an extra slug property of String type, with the same size as title
22
+ is :slug, :source => :title
23
+ end
24
+
25
+ === Creating a slug from arbitrary methods
26
+
27
+ class User
28
+ include DataMapper::Resource
29
+
30
+ property :id, Serial
31
+ property :email, String
32
+ property :password, String
33
+
34
+ # we only want to strip out the domain name
35
+ # and use only the email account name as the permalink
36
+ def slug_for_email
37
+ email.split("@").first
38
+ end
39
+
40
+ # here we define that it should have a slug that uses title as the permalink
41
+ # it will generate an extra slug property of String type, with the same size as title
42
+ is :slug, :source => :slug_for_email, :size => 255
43
+ end
44
+
45
+ === Finding objects by slug
46
+
47
+ post = Post.first(:slug => "your_slug")
48
+
49
+ == Development
50
+
51
+ It's recommended to use bundler in development.
52
+
53
+ gem install bundler
54
+ ADAPTERS='in_memory yaml sqlite postgres mysql' bundle install --without quality
55
+
56
+ This will install all dependencies so that you could run specs.
57
+
58
+ bundler exec rake spec ADAPTER=in_memory
data/Rakefile CHANGED
@@ -4,7 +4,7 @@ require 'rake'
4
4
  begin
5
5
  gem 'jeweler', '~> 1.4'
6
6
  require 'jeweler'
7
-
7
+
8
8
  Jeweler::Tasks.new do |gem|
9
9
  gem.name = "dm-is-slug"
10
10
  gem.summary = "DataMapper plugin that generates unique slugs"
@@ -15,18 +15,20 @@ begin
15
15
  'nik [a] terminaldischarge [d] net',
16
16
  'maverick.stoklosa@gmail.com',
17
17
  'frawl021@gmail.com',
18
- 'cheba@pointlessone.org'
18
+ 'cheba+github@pointlessone.org'
19
19
  ]
20
20
  gem.homepage = "http://github.com/aq1018/dm-is-slug"
21
- gem.authors = ['Aaron Qian', 'James Herdman', 'Nik Radford', 'Paul', 'Mike Frawley', 'Alex Makuta']
22
- gem.add_dependency "dm-core", "~>0.10.2"
23
- gem.add_dependency "unidecode", "~>1.0.0"
21
+ gem.authors = ['Aaron Qian', 'James Herdman', 'Nik Radford', 'Paul', 'Mike Frawley', 'Alexander Mankuta']
22
+
23
+ gem.add_dependency "dm-core", "~> 1.0.2"
24
+ gem.add_dependency "unidecode", "~> 1.0.0"
25
+
24
26
  gem.add_development_dependency 'rspec', '~> 1.3'
25
27
  end
26
-
28
+
27
29
  Jeweler::GemcutterTasks.new
28
-
30
+
29
31
  FileList['tasks/**/*.rake'].each { |task| import task }
30
32
  rescue LoadError
31
33
  puts 'Jeweler (or a dependency) not available. Install it with: gem install jeweler'
32
- end
34
+ end
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.10.2
1
+ 1.0.0
@@ -5,22 +5,23 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{dm-is-slug}
8
- s.version = "0.10.2"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Aaron Qian", "James Herdman", "Nik Radford", "Paul", "Mike Frawley", "Alex Makuta"]
12
- s.date = %q{2010-02-07}
11
+ s.authors = ["Aaron Qian", "James Herdman", "Nik Radford", "Paul", "Mike Frawley", "Alexander Mankuta"]
12
+ s.date = %q{2010-10-17}
13
13
  s.description = %q{DataMapper plugin that generates unique slugs}
14
- s.email = ["aq1018@gmail.com", "james.herdman@gmail.com", "nik [a] terminaldischarge [d] net", "maverick.stoklosa@gmail.com", "frawl021@gmail.com", "cheba@pointlessone.org"]
14
+ s.email = ["aq1018@gmail.com", "james.herdman@gmail.com", "nik [a] terminaldischarge [d] net", "maverick.stoklosa@gmail.com", "frawl021@gmail.com", "cheba+github@pointlessone.org"]
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE",
17
- "README.textile",
17
+ "README.rdoc",
18
18
  "TODO"
19
19
  ]
20
20
  s.files = [
21
21
  ".gitignore",
22
+ "Gemfile",
22
23
  "LICENSE",
23
- "README.textile",
24
+ "README.rdoc",
24
25
  "Rakefile",
25
26
  "TODO",
26
27
  "VERSION",
@@ -32,6 +33,7 @@ Gem::Specification.new do |s|
32
33
  "spec/spec.opts",
33
34
  "spec/spec_helper.rb",
34
35
  "tasks/ci.rake",
36
+ "tasks/local_gemfile.rake",
35
37
  "tasks/metrics.rake",
36
38
  "tasks/spec.rake",
37
39
  "tasks/yard.rake",
@@ -40,7 +42,7 @@ Gem::Specification.new do |s|
40
42
  s.homepage = %q{http://github.com/aq1018/dm-is-slug}
41
43
  s.rdoc_options = ["--charset=UTF-8"]
42
44
  s.require_paths = ["lib"]
43
- s.rubygems_version = %q{1.3.5}
45
+ s.rubygems_version = %q{1.3.7}
44
46
  s.summary = %q{DataMapper plugin that generates unique slugs}
45
47
  s.test_files = [
46
48
  "spec/integration/slug_spec.rb",
@@ -51,17 +53,17 @@ Gem::Specification.new do |s|
51
53
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
52
54
  s.specification_version = 3
53
55
 
54
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
55
- s.add_runtime_dependency(%q<dm-core>, ["~> 0.10.2"])
56
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
+ s.add_runtime_dependency(%q<dm-core>, ["~> 1.0.2"])
56
58
  s.add_runtime_dependency(%q<unidecode>, ["~> 1.0.0"])
57
59
  s.add_development_dependency(%q<rspec>, ["~> 1.3"])
58
60
  else
59
- s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
61
+ s.add_dependency(%q<dm-core>, ["~> 1.0.2"])
60
62
  s.add_dependency(%q<unidecode>, ["~> 1.0.0"])
61
63
  s.add_dependency(%q<rspec>, ["~> 1.3"])
62
64
  end
63
65
  else
64
- s.add_dependency(%q<dm-core>, ["~> 0.10.2"])
66
+ s.add_dependency(%q<dm-core>, ["~> 1.0.2"])
65
67
  s.add_dependency(%q<unidecode>, ["~> 1.0.0"])
66
68
  s.add_dependency(%q<rspec>, ["~> 1.3"])
67
69
  end
@@ -1,7 +1 @@
1
- require 'pathname'
2
- require 'dm-core'
3
-
4
- # Require plugin-files
5
- require Pathname(__FILE__).dirname.expand_path / 'dm-is-slug' / 'is' / 'slug.rb'
6
-
7
- DataMapper::Model.append_extensions DataMapper::Is::Slug
1
+ require 'dm-is-slug/is/slug'
@@ -1,9 +1,14 @@
1
1
  require 'unidecode'
2
+ require 'dm-core'
2
3
  require 'dm-core/support/chainable'
3
4
 
4
5
  module DataMapper
5
6
  module Is
6
7
  module Slug
8
+ def self.included(base)
9
+ base.extend ClassMethods
10
+ end
11
+
7
12
  class InvalidSlugSourceError < StandardError; end
8
13
 
9
14
  # @param [String] str A string to escape for use as a slug
@@ -66,9 +71,12 @@ module DataMapper
66
71
 
67
72
 
68
73
  options[:length] ||= get_slug_length
69
- property(:slug, String, options.merge(:unique => true)) unless slug_property
74
+ if slug_property && slug_property.class >= DataMapper::Property::String
75
+ options.merge! slug_property.options
76
+ end
77
+ property :slug, String, options.merge(:unique => true)
70
78
 
71
- before :valid?, :generate_slug
79
+ before respond_to?(:valid?) ? :valid? : :save, :generate_slug
72
80
  before :save, :generate_slug
73
81
  end
74
82
 
@@ -95,11 +103,11 @@ module DataMapper
95
103
 
96
104
  def detect_slug_property_by_name(name)
97
105
  p = properties[name]
98
- !p.nil? && p.type == String ? p : nil
106
+ !p.nil? && DataMapper::Property::String >= p.class ? p : nil
99
107
  end
100
108
 
101
109
  def get_slug_length
102
- slug_property.nil? ? (slug_source_property.nil? ? DataMapper::Property::DEFAULT_LENGTH : slug_source_property.length) : slug_property.length
110
+ slug_property.nil? ? (slug_source_property.nil? ? DataMapper::Property::String::DEFAULT_LENGTH : slug_source_property.length) : slug_property.length
103
111
  end
104
112
  end # ClassMethods
105
113
 
@@ -132,13 +140,12 @@ module DataMapper
132
140
  # 1. the slug is permanent, and slug column has something valid in it
133
141
  # 2. the slug source value is nil or empty
134
142
  def stale_slug?
135
- !((permanent_slug? && slug && !slug.empty?) || (slug_source_value.nil? || slug_source_value.empty?))
143
+ !((permanent_slug? && !slug.blank?) || slug_source_value.blank?)
136
144
  end
137
145
 
138
146
  private
139
147
 
140
148
  def generate_slug
141
- #puts "\nGenerating slug for #{self.class.name}: #{self.key.inspect}\n"
142
149
  return unless self.class.respond_to?(:slug_options) && self.class.slug_options
143
150
  raise InvalidSlugSourceError, 'Invalid slug source.' unless slug_source_property || self.respond_to?(slug_source)
144
151
  return unless stale_slug?
@@ -146,40 +153,52 @@ module DataMapper
146
153
  end
147
154
 
148
155
  def unique_slug
149
- old_slug = self.slug
150
156
  max_length = self.class.send(:get_slug_length)
151
157
  base_slug = ::DataMapper::Is::Slug.escape(slug_source_value)[0, max_length]
152
- i = 1
158
+ # Assuming that 5 digits is more than enought
159
+ index_length = 5
153
160
  new_slug = base_slug
154
161
 
155
- if old_slug != new_slug
156
- not_self_conditions = {}
157
- unless new?
158
- self.model.key.each do |property|
159
- not_self_conditions.merge!(property.name.not => self.send(property.name))
160
- end
161
- #puts "Not self: #{not_self_conditions.inspect}"
162
+ variations = max_length - base_slug.length - 1
163
+
164
+ slugs = if variations > index_length + 1
165
+ [base_slug]
166
+ else
167
+ ((variations - 1)..index_length).map do |n|
168
+ base_slug[0, max_length - n - 1]
169
+ end.uniq
170
+ end
171
+
172
+ not_self_conditions = {}
173
+ unless new?
174
+ self.model.key.each do |property|
175
+ not_self_conditions.merge!(property.name.not => self.send(property.name))
162
176
  end
177
+ end
178
+
179
+ max_index = slugs.map do |s|
180
+ self.class.all(not_self_conditions.merge :slug.like => "#{s}-%")
181
+ end.flatten.map do |r|
182
+ index = r.slug.gsub /^(#{slugs.join '|'})-/, ''
183
+ index =~ /\d+/ ? index.to_i : nil
184
+ end.compact.max
163
185
 
164
- lambda do
165
- #puts "Lambda new slug: #{new_slug}"
166
- dupe = self.class.first(not_self_conditions.merge(:slug => new_slug))
167
- if dupe
168
- #puts "Got dupe: #{dupe.inspect}"
169
- i = i + 1
170
- slug_length = max_length - i.to_s.length - 1
171
- new_slug = "#{base_slug[0, slug_length]}-#{i}"
172
- #puts "New slug: #{new_slug}"
173
- redo
174
- end
175
- end.call
176
- #puts "Found new slug: #{new_slug}"
177
- new_slug
186
+ new_index = if max_index.nil?
187
+ self.class.first(not_self_conditions.merge :slug => base_slug).present? ? 2 : 1
178
188
  else
179
- old_slug
189
+ max_index + 1
190
+ end
191
+
192
+ if new_index > 1
193
+ slug_length = max_length - new_index.to_s.length - 1
194
+ new_slug = "#{base_slug[0, slug_length]}-#{new_index}"
180
195
  end
196
+
197
+ new_slug
181
198
  end
182
199
  end # InstanceMethods
200
+
201
+ Model.send(:include, self)
183
202
  end # Slug
184
203
  end # Is
185
204
  end # DataMapper
@@ -1,10 +1,12 @@
1
- require 'pathname'
2
- require Pathname(__FILE__).dirname.expand_path.parent + 'spec_helper'
1
+ # encoding: utf-8
3
2
 
4
- if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
5
- describe 'DataMapper::Is::Slug' do
3
+ require 'spec_helper'
6
4
 
7
- class User
5
+
6
+ describe DataMapper::Is::Slug do
7
+
8
+ before :all do
9
+ class ::User
8
10
  include DataMapper::Resource
9
11
 
10
12
  property :id, Serial
@@ -19,7 +21,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
19
21
  is :slug, :source => :slug_for_email, :length => 80, :permanent_slug => false
20
22
  end
21
23
 
22
- class Post
24
+ class ::Post
23
25
  include DataMapper::Resource
24
26
 
25
27
  property :id, Serial
@@ -31,7 +33,7 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
31
33
  is :slug, :source => :title
32
34
  end
33
35
 
34
- class Todo
36
+ class ::Todo
35
37
  include DataMapper::Resource
36
38
  property :id, Serial
37
39
  property :title, String
@@ -39,43 +41,53 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
39
41
  belongs_to :user
40
42
  end
41
43
 
42
- class SlugKey
44
+ class ::SlugKey
43
45
  include DataMapper::Resource
44
46
  property :title, String
45
47
 
46
48
  is :slug, :source => :title, :key => true
47
49
  end
48
50
 
51
+ class ::Post2
52
+ include DataMapper::Resource
53
+
54
+ property :id, Serial
55
+ property :title, String, :length => 30
56
+ property :content, Text
57
+
58
+ is :slug, :source => :title, :permanent_slug => false
59
+ end
60
+ end
61
+
62
+ supported_by :sqlite, :mysql, :postgres do
63
+
49
64
  before :all do
50
- User.auto_migrate!(:default)
51
- Post.auto_migrate!(:default)
52
- Todo.auto_migrate!(:default)
53
- SlugKey.auto_migrate!(:default)
54
-
55
- @u1 = User.create(:email => "john@ekohe.com")
56
- @p1 = Post.create(:user => @u1, :title => "My first shinny blog post")
57
- @p2 = Post.create(:user => @u1, :title => "My second shinny blog post")
58
- @p3 = Post.create(:user => @u1, :title => "My third shinny blog post")
59
-
60
- @u2 = User.create(:email => "john@someotherplace.com")
61
- @p4 = Post.create(:user => @u2, :title => "My first Shinny blog post")
62
- @p5 = Post.create(:user => @u2, :title => "i heart merb and dm")
63
- @p6 = Post.create(:user => @u2, :title => "A fancy café")
64
- @p7 = Post.create(:user => @u2, :title => "你好")
65
-
66
- (1..10).each do |i|
67
- instance_variable_set "@p1_#{i}".to_sym, Post.create(:user => @u2, :title => "another productive day!!")
68
- end
69
- (1..10).each do |i|
70
- instance_variable_set "@p2_#{i}".to_sym, Post.create(:user => @u2, :title => "DM tricks")
71
- end
65
+ DataMapper.repository do
66
+ @u1 = User.create(:email => "john@ekohe.com")
67
+ @p1 = Post.create(:user => @u1, :title => "My first shinny blog post")
68
+ @p2 = Post.create(:user => @u1, :title => "My second shinny blog post")
69
+ @p3 = Post.create(:user => @u1, :title => "My third shinny blog post")
70
+
71
+ @u2 = User.create(:email => "john@someotherplace.com")
72
+ @p4 = Post.create(:user => @u2, :title => "My first Shinny blog post")
73
+ @p5 = Post.create(:user => @u2, :title => "i heart merb and dm")
74
+ @p6 = Post.create(:user => @u2, :title => "A fancy café")
75
+ @p7 = Post.create(:user => @u2, :title => "你好")
76
+
77
+ (1..10).each do |i|
78
+ instance_variable_set "@p1_#{i}".to_sym, Post.create(:user => @u2, :title => "another productive day!!")
79
+ end
80
+ (1..10).each do |i|
81
+ instance_variable_set "@p2_#{i}".to_sym, Post.create(:user => @u2, :title => "DM tricks")
82
+ end
72
83
 
73
- @sk = SlugKey.create(:title => 'slug key')
84
+ @sk = SlugKey.create(:title => 'slug key')
74
85
 
75
- @post1 = Post.create :user => @u1, :title => 'a' * Post.slug_property.length
76
- @post2 = Post.create :user => @u1, :title => 'a' * Post.slug_property.length
86
+ @post1 = Post.create :user => @u1, :title => 'a' * Post.slug_property.length
87
+ @post2 = Post.create :user => @u1, :title => 'a' * Post.slug_property.length
88
+ end
77
89
  end
78
-
90
+
79
91
  it "should raise error if :source option is not specified" do
80
92
  lambda {
81
93
  class BadUsage
@@ -89,20 +101,24 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
89
101
  end
90
102
 
91
103
  it "should display obsolete warning if :size option is used" do
92
- class Thingy
104
+ module M
105
+ class Thingy
106
+ end
93
107
  end
94
- Thingy.stub!(:warn)
95
- Thingy.should_receive(:warn).with("Slug with :size option is deprecated, use :length instead")
108
+ M::Thingy.stub!(:warn)
109
+ M::Thingy.should_receive(:warn).with("Slug with :size option is deprecated, use :length instead")
96
110
 
97
111
  lambda {
98
- class Thingy
112
+ class M::Thingy
99
113
  include DataMapper::Resource
114
+ property :id, Serial
100
115
  property :title, String
101
116
 
102
117
  is :slug, :source => :title, :size => 20
103
118
  end
104
119
  }.should_not raise_error
105
120
 
121
+ M.const_set 'Thingy', nil
106
122
  end
107
123
 
108
124
  it "should generate slugs" do
@@ -171,15 +187,15 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
171
187
  it "should have the right size for properties" do
172
188
  user_slug_property = User.properties[:slug]
173
189
  user_slug_property.should_not be_nil
174
- user_slug_property.type.should == String
190
+ user_slug_property.should be_an_instance_of(DataMapper::Property::String)
175
191
  user_slug_property.length.should == 80
176
192
 
177
193
  post_title_property = Post.properties[:title]
178
- post_title_property.type.should == String
194
+ post_title_property.should be_an_instance_of(DataMapper::Property::String)
179
195
  post_title_property.length.should == 30
180
196
 
181
197
  post_slug_property = Post.properties[:slug]
182
- post_slug_property.type.should == String
198
+ post_slug_property.should be_an_instance_of(DataMapper::Property::String)
183
199
  post_slug_property.should_not be_nil
184
200
  post_slug_property.length.should == 30
185
201
  end
@@ -238,25 +254,15 @@ if HAS_SQLITE3 || HAS_MYSQL || HAS_POSTGRES
238
254
  end
239
255
 
240
256
  describe 'editing' do
241
- class Post2
242
- include DataMapper::Resource
243
- property :id, Serial
244
- property :title, String, :length => 30
245
- property :content, Text
246
-
247
- is :slug, :source => :title, :permanent_slug => false
248
- end
249
-
250
- Post2.auto_migrate!
251
-
252
257
  before :each do
253
258
  Post2.all.destroy!
254
259
  @post = Post2.create :title => 'The Post', :content => 'The content.'
255
260
  end
256
261
 
257
262
  it 'should not change slug if source is not changed' do
258
- @post.update :content => 'The other content.'
259
- Post2.first.slug.should == 'the-post'
263
+ @post.update(:content => 'The other content.').should be_true
264
+ @post.reload
265
+ @post.slug.should == 'the-post'
260
266
  end
261
267
 
262
268
  it 'should change slug if source is changed' do
@@ -1,38 +1,13 @@
1
1
  require 'rubygems'
2
-
3
- # use local dm-core if running from a typical dev checkout.
4
- lib = File.join('..', '..', 'dm-core', 'lib')
5
- $LOAD_PATH.unshift(lib) if File.directory?(lib)
6
- require 'dm-core'
7
-
8
- # use local dm-adjust if running from a typical dev checkout.
9
- lib = File.join('..', 'dm-adjust', 'lib')
10
- $LOAD_PATH.unshift(lib) if File.directory?(lib)
11
- require 'dm-adjust'
12
-
13
- # Support running specs with 'rake spec' and 'spec'
14
- $LOAD_PATH.unshift('lib') unless $LOAD_PATH.include?('lib')
15
-
16
- require 'dm-validations'
2
+
3
+ require 'dm-core/spec/setup'
4
+ require 'dm-core/spec/lib/adapter_helpers'
5
+
17
6
  require 'dm-is-slug'
18
-
19
- def load_driver(name, default_uri)
20
- return false if ENV['ADAPTER'] != name.to_s
21
-
22
- begin
23
- DataMapper.setup(name, ENV["#{name.to_s.upcase}_SPEC_URI"] || default_uri)
24
- DataMapper::Repository.adapters[:default] = DataMapper::Repository.adapters[name]
25
- true
26
- rescue LoadError => e
27
- warn "Could not load do_#{name}: #{e}"
28
- false
29
- end
30
- end
31
-
32
- ENV['ADAPTER'] ||= 'sqlite3'
33
-
34
- HAS_SQLITE3 = load_driver(:sqlite3, 'sqlite3::memory:')
35
- HAS_MYSQL = load_driver(:mysql, 'mysql://localhost/dm_core_test')
36
- HAS_POSTGRES = load_driver(:postgres, 'postgres://postgres@localhost/dm_core_test')
7
+ require 'dm-migrations'
37
8
 
9
+ DataMapper::Spec.setup!
38
10
 
11
+ Spec::Runner.configure do |config|
12
+ config.extend(DataMapper::Spec::Adapters::Helpers)
13
+ end
@@ -0,0 +1,16 @@
1
+ desc "Support bundling from local source code (allows BUNDLE_GEMFILE=Gemfile.local bundle foo)"
2
+ task :local_gemfile do |t|
3
+
4
+ root = Pathname(__FILE__).dirname.parent
5
+ datamapper = root.parent
6
+
7
+ root.join('Gemfile.local').open('w') do |f|
8
+ root.join('Gemfile').open.each do |line|
9
+ line.sub!(/DATAMAPPER = 'git:\/\/github.com\/datamapper'/, "DATAMAPPER = '#{datamapper}'")
10
+ line.sub!(/:git => \"#\{DATAMAPPER\}\/(.+?)(?:\.git)?\"/, ':path => "#{DATAMAPPER}/\1"')
11
+ line.sub!(/do_options\[:git\] = \"#\{DATAMAPPER\}\/(.+?)(?:\.git)?\"/, 'do_options[:path] = "#{DATAMAPPER}/\1"')
12
+ f.puts line
13
+ end
14
+ end
15
+
16
+ end
metadata CHANGED
@@ -1,7 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dm-is-slug
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.10.2
4
+ hash: 23
5
+ prerelease: false
6
+ segments:
7
+ - 1
8
+ - 0
9
+ - 0
10
+ version: 1.0.0
5
11
  platform: ruby
6
12
  authors:
7
13
  - Aaron Qian
@@ -9,44 +15,61 @@ authors:
9
15
  - Nik Radford
10
16
  - Paul
11
17
  - Mike Frawley
12
- - Alex Makuta
18
+ - Alexander Mankuta
13
19
  autorequire:
14
20
  bindir: bin
15
21
  cert_chain: []
16
22
 
17
- date: 2010-02-07 00:00:00 +08:00
23
+ date: 2010-10-17 00:00:00 -07:00
18
24
  default_executable:
19
25
  dependencies:
20
26
  - !ruby/object:Gem::Dependency
21
27
  name: dm-core
22
- type: :runtime
23
- version_requirement:
24
- version_requirements: !ruby/object:Gem::Requirement
28
+ prerelease: false
29
+ requirement: &id001 !ruby/object:Gem::Requirement
30
+ none: false
25
31
  requirements:
26
32
  - - ~>
27
33
  - !ruby/object:Gem::Version
28
- version: 0.10.2
29
- version:
34
+ hash: 19
35
+ segments:
36
+ - 1
37
+ - 0
38
+ - 2
39
+ version: 1.0.2
40
+ type: :runtime
41
+ version_requirements: *id001
30
42
  - !ruby/object:Gem::Dependency
31
43
  name: unidecode
32
- type: :runtime
33
- version_requirement:
34
- version_requirements: !ruby/object:Gem::Requirement
44
+ prerelease: false
45
+ requirement: &id002 !ruby/object:Gem::Requirement
46
+ none: false
35
47
  requirements:
36
48
  - - ~>
37
49
  - !ruby/object:Gem::Version
50
+ hash: 23
51
+ segments:
52
+ - 1
53
+ - 0
54
+ - 0
38
55
  version: 1.0.0
39
- version:
56
+ type: :runtime
57
+ version_requirements: *id002
40
58
  - !ruby/object:Gem::Dependency
41
59
  name: rspec
42
- type: :development
43
- version_requirement:
44
- version_requirements: !ruby/object:Gem::Requirement
60
+ prerelease: false
61
+ requirement: &id003 !ruby/object:Gem::Requirement
62
+ none: false
45
63
  requirements:
46
64
  - - ~>
47
65
  - !ruby/object:Gem::Version
66
+ hash: 9
67
+ segments:
68
+ - 1
69
+ - 3
48
70
  version: "1.3"
49
- version:
71
+ type: :development
72
+ version_requirements: *id003
50
73
  description: DataMapper plugin that generates unique slugs
51
74
  email:
52
75
  - aq1018@gmail.com
@@ -54,19 +77,20 @@ email:
54
77
  - nik [a] terminaldischarge [d] net
55
78
  - maverick.stoklosa@gmail.com
56
79
  - frawl021@gmail.com
57
- - cheba@pointlessone.org
80
+ - cheba+github@pointlessone.org
58
81
  executables: []
59
82
 
60
83
  extensions: []
61
84
 
62
85
  extra_rdoc_files:
63
86
  - LICENSE
64
- - README.textile
87
+ - README.rdoc
65
88
  - TODO
66
89
  files:
67
90
  - .gitignore
91
+ - Gemfile
68
92
  - LICENSE
69
- - README.textile
93
+ - README.rdoc
70
94
  - Rakefile
71
95
  - TODO
72
96
  - VERSION
@@ -78,6 +102,7 @@ files:
78
102
  - spec/spec.opts
79
103
  - spec/spec_helper.rb
80
104
  - tasks/ci.rake
105
+ - tasks/local_gemfile.rake
81
106
  - tasks/metrics.rake
82
107
  - tasks/spec.rake
83
108
  - tasks/yard.rake
@@ -92,21 +117,27 @@ rdoc_options:
92
117
  require_paths:
93
118
  - lib
94
119
  required_ruby_version: !ruby/object:Gem::Requirement
120
+ none: false
95
121
  requirements:
96
122
  - - ">="
97
123
  - !ruby/object:Gem::Version
124
+ hash: 3
125
+ segments:
126
+ - 0
98
127
  version: "0"
99
- version:
100
128
  required_rubygems_version: !ruby/object:Gem::Requirement
129
+ none: false
101
130
  requirements:
102
131
  - - ">="
103
132
  - !ruby/object:Gem::Version
133
+ hash: 3
134
+ segments:
135
+ - 0
104
136
  version: "0"
105
- version:
106
137
  requirements: []
107
138
 
108
139
  rubyforge_project:
109
- rubygems_version: 1.3.5
140
+ rubygems_version: 1.3.7
110
141
  signing_key:
111
142
  specification_version: 3
112
143
  summary: DataMapper plugin that generates unique slugs
@@ -1,56 +0,0 @@
1
- = dm-is-slug
2
-
3
- DataMapper plugin for creating and slugs(permalinks).
4
-
5
- == Installation
6
-
7
- NOTE: You no longer need to download dm-more source code in order to install
8
- this.
9
-
10
- All you need to do is:
11
-
12
- $ sudo rake install
13
-
14
- Remember to require it in your app's init.rb
15
-
16
- dependency 'dm-is-slug'
17
-
18
- == Getting started
19
-
20
- Lets say we have a post-class, and we want to generate permalinks or slugs for all posts.
21
-
22
- class Post
23
- include DataMapper::Resource
24
-
25
- property :id, Serial
26
- property :title, String
27
- property :content, String
28
-
29
- # here we define that it should have a slug that uses title as the permalink
30
- # it will generate an extra slug property of String type, with the same size as title
31
- is :slug, :source => :title
32
- end
33
-
34
- Let's Say we need to define a permalink based on a method instead of a property.
35
-
36
- class User
37
- include DataMapper::Resource
38
-
39
- property :id, Serial
40
- property :email, String
41
- property :password, String
42
-
43
- # we only want to strip out the domain name
44
- # and use only the email account name as the permalink
45
- def slug_for_email
46
- email.split("@").first
47
- end
48
-
49
- # here we define that it should have a slug that uses title as the permalink
50
- # it will generate an extra slug property of String type, with the same size as title
51
- is :slug, :source => :slug_for_email, :size => 255
52
- end
53
-
54
- You can now find objects by slug like this:
55
-
56
- post = Post.first(:slug => "your_slug")