dm-is-slug 0.10.2 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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")