stringex 1.5.1 → 2.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.
Files changed (63) hide show
  1. checksums.yaml +15 -0
  2. data/Gemfile +16 -0
  3. data/Gemfile.lock +74 -0
  4. data/README.rdoc +22 -1
  5. data/Rakefile +46 -223
  6. data/VERSION +1 -0
  7. data/init.rb +1 -0
  8. data/lib/stringex.rb +11 -3
  9. data/lib/stringex/acts_as_url.rb +49 -97
  10. data/lib/stringex/acts_as_url/adapter.rb +26 -0
  11. data/lib/stringex/acts_as_url/adapter/active_record.rb +23 -0
  12. data/lib/stringex/acts_as_url/adapter/base.rb +188 -0
  13. data/lib/stringex/acts_as_url/adapter/data_mapper.rb +67 -0
  14. data/lib/stringex/acts_as_url/adapter/mongoid.rb +36 -0
  15. data/lib/stringex/configuration.rb +4 -0
  16. data/lib/stringex/configuration/acts_as_url.rb +44 -0
  17. data/lib/stringex/configuration/base.rb +58 -0
  18. data/lib/stringex/configuration/configurator.rb +25 -0
  19. data/lib/stringex/configuration/string_extensions.rb +19 -0
  20. data/lib/stringex/localization.rb +98 -0
  21. data/lib/stringex/localization/backend/i18n.rb +53 -0
  22. data/lib/stringex/localization/backend/internal.rb +51 -0
  23. data/lib/stringex/localization/conversion_expressions.rb +148 -0
  24. data/lib/stringex/localization/converter.rb +121 -0
  25. data/lib/stringex/localization/default_conversions.rb +88 -0
  26. data/lib/stringex/rails/railtie.rb +10 -0
  27. data/lib/stringex/string_extensions.rb +153 -208
  28. data/lib/stringex/unidecoder.rb +6 -101
  29. data/lib/stringex/unidecoder_data/x00.yml +1 -1
  30. data/lib/stringex/unidecoder_data/x02.yml +5 -5
  31. data/lib/stringex/unidecoder_data/x05.yml +1 -1
  32. data/lib/stringex/unidecoder_data/x06.yml +1 -1
  33. data/lib/stringex/unidecoder_data/x07.yml +3 -3
  34. data/lib/stringex/unidecoder_data/x09.yml +1 -1
  35. data/lib/stringex/unidecoder_data/x0e.yml +2 -2
  36. data/lib/stringex/unidecoder_data/x1f.yml +2 -2
  37. data/lib/stringex/unidecoder_data/x20.yml +1 -1
  38. data/lib/stringex/unidecoder_data/xfb.yml +1 -1
  39. data/lib/stringex/unidecoder_data/xff.yml +1 -1
  40. data/lib/stringex/version.rb +8 -0
  41. data/locales/da.yml +73 -0
  42. data/locales/en.yml +66 -0
  43. data/stringex.gemspec +77 -18
  44. data/test/acts_as_url/adapter/active_record.rb +72 -0
  45. data/test/acts_as_url/adapter/data_mapper.rb +82 -0
  46. data/test/acts_as_url/adapter/mongoid.rb +73 -0
  47. data/test/acts_as_url_configuration_test.rb +51 -0
  48. data/test/acts_as_url_integration_test.rb +271 -0
  49. data/test/localization/da_test.rb +117 -0
  50. data/test/localization/default_test.rb +113 -0
  51. data/test/localization/en_test.rb +117 -0
  52. data/test/localization_test.rb +123 -0
  53. data/test/redcloth_to_html_test.rb +37 -0
  54. data/test/string_extensions_test.rb +59 -91
  55. data/test/test_helper.rb +2 -0
  56. data/test/unicode_point_suite/basic_greek_test.rb +113 -0
  57. data/test/unicode_point_suite/basic_latin_test.rb +142 -0
  58. data/test/unicode_point_suite/codepoint_test_helper.rb +32 -0
  59. data/test/unidecoder/bad_localization.yml +1 -0
  60. data/test/unidecoder/localization.yml +4 -0
  61. data/test/unidecoder_test.rb +3 -5
  62. metadata +145 -37
  63. data/test/acts_as_url_test.rb +0 -272
data/stringex.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "stringex"
8
- s.version = "1.5.1"
8
+ s.version = "2.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Russell Norris"]
12
- s.date = "2012-11-30"
12
+ s.date = "2013-06-03"
13
13
  s.description = "Some [hopefully] useful extensions to Ruby's String class. Stringex is made up of three libraries: ActsAsUrl [permalink solution with better character translation], Unidecoder [Unicode to ASCII transliteration], and StringExtensions [miscellaneous helper methods for the String class]."
14
14
  s.email = "rsl@luckysneaks.com"
15
15
  s.extra_rdoc_files = [
@@ -17,12 +17,32 @@ Gem::Specification.new do |s|
17
17
  "README.rdoc"
18
18
  ]
19
19
  s.files = [
20
+ "Gemfile",
21
+ "Gemfile.lock",
20
22
  "MIT-LICENSE",
21
23
  "README.rdoc",
22
24
  "Rakefile",
25
+ "VERSION",
23
26
  "init.rb",
24
27
  "lib/stringex.rb",
25
28
  "lib/stringex/acts_as_url.rb",
29
+ "lib/stringex/acts_as_url/adapter.rb",
30
+ "lib/stringex/acts_as_url/adapter/active_record.rb",
31
+ "lib/stringex/acts_as_url/adapter/base.rb",
32
+ "lib/stringex/acts_as_url/adapter/data_mapper.rb",
33
+ "lib/stringex/acts_as_url/adapter/mongoid.rb",
34
+ "lib/stringex/configuration.rb",
35
+ "lib/stringex/configuration/acts_as_url.rb",
36
+ "lib/stringex/configuration/base.rb",
37
+ "lib/stringex/configuration/configurator.rb",
38
+ "lib/stringex/configuration/string_extensions.rb",
39
+ "lib/stringex/localization.rb",
40
+ "lib/stringex/localization/backend/i18n.rb",
41
+ "lib/stringex/localization/backend/internal.rb",
42
+ "lib/stringex/localization/conversion_expressions.rb",
43
+ "lib/stringex/localization/converter.rb",
44
+ "lib/stringex/localization/default_conversions.rb",
45
+ "lib/stringex/rails/railtie.rb",
26
46
  "lib/stringex/string_extensions.rb",
27
47
  "lib/stringex/unidecoder.rb",
28
48
  "lib/stringex/unidecoder_data/x00.yml",
@@ -205,37 +225,76 @@ Gem::Specification.new do |s|
205
225
  "lib/stringex/unidecoder_data/xfd.yml",
206
226
  "lib/stringex/unidecoder_data/xfe.yml",
207
227
  "lib/stringex/unidecoder_data/xff.yml",
208
- "stringex.gemspec"
228
+ "lib/stringex/version.rb",
229
+ "locales/da.yml",
230
+ "locales/en.yml",
231
+ "stringex.gemspec",
232
+ "test/acts_as_url/adapter/active_record.rb",
233
+ "test/acts_as_url/adapter/data_mapper.rb",
234
+ "test/acts_as_url/adapter/mongoid.rb",
235
+ "test/acts_as_url_configuration_test.rb",
236
+ "test/acts_as_url_integration_test.rb",
237
+ "test/localization/da_test.rb",
238
+ "test/localization/default_test.rb",
239
+ "test/localization/en_test.rb",
240
+ "test/localization_test.rb",
241
+ "test/redcloth_to_html_test.rb",
242
+ "test/string_extensions_test.rb",
243
+ "test/test_helper.rb",
244
+ "test/unicode_point_suite/basic_greek_test.rb",
245
+ "test/unicode_point_suite/basic_latin_test.rb",
246
+ "test/unicode_point_suite/codepoint_test_helper.rb",
247
+ "test/unidecoder/bad_localization.yml",
248
+ "test/unidecoder/localization.yml",
249
+ "test/unidecoder_test.rb"
209
250
  ]
210
251
  s.homepage = "http://github.com/rsl/stringex"
252
+ s.licenses = ["MIT"]
211
253
  s.rdoc_options = ["--main", "README.rdoc", "--charset", "utf-8", "--line-numbers"]
212
254
  s.require_paths = ["lib"]
213
- s.rubygems_version = "1.8.24"
255
+ s.rubygems_version = "2.0.3"
214
256
  s.summary = "Some [hopefully] useful extensions to Ruby's String class"
215
- s.test_files = ["test/acts_as_url_test.rb", "test/string_extensions_test.rb", "test/unidecoder_test.rb"]
216
257
 
217
258
  if s.respond_to? :specification_version then
218
- s.specification_version = 3
259
+ s.specification_version = 4
219
260
 
220
261
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
221
- s.add_development_dependency(%q<activerecord>, [">= 0"])
262
+ s.add_development_dependency(%q<activerecord>, ["= 3.2.13"])
263
+ s.add_development_dependency(%q<dm-core>, ["= 1.2.0"])
264
+ s.add_development_dependency(%q<dm-migrations>, ["= 1.2.0"])
265
+ s.add_development_dependency(%q<dm-sqlite-adapter>, ["= 1.2.0"])
266
+ s.add_development_dependency(%q<dm-validations>, ["= 1.2.0"])
222
267
  s.add_development_dependency(%q<jeweler>, ["= 1.8.4"])
223
- s.add_development_dependency(%q<RedCloth>, [">= 0"])
224
- s.add_development_dependency(%q<sqlite3>, [">= 0"])
225
- s.add_development_dependency(%q<travis-lint>, ["= 1.4.0"])
268
+ s.add_development_dependency(%q<mongoid>, ["= 3.1.4"])
269
+ s.add_development_dependency(%q<RedCloth>, ["= 4.2.9"])
270
+ s.add_development_dependency(%q<sqlite3>, ["= 1.3.7"])
271
+ s.add_development_dependency(%q<travis-lint>, ["= 1.7.0"])
272
+ s.add_development_dependency(%q<i18n>, ["= 0.6.1"])
226
273
  else
227
- s.add_dependency(%q<activerecord>, [">= 0"])
274
+ s.add_dependency(%q<activerecord>, ["= 3.2.13"])
275
+ s.add_dependency(%q<dm-core>, ["= 1.2.0"])
276
+ s.add_dependency(%q<dm-migrations>, ["= 1.2.0"])
277
+ s.add_dependency(%q<dm-sqlite-adapter>, ["= 1.2.0"])
278
+ s.add_dependency(%q<dm-validations>, ["= 1.2.0"])
228
279
  s.add_dependency(%q<jeweler>, ["= 1.8.4"])
229
- s.add_dependency(%q<RedCloth>, [">= 0"])
230
- s.add_dependency(%q<sqlite3>, [">= 0"])
231
- s.add_dependency(%q<travis-lint>, ["= 1.4.0"])
280
+ s.add_dependency(%q<mongoid>, ["= 3.1.4"])
281
+ s.add_dependency(%q<RedCloth>, ["= 4.2.9"])
282
+ s.add_dependency(%q<sqlite3>, ["= 1.3.7"])
283
+ s.add_dependency(%q<travis-lint>, ["= 1.7.0"])
284
+ s.add_dependency(%q<i18n>, ["= 0.6.1"])
232
285
  end
233
286
  else
234
- s.add_dependency(%q<activerecord>, [">= 0"])
287
+ s.add_dependency(%q<activerecord>, ["= 3.2.13"])
288
+ s.add_dependency(%q<dm-core>, ["= 1.2.0"])
289
+ s.add_dependency(%q<dm-migrations>, ["= 1.2.0"])
290
+ s.add_dependency(%q<dm-sqlite-adapter>, ["= 1.2.0"])
291
+ s.add_dependency(%q<dm-validations>, ["= 1.2.0"])
235
292
  s.add_dependency(%q<jeweler>, ["= 1.8.4"])
236
- s.add_dependency(%q<RedCloth>, [">= 0"])
237
- s.add_dependency(%q<sqlite3>, [">= 0"])
238
- s.add_dependency(%q<travis-lint>, ["= 1.4.0"])
293
+ s.add_dependency(%q<mongoid>, ["= 3.1.4"])
294
+ s.add_dependency(%q<RedCloth>, ["= 4.2.9"])
295
+ s.add_dependency(%q<sqlite3>, ["= 1.3.7"])
296
+ s.add_dependency(%q<travis-lint>, ["= 1.7.0"])
297
+ s.add_dependency(%q<i18n>, ["= 0.6.1"])
239
298
  end
240
299
  end
241
300
 
@@ -0,0 +1,72 @@
1
+ require 'rubygems'
2
+ gem 'activerecord'
3
+ require 'active_record'
4
+ require "stringex"
5
+ # Reload adapters to make sure ActsAsUrl sees the ORM
6
+ Stringex::ActsAsUrl::Adapter.load_available
7
+
8
+ puts "-------------------------------------------------"
9
+ puts "Running ActsAsUrl tests with ActiveRecord adapter"
10
+ puts "-------------------------------------------------"
11
+
12
+ ActiveRecord::Base.establish_connection :adapter => "sqlite3", :database => ":memory:"
13
+
14
+ ActiveRecord::Migration.verbose = false
15
+ ActiveRecord::Schema.define do
16
+ create_table :documents, :force => true do |t|
17
+ t.string :title, :other, :url
18
+ end
19
+
20
+ create_table :sti_base_documents, :force => true do |t|
21
+ t.string :title, :other, :url, :type
22
+ end
23
+ end
24
+ ActiveRecord::Migration.verbose = true
25
+
26
+ class Document < ActiveRecord::Base
27
+ acts_as_url :title
28
+ end
29
+
30
+ class STIBaseDocument < ActiveRecord::Base
31
+ # This gets redefined in the only test that uses it but I want to be uniform
32
+ # in setting configuration details in the tests themselves
33
+ acts_as_url :title
34
+ end
35
+
36
+ class STIChildDocument < STIBaseDocument
37
+ end
38
+
39
+ class AnotherSTIChildDocument < STIBaseDocument
40
+ end
41
+
42
+ module AdapterSpecificTestBehaviors
43
+ def setup
44
+ # No setup tasks at present
45
+ end
46
+
47
+ def teardown
48
+ [Document, STIBaseDocument].each do |klass|
49
+ klass.delete_all
50
+ # Reset behavior to default
51
+ klass.class_eval do
52
+ acts_as_url :title
53
+ end
54
+ end
55
+ end
56
+
57
+ def add_validation_on_document_title
58
+ Document.class_eval do
59
+ validates_presence_of :title
60
+ end
61
+ end
62
+
63
+ def remove_validation_on_document_title
64
+ Document.class_eval do
65
+ _validators.delete :title
66
+ end
67
+ end
68
+
69
+ def adapter_specific_update(instance, hash)
70
+ instance.send :update_attributes!, hash
71
+ end
72
+ end
@@ -0,0 +1,82 @@
1
+ require 'rubygems'
2
+ gem 'dm-core'
3
+ gem 'dm-migrations'
4
+ gem 'dm-validations'
5
+ require 'dm-core'
6
+ require 'dm-migrations'
7
+ require 'dm-validations'
8
+ require 'stringex'
9
+ # Reload adapters to make sure ActsAsUrl sees the ORM
10
+ Stringex::ActsAsUrl::Adapter.load_available
11
+
12
+ puts "-------------------------------------------------"
13
+ puts "Running ActsAsUrl tests with DataMapper adapter"
14
+ puts "-------------------------------------------------"
15
+
16
+ DataMapper.setup :default, 'sqlite::memory:'
17
+
18
+ # What the tests do in constant redefining the same classes doesn't quite work with DataMapper.
19
+ # This proc allows us to reset the class definitions on each test. This might be more expensive
20
+ # but it definitely allows the class definitions to be correct. If someone more familiar with
21
+ # DataMapper than I am wants to refactor this, I'd be more than happy to take a look.
22
+ DefineTestClasses = proc do
23
+ class Document
24
+ include DataMapper::Resource
25
+ property :id, Serial
26
+ property :title, String
27
+ property :other, String
28
+ property :url, String, :lazy => false
29
+
30
+ acts_as_url :title
31
+ end
32
+
33
+ class STIBaseDocument
34
+ include DataMapper::Resource
35
+ property :id, Serial
36
+ property :title, String
37
+ property :other, String
38
+ property :url, String, :lazy => false
39
+ property :type, String
40
+
41
+ # This gets redefined in the only test that uses it but I want to be uniform
42
+ # in setting configuration details in the tests themselves
43
+ acts_as_url :title
44
+ end
45
+
46
+ class STIChildDocument < STIBaseDocument
47
+ end
48
+
49
+ class AnotherSTIChildDocument < STIBaseDocument
50
+ end
51
+
52
+ DataMapper.finalize
53
+ Document.auto_migrate!
54
+ STIBaseDocument.auto_migrate!
55
+ end
56
+
57
+ module AdapterSpecificTestBehaviors
58
+ def setup
59
+ DefineTestClasses.call
60
+ end
61
+
62
+ def teardown
63
+ [Document, STIBaseDocument, STIChildDocument, AnotherSTIChildDocument].each do |klass|
64
+ klass.destroy
65
+ Object.send :remove_const, klass.name.intern
66
+ end
67
+ end
68
+
69
+ def add_validation_on_document_title
70
+ Document.class_eval do
71
+ validates_presence_of :title
72
+ end
73
+ end
74
+
75
+ def remove_validation_on_document_title
76
+ # Do nothing. The class is going to be reloaded on the next test.
77
+ end
78
+
79
+ def adapter_specific_update(instance, hash)
80
+ response = instance.send :update, hash
81
+ end
82
+ end
@@ -0,0 +1,73 @@
1
+ require 'rubygems'
2
+ gem 'mongoid'
3
+ require 'mongoid'
4
+ require 'stringex'
5
+ # Reload adapters to make sure ActsAsUrl sees the ORM
6
+ Stringex::ActsAsUrl::Adapter.load_available
7
+
8
+ puts "-------------------------------------------------"
9
+ puts "Running ActsAsUrl tests with Mongoid adapter"
10
+ puts "-------------------------------------------------"
11
+
12
+ Mongoid.configure do |config|
13
+ config.connect_to('acts_as_url')
14
+ end
15
+
16
+ class Document
17
+ include Mongoid::Document
18
+ field :title, :type => String
19
+ field :other, :type => String
20
+ field :url, :type => String
21
+
22
+ acts_as_url :title
23
+ end
24
+
25
+ class STIBaseDocument
26
+ include Mongoid::Document
27
+ field :title, :type => String
28
+ field :other, :type => String
29
+ field :url, :type => String
30
+ field :type, :type => String
31
+
32
+ # This gets redefined in the only test that uses it but I want to be uniform
33
+ # in setting configuration details in the tests themselves
34
+ acts_as_url :title
35
+ end
36
+
37
+ class STIChildDocument < STIBaseDocument
38
+ end
39
+
40
+ class AnotherSTIChildDocument < STIBaseDocument
41
+ end
42
+
43
+ module AdapterSpecificTestBehaviors
44
+ def setup
45
+ # No setup tasks at present
46
+ end
47
+
48
+ def teardown
49
+ [Document, STIBaseDocument].each do |klass|
50
+ klass.delete_all
51
+ # Reset behavior to default
52
+ klass.class_eval do
53
+ acts_as_url :title
54
+ end
55
+ end
56
+ end
57
+
58
+ def add_validation_on_document_title
59
+ Document.class_eval do
60
+ validates_presence_of :title
61
+ end
62
+ end
63
+
64
+ def remove_validation_on_document_title
65
+ Document.class_eval do
66
+ _validators.delete :title
67
+ end
68
+ end
69
+
70
+ def adapter_specific_update(instance, hash)
71
+ instance.send :update_attributes!, hash
72
+ end
73
+ end
@@ -0,0 +1,51 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+ require 'stringex'
5
+
6
+ class ActsAsUrlConfigurationTest < Test::Unit::TestCase
7
+ def teardown
8
+ Stringex::ActsAsUrl.unconfigure!
9
+ end
10
+
11
+ def test_can_set_base_settings
12
+ default_configuration = Stringex::Configuration::ActsAsUrl.new(:url_attribute => "original")
13
+ assert_equal "original", default_configuration.settings.url_attribute
14
+
15
+ Stringex::ActsAsUrl.configure do |c|
16
+ c.url_attribute = "special"
17
+ end
18
+ new_configuration = Stringex::Configuration::ActsAsUrl.new
19
+ assert_equal "special", new_configuration.settings.url_attribute
20
+ end
21
+
22
+ def test_local_options_overrides_system_wide_configuration
23
+ Stringex::ActsAsUrl.configure do |c|
24
+ c.url_attribute = "special"
25
+ end
26
+ system_configuration = Stringex::Configuration::ActsAsUrl.new
27
+ assert_equal "special", system_configuration.settings.url_attribute
28
+
29
+ local_configuration = Stringex::Configuration::ActsAsUrl.new(:url_attribute => "local")
30
+ assert_equal "local", local_configuration.settings.url_attribute
31
+ end
32
+
33
+ def test_inherits_settings_from_string_extensions
34
+ string_extensions_settings = Stringex::Configuration::StringExtensions.new
35
+ acts_as_url_settings = Stringex::Configuration::ActsAsUrl.new
36
+
37
+ acts_as_url_settings.string_extensions_settings.keys.each do |key|
38
+ assert_equal acts_as_url_settings.settings.send(key), string_extensions_settings.settings.send(key)
39
+ end
40
+ end
41
+
42
+ def test_accepts_base_settings_for_string_extensions
43
+ string_extensions_settings = Stringex::Configuration::StringExtensions.new.default_settings
44
+
45
+ Stringex::ActsAsUrl.configure do |c|
46
+ string_extensions_settings.keys.each do |key|
47
+ assert_respond_to c, "#{key}="
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,271 @@
1
+ # encoding: UTF-8
2
+
3
+ require 'test_helper'
4
+
5
+ adapter = ENV['ADAPTER'] || 'active_record'
6
+ require File.join(File.expand_path(File.dirname(__FILE__)), "acts_as_url/adapter/#{adapter}.rb")
7
+
8
+ class ActsAsUrlIntegrationTest < Test::Unit::TestCase
9
+ include AdapterSpecificTestBehaviors
10
+
11
+ def test_should_create_url
12
+ @doc = Document.create(:title => "Let's Make a Test Title, <em>Okay</em>?")
13
+ assert_equal "lets-make-a-test-title-okay", @doc.url
14
+ end
15
+
16
+ def test_should_create_unique_url
17
+ @doc = Document.create(:title => "Unique")
18
+ @other_doc = Document.create(:title => "Unique")
19
+ assert_equal "unique", @doc.url
20
+ assert_equal "unique-1", @other_doc.url
21
+ end
22
+
23
+ def test_should_create_unique_url_when_partial_url_already_exists
24
+ @doc = Document.create(:title => "House Farms")
25
+ @other_doc = Document.create(:title => "House Farm")
26
+
27
+ assert_equal "house-farms", @doc.url
28
+ assert_equal "house-farm", @other_doc.url
29
+ end
30
+
31
+ def test_should_not_sync_url_by_default
32
+ @doc = Document.create(:title => "Stable as Stone")
33
+ @original_url = @doc.url
34
+ adapter_specific_update @doc, :title => "New Unstable Madness"
35
+ assert_equal @original_url, @doc.url
36
+ end
37
+
38
+ def test_should_allow_syncing_url
39
+ Document.class_eval do
40
+ acts_as_url :title, :sync_url => true
41
+ end
42
+
43
+ @doc = Document.create(:title => "Original")
44
+ @original_url = @doc.url
45
+ adapter_specific_update @doc, :title => "New and Improved"
46
+ assert_not_equal @original_url, @doc.url
47
+ end
48
+
49
+ def test_should_not_increment_count_on_repeated_saves
50
+ Document.class_eval do
51
+ acts_as_url :title, :sync_url => true
52
+ end
53
+
54
+ @doc = Document.create(:title => "Continuous or Constant")
55
+ assert_equal "continuous-or-constant", @doc.url
56
+ 5.times do |n|
57
+ @doc.save!
58
+ assert_equal "continuous-or-constant", @doc.url
59
+ end
60
+ end
61
+
62
+ def test_should_allow_allowing_duplicate_url
63
+ Document.class_eval do
64
+ acts_as_url :title, :allow_duplicates => true
65
+ end
66
+
67
+ @doc = Document.create(:title => "I am not a clone")
68
+ @other_doc = Document.create(:title => "I am not a clone")
69
+ assert_equal @doc.url, @other_doc.url
70
+ end
71
+
72
+ def test_should_allow_scoping_url_uniqueness
73
+ Document.class_eval do
74
+ acts_as_url :title, :scope => :other
75
+ end
76
+
77
+ @doc = Document.create(:title => "Mocumentary", :other => "I don't care if I'm unique for some reason")
78
+ @other_doc = Document.create(:title => "Mocumentary", :other => "Me either")
79
+ assert_equal @doc.url, @other_doc.url
80
+ end
81
+
82
+ def test_should_still_create_unique_urls_if_scoped_attribute_is_the_same
83
+ Document.class_eval do
84
+ acts_as_url :title, :scope => :other
85
+ end
86
+
87
+ @doc = Document.create(:title => "Mocumentary", :other => "Suddenly, I care if I'm unique")
88
+ @other_doc = Document.create(:title => "Mocumentary", :other => "Suddenly, I care if I'm unique")
89
+ assert_not_equal @doc.url, @other_doc.url
90
+ end
91
+
92
+ def test_should_allow_setting_url_attribute
93
+ Document.class_eval do
94
+ # Manually undefining the url method on Document which, in a real class not reused for tests,
95
+ # would never have been defined to begin with.
96
+ remove_method :url
97
+ acts_as_url :title, :url_attribute => :other
98
+ end
99
+
100
+ @doc = Document.create(:title => "Anything at This Point")
101
+ assert_equal "anything-at-this-point", @doc.other
102
+ assert_nil @doc.url
103
+ ensure
104
+ Document.class_eval do
105
+ # Manually undefining the other method on Document for the same reasons as before
106
+ remove_method :other
107
+ end
108
+ end
109
+
110
+ def test_should_allow_updating_url_only_when_blank
111
+ Document.class_eval do
112
+ acts_as_url :title, :only_when_blank => true
113
+ end
114
+
115
+ @string = 'the-url-of-concrete'
116
+ @doc = Document.create(:title => "Stable as Stone", :url => @string)
117
+ assert_equal @string, @doc.url
118
+ @other_doc = Document.create(:title => "Stable as Stone")
119
+ assert_equal 'stable-as-stone', @other_doc.url
120
+ end
121
+
122
+ def test_should_mass_initialize_urls
123
+ @doc = Document.create(:title => "Initial")
124
+ @other_doc = Document.create(:title => "Subsequent")
125
+ adapter_specific_update @doc, :url => nil
126
+ adapter_specific_update @other_doc, :url => nil
127
+ # Just making sure this got unset before the real test
128
+ assert_nil @doc.url
129
+ assert_nil @other_doc.url
130
+
131
+ Document.initialize_urls
132
+
133
+ @doc.reload
134
+ @other_doc.reload
135
+ assert_equal "initial", @doc.url
136
+ assert_equal "subsequent", @other_doc.url
137
+ end
138
+
139
+ def test_should_mass_initialize_urls_with_custom_url_attribute
140
+ Document.class_eval do
141
+ # Manually undefining the url method on Document which, in a real class not reused for tests,
142
+ # would never have been defined to begin with.
143
+ remove_method :url
144
+ acts_as_url :title, :url_attribute => :other
145
+ end
146
+
147
+ @doc = Document.create(:title => "Initial")
148
+ @other_doc = Document.create(:title => "Subsequent")
149
+ adapter_specific_update @doc, :other => nil
150
+ adapter_specific_update @other_doc, :other => nil
151
+ # Just making sure this got unset before the real test
152
+ assert_nil @doc.other
153
+ assert_nil @other_doc.other
154
+
155
+ Document.initialize_urls
156
+
157
+ @doc.reload
158
+ @other_doc.reload
159
+ assert_equal "initial", @doc.other
160
+ assert_equal "subsequent", @other_doc.other
161
+ ensure
162
+ Document.class_eval do
163
+ # Manually undefining the other method on Document for the same reasons as before
164
+ remove_method :other
165
+ end
166
+ end
167
+
168
+ def test_should_allow_using_custom_method_for_generating_url
169
+ Document.class_eval do
170
+ acts_as_url :non_attribute_method
171
+
172
+ def non_attribute_method
173
+ "#{title} got massaged"
174
+ end
175
+ end
176
+
177
+ @doc = Document.create(:title => "Title String")
178
+ assert_equal "title-string-got-massaged", @doc.url
179
+ ensure
180
+ Document.class_eval do
181
+ # Manually undefining method that isn't defined on Document by default
182
+ remove_method :non_attribute_method
183
+ end
184
+ end
185
+
186
+ def test_should_allow_customizing_duplicate_count_separator
187
+ Document.class_eval do
188
+ acts_as_url :title, :duplicate_count_separator => "---"
189
+ end
190
+
191
+ @doc = Document.create(:title => "Unique")
192
+ @other_doc = Document.create(:title => "Unique")
193
+ assert_equal "unique", @doc.url
194
+ assert_equal "unique---1", @other_doc.url
195
+ end
196
+
197
+ def test_should_only_update_url_if_url_attribute_is_valid
198
+ Document.class_eval do
199
+ acts_as_url :title, :sync_url => true
200
+ end
201
+ add_validation_on_document_title
202
+
203
+ @doc = Document.create(:title => "Valid Record", :other => "Present")
204
+ assert_equal "valid-record", @doc.url
205
+ @doc.title = nil
206
+ assert_equal false, @doc.valid?
207
+ assert_equal "valid-record", @doc.url
208
+ ensure
209
+ remove_validation_on_document_title
210
+ end
211
+
212
+ def test_should_allow_customizing_url_limit
213
+ Document.class_eval do
214
+ acts_as_url :title, :limit => 13
215
+ end
216
+
217
+ @doc = Document.create(:title => "I am much too long")
218
+ assert_equal "i-am-much-too", @doc.url
219
+ end
220
+
221
+ def test_handling_duplicate_urls_with_limits
222
+ Document.class_eval do
223
+ acts_as_url :title, :limit => 13
224
+ end
225
+
226
+ @doc = Document.create(:title => "I am much too long and also duplicated")
227
+ assert_equal "i-am-much-too", @doc.url
228
+ @other_doc = Document.create(:title => "I am much too long and also duplicated")
229
+ assert_equal "i-am-much-too-1", @other_doc.url
230
+ end
231
+
232
+ def test_should_allow_excluding_specific_values_from_being_run_through_to_url
233
+ Document.class_eval do
234
+ acts_as_url :title, :exclude => ["_So_Fucking_Special"]
235
+ end
236
+
237
+ @doc = Document.create(:title => "_So_Fucking_Special")
238
+ assert_equal "_So_Fucking_Special", @doc.url
239
+ @doc_2 = Document.create(:title => "But I'm a creep")
240
+ assert_equal "but-im-a-creep", @doc_2.url
241
+ end
242
+
243
+ def test_should_allow_not_forcing_downcasing
244
+ Document.class_eval do
245
+ acts_as_url :title, :force_downcase => false
246
+ end
247
+
248
+ @doc = Document.create(:title => "I have CAPS!")
249
+ assert_equal "I-have-CAPS", @doc.url
250
+ end
251
+
252
+ def test_should_allow_alternate_whitespace_replacements
253
+ Document.class_eval do
254
+ acts_as_url :title, :replace_whitespace_with => "~"
255
+ end
256
+
257
+ @doc = Document.create(:title => "now with tildes")
258
+ assert_equal "now~with~tildes", @doc.url
259
+ end
260
+
261
+ def test_should_allow_enforcing_uniqueness_on_sti_base_class
262
+ STIBaseDocument.class_eval do
263
+ acts_as_url :title, :enforce_uniqueness_on_sti_base_class => true
264
+ end
265
+
266
+ @doc = STIChildDocument.create(:title => "Unique")
267
+ assert_equal "unique", @doc.url
268
+ @doc_2 = AnotherSTIChildDocument.create(:title => "Unique")
269
+ assert_equal "unique-1", @doc_2.url
270
+ end
271
+ end