stringex 2.0.11 → 2.8.6

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 (81) hide show
  1. checksums.yaml +6 -14
  2. data/Gemfile +45 -14
  3. data/MIT-LICENSE +1 -1
  4. data/README.md +162 -0
  5. data/Rakefile +5 -31
  6. data/VERSION +1 -1
  7. data/lib/stringex/acts_as_url/adapter/active_record.rb +1 -1
  8. data/lib/stringex/acts_as_url/adapter/base.rb +37 -5
  9. data/lib/stringex/acts_as_url/adapter/data_mapper.rb +3 -7
  10. data/lib/stringex/acts_as_url/adapter/mongoid.rb +2 -2
  11. data/lib/stringex/acts_as_url.rb +11 -4
  12. data/lib/stringex/configuration/acts_as_url.rb +15 -10
  13. data/lib/stringex/configuration/string_extensions.rb +7 -6
  14. data/lib/stringex/core_ext.rb +10 -0
  15. data/lib/stringex/localization/backend/i18n.rb +16 -3
  16. data/lib/stringex/localization/conversion_expressions.rb +64 -60
  17. data/lib/stringex/localization/converter.rb +8 -4
  18. data/lib/stringex/localization/default_conversions.rb +56 -55
  19. data/lib/stringex/localization.rb +2 -2
  20. data/lib/stringex/string_extensions.rb +34 -6
  21. data/lib/stringex/unidecoder.rb +26 -22
  22. data/lib/stringex/unidecoder_data/x00.yml +1 -1
  23. data/lib/stringex/unidecoder_data/x03.yml +2 -2
  24. data/lib/stringex/unidecoder_data/x05.yml +1 -1
  25. data/lib/stringex/unidecoder_data/x07.yml +1 -1
  26. data/lib/stringex/unidecoder_data/x09.yml +2 -2
  27. data/lib/stringex/unidecoder_data/x0a.yml +2 -2
  28. data/lib/stringex/unidecoder_data/x0f.yml +1 -1
  29. data/lib/stringex/unidecoder_data/x12.yml +1 -1
  30. data/lib/stringex/unidecoder_data/x13.yml +1 -1
  31. data/lib/stringex/unidecoder_data/x14.yml +2 -2
  32. data/lib/stringex/unidecoder_data/x15.yml +1 -1
  33. data/lib/stringex/unidecoder_data/x16.yml +2 -2
  34. data/lib/stringex/unidecoder_data/x18.yml +2 -2
  35. data/lib/stringex/unidecoder_data/x20.yml +4 -4
  36. data/lib/stringex/unidecoder_data/x21.yml +28 -28
  37. data/lib/stringex/unidecoder_data/x25.yml +16 -16
  38. data/lib/stringex/unidecoder_data/x28.yml +1 -1
  39. data/lib/stringex/unidecoder_data/x30.yml +2 -2
  40. data/lib/stringex/unidecoder_data/x32.yml +1 -1
  41. data/lib/stringex/unidecoder_data/xa1.yml +1 -1
  42. data/lib/stringex/unidecoder_data/xb1.yml +1 -1
  43. data/lib/stringex/unidecoder_data/xc6.yml +2 -2
  44. data/lib/stringex/unidecoder_data/xfe.yml +3 -3
  45. data/lib/stringex/unidecoder_data/xff.yml +5 -5
  46. data/lib/stringex.rb +1 -2
  47. data/locales/da.yml +2 -1
  48. data/locales/de.yml +1 -0
  49. data/locales/en.yml +1 -0
  50. data/locales/fr.yml +72 -0
  51. data/locales/nb.yml +76 -0
  52. data/locales/nl.yml +69 -0
  53. data/locales/no.yml +76 -0
  54. data/locales/pl.yml +88 -0
  55. data/locales/pt-BR.yml +1 -0
  56. data/locales/ru.yml +1 -0
  57. data/locales/sv.yml +76 -0
  58. data/stringex.gemspec +38 -59
  59. data/test/unit/acts_as_url/adapter/{active_record.rb → activerecord.rb} +4 -5
  60. data/test/unit/acts_as_url/adapter/{data_mapper.rb → datamapper.rb} +2 -3
  61. data/test/unit/acts_as_url/adapter/mongoid.rb +18 -11
  62. data/test/unit/acts_as_url_configuration_test.rb +2 -2
  63. data/test/unit/acts_as_url_integration_test.rb +169 -73
  64. data/test/unit/localization/da_test.rb +3 -2
  65. data/test/unit/localization/de_test.rb +1 -0
  66. data/test/unit/localization/default_test.rb +2 -0
  67. data/test/unit/localization/en_test.rb +1 -0
  68. data/test/unit/localization/fr_test.rb +118 -0
  69. data/test/unit/localization/nl_test.rb +118 -0
  70. data/test/unit/localization/pl_test.rb +118 -0
  71. data/test/unit/localization/pt_br_test.rb +118 -0
  72. data/test/unit/localization/ru_test.rb +2 -1
  73. data/test/unit/localization/sv_test.rb +118 -0
  74. data/test/unit/localization_test.rb +39 -19
  75. data/test/unit/string_extensions_test.rb +60 -6
  76. data/test/unit/unicode_point_suite/basic_greek_test.rb +1 -1
  77. data/test/unit/unicode_point_suite/basic_latin_test.rb +3 -1
  78. data/test/unit/unidecoder_test.rb +2 -1
  79. metadata +47 -94
  80. data/README.rdoc +0 -131
  81. data/test/unit/redcloth_to_html_test.rb +0 -37
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- MDc3OWVmOWMzZGQwOGRlZDI1YjRmYmNiYWJhZTkwOTFmNjAwZDQ1OQ==
5
- data.tar.gz: !binary |-
6
- ODdiMzBhMDM2ZjYwYjI5ZTI1OGJmYjZlYTlhZDdjMmRhN2FhZDE4YQ==
7
- !binary "U0hBNTEy":
8
- metadata.gz: !binary |-
9
- YzcxMTU1MjUzMTg4OTVhNmRiMjYyNTAwNTllNTE4ODFlMThhMmYxYzkwZjAz
10
- NjEyYzg0ODhkYWUwOGQzYmVlMDBkYmQ3OWU3ZjE2NzQwOWRjYWY2NjZkNTYz
11
- NjM0ZDU1M2I0YzljZjQ5NmM2YzA2ZDRjMDYwOGEyYTgzNTQxODY=
12
- data.tar.gz: !binary |-
13
- ZjcwZTkzODcwNzA5OWJkZmU4ZjEzZDI5MjQ2YjgwYTMxYmM1YWIyOTkwNWEx
14
- ODZiOWUxMTQzZTkwMGVjNTlhN2I0Y2FmNTQ0ZWM1MWJhMzhmOWVmNjc3MDI4
15
- NTQxNzIzZTdkNjQ1OGFiODUyMTNjODE4MDI5Yjk5MWE1NmFjMTg=
2
+ SHA256:
3
+ metadata.gz: 1b26eaa16536e306141877a8ee3f50acdd23d8cb3601fe1830ccf798e7a2b433
4
+ data.tar.gz: 8062ea4ee5667139acb8337fa979d212ab1ef52a69a1303efd302df142c83c8c
5
+ SHA512:
6
+ metadata.gz: 7179fa45397f05d438470e2ae225e0e4ac03a6f0cf2922af031ca4e7c68bb7be20d8d833bab9f928782687ccc78f5cdac30142a2923941e23441616b948b3041
7
+ data.tar.gz: b42d191422c1340122677106d7360a05ec6c41f30206f577701a276ac253509a3f4553a5f628b383b3aed4fa293e4c0b7498eb0466cc565eeaefe576e9ebba08
data/Gemfile CHANGED
@@ -1,20 +1,51 @@
1
1
  # A sample Gemfile
2
- source "https://rubygems.org"
2
+ source 'https://rubygems.org'
3
+
4
+ def activerecord?
5
+ adapter.nil? || adapter == 'activerecord'
6
+ end
7
+
8
+ def datamapper?
9
+ adapter == 'datamapper'
10
+ end
11
+
12
+ def mongoid?
13
+ if RUBY_VERSION > '1.8.x'
14
+ adapter == 'mongoid'
15
+ else
16
+ puts 'Mongoid requires Ruby higher than 1.8.x'
17
+ end
18
+ end
19
+
20
+ def adapter
21
+ ENV['ADAPTER']
22
+ end
3
23
 
4
24
  group :development do
5
- gem "activerecord", "3.2.13"
6
- gem "dm-core", "1.2.0"
7
- gem "dm-migrations", "1.2.0"
8
- gem "dm-sqlite-adapter", "1.2.0"
9
- gem "dm-validations", "1.2.0"
10
- gem "jeweler", "1.8.4"
11
- if RUBY_VERSION > "1.8.x"
12
- gem "mongoid", "3.1.4"
25
+ # Standard gems across gemfiles
26
+ gem 'jeweler', '2.3.7'
27
+ gem 'travis-lint', '1.7.0'
28
+ # Can I state that I really dislike camelcased gem names?
29
+ gem 'RedCloth', '4.2.9'
30
+ gem 'sqlite3', '1.3.10'
31
+ gem 'test-unit', '3.0.9'
32
+
33
+ if activerecord?
34
+ gem 'activerecord', '5.1.4'
35
+ end
36
+
37
+ if datamapper?
38
+ gem 'dm-core', '1.2.1'
39
+ gem 'dm-migrations', '1.2.0'
40
+ gem 'dm-sqlite-adapter', '1.2.0'
41
+ gem 'dm-validations', '1.2.0'
42
+ end
43
+
44
+ if mongoid?
45
+ gem 'mongoid', '3.1.6'
46
+ gem 'i18n', '0.6.1'
13
47
  else
14
- puts "Mongoid requires Ruby higher than 1.8.x"
48
+ # Everyone else can get the most up-to-date I18n
49
+ gem 'i18n', '0.7.0'
15
50
  end
16
- gem "RedCloth", "4.2.9" # Can I state that I really dislike camelcased gem names?
17
- gem "sqlite3", "1.3.7"
18
- gem "travis-lint", "1.7.0"
19
- gem "i18n", "0.6.1"
20
51
  end
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2008-2012 Lucky Sneaks
1
+ Copyright (c) 2008-2014 Lucky Sneaks
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md ADDED
@@ -0,0 +1,162 @@
1
+ # Stringex [<img src="https://codeclimate.com/github/rsl/stringex.svg" />](https://codeclimate.com/github/rsl/stringex) [<img src="https://travis-ci.org/rsl/stringex.svg?branch=master" alt="Build Status" />](https://travis-ci.org/rsl/stringex) [<img src="https://badge.fury.io/rb/stringex.svg" alt="Gem Version" />](http://badge.fury.io/rb/stringex)
2
+
3
+ Some [hopefully] useful extensions to Ruby's String class. It is made up of three libraries: ActsAsUrl, Unidecoder, and StringExtensions.
4
+
5
+ *NOTE: Stringex 2.0 [and beyond] drops support for Rails 2. If you need support for that version, use 1.5.1 instead.*
6
+
7
+ ## ActsAsUrl
8
+
9
+ *NOTE: You can now require 'stringex_lite' instead of 'stringex' and skip loading ActsAsUrl functionality if you don't need it.*
10
+
11
+ This library is designed to create URI-friendly representations of an attribute, for use in generating urls from your attributes. Basic usage is just calling the method:
12
+
13
+ ```ruby
14
+ # Inside your model
15
+ acts_as_url :title
16
+ ```
17
+
18
+ which will populate the `url` attribute on the object with the converted contents of the `title` attribute. `acts_as_url` takes the following options:
19
+
20
+ | | |
21
+ |---|---|
22
+ | `:url_attribute` | The name of the attribute to use for storing the generated url string. Default is `:url` |
23
+ | `:scope` | The name of model attribute to scope unique urls to. There is no default here. |
24
+ | `:only_when_blank` | If set to true, the url generation will only happen when `:url_attribute` is blank. Default is false (meaning url generation will happen always). |
25
+ | `:sync_url` | If set to true, the url field will be updated when changes are made to the attribute it is based on. Default is false. |
26
+ | `:allow_slash` | If set to true, the url field will not convert slashes. Default is false. |
27
+ | `:allow_duplicates` | If set to true, unique urls will not be enforced. Default is false. *NOTE: This is strongly not recommended if you are routing solely on the generated slug as you will no longer be guaranteed to lookup the expected record based on a duplicate slug.* |
28
+ | `:limit` | If set, will limit length of url generated. Default is nil. |
29
+ | `:truncate_words` | Used with :limit. If set to false, the url will be truncated to the last whole word before the limit was reached. Default is true. |
30
+ | `:blacklist` | List of urls that should not be allowed. Default is `%w{new}` [which avoids confusion on urls like `/documents/new`]. |
31
+ | `:blacklist_policy` | Proc or lambda defining new naming behavior when blacklisted urls are encountered. Default converts `/documents/new` to `/documents/new-document`. |
32
+
33
+ In order to use the generated url attribute, you will probably want to
34
+ override `to_param` like so, in your Model:
35
+
36
+ ```ruby
37
+ # Inside your model
38
+ def to_param
39
+ url # or whatever you set :url_attribute to
40
+ end
41
+ ```
42
+
43
+ Routing called via named routes like `foo_path(@foo)` will automatically use the url. In your controllers you will need to call
44
+ `Foo.find_by_url(params[:id])` instead of the regular find. Don't look for `params[:url]` unless you set it explicitly in the routing, `to_param` will generate `params[:id]`.
45
+
46
+ Note that if you add `acts_as_url` to an existing model, the `url` database column will initially be blank. To set this column for your existing instances, you can use the `initialize_urls` method. So if your class is `Post`, just say `Post.initialize_urls`.
47
+
48
+ Unlike other permalink solutions, ActsAsUrl doesn't rely on Iconv (which is inconsistent across platforms and doesn't provide great transliteration as is) but instead uses a transliteration scheme (see the code for Unidecoder) which produces much better results for Unicode characters. It also mixes in some custom helpers to translate common characters into a more URI-friendly format rather than just dump them completely. Examples:
49
+
50
+ ```ruby
51
+ # A simple prelude
52
+ "simple English".to_url => "simple-english"
53
+ "it's nothing at all".to_url => "its-nothing-at-all"
54
+ "rock & roll".to_url => "rock-and-roll"
55
+
56
+ # Let's show off
57
+ "$12 worth of Ruby power".to_url => "12-dollars-worth-of-ruby-power"
58
+ "10% off if you act now".to_url => "10-percent-off-if-you-act-now"
59
+
60
+ # You dont EVEN wanna rely on Iconv for this next part
61
+ "kick it en Français".to_url => "kick-it-en-francais"
62
+ "rock it Español style".to_url => "rock-it-espanol-style"
63
+ "tell your readers 你好".to_url => "tell-your-readers-ni-hao"
64
+ ```
65
+
66
+ Compare those results with the ones produced on my Intel Mac by a leading permalink plugin:
67
+
68
+ ```ruby
69
+ "simple English" # => "simple-english"
70
+ "it's nothing at all" # => "it-s-nothing-at-all"
71
+ "rock & roll" # => "rock-roll"
72
+
73
+ "$12 worth of Ruby power" # => "12-worth-of-ruby-power"
74
+ "10% off if you act now" # => "10-off-if-you-act-now"
75
+
76
+ "kick it en Français" # => "kick-it-en-francais"
77
+ "rock it Español style" # => "rock-it-espan-ol-style"
78
+ "tell your readers 你好" # => "tell-your-readers"
79
+ ```
80
+
81
+ Not so great, actually.
82
+
83
+ Note: No offense is intended to the author(s) of whatever plugins might produce such results. It's not your faults Iconv sucks.
84
+
85
+ ## Unidecoder
86
+
87
+ This library converts Unicode [and accented ASCII] characters to their plain-text ASCII equivalents. This is a port of Perl's Unidecode and provides eminently superior and more reliable results than Iconv. (Seriously, Iconv... A plague on both your houses! [sic])
88
+
89
+ You may require only the unidecoder (and its dependent localization) via
90
+
91
+ ```ruby
92
+ require "stringex/unidecoder"
93
+ ```
94
+
95
+ You probably won't ever need to run Unidecoder by itself. Thus, you probably would want to add String#to_ascii which wraps all of Unidecoder's functionality, by requiring:
96
+
97
+ ```ruby
98
+ require "stringex/core_ext"
99
+ ```
100
+
101
+ For anyone interested, details of the implementation can be read about in the original implementation of [Text::Unidecode](http://interglacial.com/~sburke/tpj/as_html/tpj22.html). Extensive examples can be found in the tests.
102
+
103
+ ## StringExtensions
104
+
105
+ A small collection of extensions on Ruby's String class. Please see the documentation for StringExtensions module for more information. There's not much to explain about them really.
106
+
107
+ ## Localization
108
+
109
+ With Stringex version 2.0 and higher, you can localize the different conversions in Stringex. Read more [here](https://github.com/rsl/stringex/wiki/Localization-of-Stringex-conversions). If you add a new language, please submit a pull request so we can make it available to other users also.
110
+
111
+ ## Ruby on Rails Usage
112
+
113
+ When using Stringex with Ruby on Rails, you automatically get built-in translations for miscellaneous characters, HTML entities, and vulgar fractions. You can see Stringex's standard translations [here](https://github.com/rsl/stringex/tree/master/locales).
114
+
115
+ Currently, built-in translations are available for the following languages:
116
+
117
+ * English (en)
118
+ * Danish (da)
119
+ * Swedish (sv)
120
+ * Dutch (nl)
121
+ * German (de)
122
+ * Polish (pl)
123
+ * Portuguese Brazilian (pt-BR)
124
+ * Russian (ru)
125
+
126
+ You can easily add your own or customize the built-in translations - read [here](https://github.com/rsl/stringex/wiki/Localization-of-Stringex-conversions). If you add a new language, please submit a pull request so we can make it available to other users also.
127
+
128
+ If you don't want to use the Stringex built-in translations, you can force Stringex to use English (or another language), regardless what is in your `I18n.locale`. In an initializer, e.g. `config/initializers/stringex.rb`:
129
+
130
+ ```ruby
131
+ Stringex::Localization.locale = :en
132
+ ```
133
+
134
+ ## CanCan Usage Note
135
+
136
+ You'll need to add a `:find_by => :url` to your `load_and_authorize_resource`. Here's an example:
137
+
138
+ ```ruby
139
+ load_and_authorize_resource :class => "Whatever", :message => "Not authorized", :find_by => :url
140
+ ```
141
+
142
+ ## Semantic Versioning
143
+
144
+ This project conforms to [semver](http://semver.org/). As a result of this policy, you can (and should) specify a dependency on this gem using the [Pessimistic Version Constraint](http://guides.rubygems.org/patterns/) with two digits of precision. For example:
145
+
146
+ ```ruby
147
+ spec.add_dependency 'stringex', '~> 1.0'
148
+ ```
149
+
150
+ This means your project is compatible with licensee 1.0 up until 2.0. You can also set a higher minimum version:
151
+
152
+ ```ruby
153
+ spec.add_dependency 'stringex', '~> 1.1'
154
+ ```
155
+
156
+ ## Thanks & Acknowledgements
157
+
158
+ If it's not obvious, some of the code for ActsAsUrl is based on Rick Olsen's [permalink_fu](http://svn.techno-weenie.net/projects/plugins/permalink_fu/) plugin. Unidecoder is a Ruby port of Sean Burke's [Text::Unidecode](http://interglacial.com/~sburke/tpj/as_html/tpj22.html) module for Perl. And, finally, the bulk of [strip_html_tags](classes/Stringex/StringExtensions.html#M000005) in StringExtensions was stolen from Tobias Lütke's Regex in [Typo](http://typosphere.org/).
159
+
160
+ GIANT thanks to the many contributors who have helped make Stringex better and better: http://github.com/rsl/stringex/contributors
161
+
162
+ Copyright (c) 2008-2018 Lucky Sneaks, released under the MIT license
data/Rakefile CHANGED
@@ -30,46 +30,20 @@ end
30
30
  Rake::TestTask.new do |t|
31
31
  t.libs << 'lib' << 'test'
32
32
  t.pattern = 'test/unit/**/*_test.rb'
33
- t.verbose = true
33
+ t.verbose = false
34
+ t.warning = false
34
35
  end
35
36
 
36
37
  namespace :test do
37
38
  Rake::TestTask.new(:performance) do |t|
38
39
  t.libs << 'lib' << 'test'
39
40
  t.pattern = 'test/performance/**/*_test.rb'
40
- t.verbose = true
41
+ t.verbose = false
42
+ t.warning = false
41
43
  end
42
44
  end
43
45
 
44
- desc 'Default: Run Stringex test suite using ActiveRecord as the ORM'
45
- task :default => [:setup_active_record_suite, :test]
46
-
47
- task :setup_active_record_suite do
48
- ENV['ADAPTER'] = 'active_record'
49
- end
50
-
51
- desc 'Run Stringex test suite using ActiveRecord as the ORM'
52
- namespace :test do
53
- task :active_record => [:setup_active_record_suite]
54
- end
55
-
56
- task :setup_mongoid_suite do
57
- ENV['ADAPTER'] = 'mongoid'
58
- end
59
-
60
- desc 'Run Stringex test suite using Mongoid as the ORM'
61
- namespace :test do
62
- task :mongoid => [:setup_mongoid_suite, :test]
63
- end
64
-
65
- task :setup_data_mapper_suite do
66
- ENV['ADAPTER'] = 'data_mapper'
67
- end
68
-
69
- desc 'Run Stringex test suite using DataMapper as the ORM'
70
- namespace :test do
71
- task :data_mapper => [:setup_data_mapper_suite, :test]
72
- end
46
+ task :default => :test
73
47
 
74
48
  desc 'Generate RDoc for Stringex'
75
49
  Rake::RDocTask.new(:rdoc) do |rdoc|
data/VERSION CHANGED
@@ -1 +1 @@
1
- 2.0.11
1
+ 2.8.6
@@ -11,7 +11,7 @@ module Stringex
11
11
  private
12
12
 
13
13
  def klass_previous_instances(&block)
14
- klass.find_each(:conditions => {settings.url_attribute => [nil, '']}, &block)
14
+ klass.where(settings.url_attribute => [nil, '']).find_each(&block)
15
15
  end
16
16
 
17
17
  def self.orm_class
@@ -22,6 +22,7 @@ module Stringex
22
22
  self.instance = instance
23
23
 
24
24
  handle_url!
25
+ handle_blacklisted_url!
25
26
  handle_duplicate_url! unless settings.allow_duplicates
26
27
  end
27
28
 
@@ -69,7 +70,11 @@ module Stringex
69
70
  end
70
71
 
71
72
  def create_callback
72
- klass.send klass_callback_method, :ensure_unique_url, callback_options
73
+ klass.send(
74
+ klass_callback_method,
75
+ :ensure_unique_url,
76
+ **callback_options
77
+ )
73
78
  end
74
79
 
75
80
  def klass_callback_method
@@ -118,20 +123,47 @@ module Stringex
118
123
  end
119
124
 
120
125
  def handle_duplicate_url!
121
- return if url_owners.none?{|owner| url_attribute_for(owner) == base_url}
122
- n = 1
123
- while url_owners.any?{|owner| url_attribute_for(owner) == duplicate_for_base_url(n)}
124
- n = n.succ
126
+ return if !url_taken?(base_url)
127
+ n = nil
128
+ sequence = duplicate_url_sequence.tap(&:rewind)
129
+ loop do
130
+ n = sequence.next
131
+ break unless url_taken?(duplicate_for_base_url(n))
125
132
  end
126
133
  write_url_attribute duplicate_for_base_url(n)
127
134
  end
128
135
 
136
+ def duplicate_url_sequence
137
+ settings.duplicate_sequence ||
138
+ Enumerator.new do |enum|
139
+ n = 1
140
+ loop do
141
+ enum.yield n
142
+ n += 1
143
+ end
144
+ end
145
+ end
146
+
147
+ def url_taken?(url)
148
+ if settings.url_taken_method
149
+ instance.send(settings.url_taken_method, url)
150
+ else
151
+ url_owners.any?{|owner| url_attribute_for(owner) == url}
152
+ end
153
+ end
154
+
129
155
  def handle_url!
130
156
  self.base_url = instance.send(settings.url_attribute)
131
157
  modify_base_url if is_blank?(base_url) || !settings.only_when_blank
132
158
  write_url_attribute base_url
133
159
  end
134
160
 
161
+ def handle_blacklisted_url!
162
+ return unless settings.blacklist.to_set.include?(base_url)
163
+ self.base_url = settings.blacklist_policy.call(instance, base_url)
164
+ write_url_attribute base_url
165
+ end
166
+
135
167
  def instance_from_db
136
168
  instance.class.find(instance.id)
137
169
  end
@@ -33,19 +33,15 @@ module Stringex
33
33
  end
34
34
 
35
35
  def klass_previous_instances(&block)
36
- klass.all(:conditions => {settings.url_attribute => [nil]}).each(&block)
36
+ klass.all(conditions: {settings.url_attribute => [nil]}).each(&block)
37
37
  end
38
38
 
39
39
  def primary_key
40
40
  instance.class.key.first.instance_variable_get '@name'
41
41
  end
42
42
 
43
- def read_attribute(instance, attribute)
44
- instance.attributes[attribute]
45
- end
46
-
47
43
  def url_owners
48
- @url_owners ||= url_owners_class.all(:conditions => url_owner_conditions)
44
+ @url_owners ||= url_owners_class.all(conditions: url_owner_conditions)
49
45
  end
50
46
 
51
47
  def read_attribute(instance, name)
@@ -62,4 +58,4 @@ module Stringex
62
58
  end
63
59
  end
64
60
  end
65
- end
61
+ end
@@ -11,7 +11,7 @@ module Stringex
11
11
 
12
12
  def add_new_record_url_owner_conditions
13
13
  return if instance.new_record?
14
- @url_owner_conditions.merge! :id => {'$ne' => instance.id}
14
+ @url_owner_conditions.merge! id: {'$ne' => instance.id}
15
15
  end
16
16
 
17
17
  def add_scoped_url_owner_conditions
@@ -34,4 +34,4 @@ module Stringex
34
34
  end
35
35
  end
36
36
  end
37
- end
37
+ end
@@ -4,7 +4,7 @@ require "stringex/acts_as_url/adapter"
4
4
  module Stringex
5
5
  module ActsAsUrl # :nodoc:
6
6
  def self.configure(&block)
7
- Stringex::Configuration::ActsAsUrl.configure &block
7
+ Stringex::Configuration::ActsAsUrl.configure(&block)
8
8
  end
9
9
 
10
10
  def self.unconfigure!
@@ -33,6 +33,11 @@ module Stringex
33
33
  # differentiate between urls. Default is false[y]. See note on <tt>:scope</tt>.
34
34
  # <tt>:duplicate_count_separator</tt>:: String to use when forcing unique urls from non-unique strings.
35
35
  # Default is "-".
36
+ # <tt>:duplicate_sequence</tt>:: Supply an enumerator to generate the values used to generate
37
+ # unique urls (when <tt>:allow_duplicates</tt> is false).
38
+ # By default, generates positive integers in sequence from 1.
39
+ # <strong>Note:</strong> The sequence is restarted for each record
40
+ # (by calling <tt>#rewind</tt>).
36
41
  # <tt>:force_downcase</tt>:: If false, allows generated url to contain uppercased letters. Default is false.
37
42
  # <tt>:exclude_list</tt>:: List of complete strings that should not be transformed by <tt>acts_as_url</tt>.
38
43
  # Default is empty.
@@ -72,11 +77,13 @@ module Stringex
72
77
 
73
78
  # Some ORMs function as mixins not base classes and need to have a hook to reinclude
74
79
  # and re-extend ActsAsUrl methods
75
- def included(base)
80
+ def included(base = nil, &block)
76
81
  super
77
82
 
78
- base.send :include, Stringex::ActsAsUrl::ActsAsUrlInstanceMethods
79
- base.send :extend, Stringex::ActsAsUrl::ActsAsUrlClassMethods
83
+ if base
84
+ base.send :include, Stringex::ActsAsUrl::ActsAsUrlInstanceMethods
85
+ base.send :extend, Stringex::ActsAsUrl::ActsAsUrlClassMethods
86
+ end
80
87
  end
81
88
 
82
89
  # Initialize the url fields for the records that need it. Designed for people who add
@@ -14,7 +14,8 @@ module Stringex
14
14
  :exclude,
15
15
  :force_downcase,
16
16
  :limit,
17
- :replace_whitespace_with
17
+ :replace_whitespace_with,
18
+ :truncate_words
18
19
  ].inject(Hash.new){|m, x| m[x] = settings.send(x); m}
19
20
  end
20
21
 
@@ -30,16 +31,20 @@ module Stringex
30
31
 
31
32
  def self.default_settings
32
33
  @default_settings ||= {
33
- :allow_duplicates => false,
34
- :callback_method => :before_validation,
35
- :duplicate_count_separator => "-",
36
- :enforce_uniqueness_on_sti_class => false,
37
- :only_when_blank => false,
38
- :scope_for_url => nil,
39
- :sync_url => false,
40
- :url_attribute => "url",
34
+ allow_duplicates: false,
35
+ callback_method: :before_validation,
36
+ duplicate_count_separator: "-",
37
+ enforce_uniqueness_on_sti_base_class: false,
38
+ only_when_blank: false,
39
+ scope_for_url: nil,
40
+ sync_url: false,
41
+ url_attribute: "url",
42
+ blacklist: %w[new],
43
+ blacklist_policy: lambda { |instance, url|
44
+ "#{url}-#{instance.class.to_s.downcase}"
45
+ }
41
46
  }.merge(Stringex::Configuration::StringExtensions.new.default_settings)
42
47
  end
43
48
  end
44
49
  end
45
- end
50
+ end
@@ -7,13 +7,14 @@ module Stringex
7
7
 
8
8
  def self.default_settings
9
9
  @default_settings ||= {
10
- :allow_slash => false,
11
- :exclude => [],
12
- :force_downcase => true,
13
- :limit => nil,
14
- :replace_whitespace_with => "-"
10
+ allow_slash: false,
11
+ exclude: [],
12
+ force_downcase: true,
13
+ limit: nil,
14
+ replace_whitespace_with: "-",
15
+ truncate_words: true
15
16
  }
16
17
  end
17
18
  end
18
19
  end
19
- end
20
+ end
@@ -0,0 +1,10 @@
1
+ Stringex = Module.new unless defined?(Stringex)
2
+ ensure_module_defined = ->(base, module_name){
3
+ base.const_set(module_name, Module.new) unless base.const_defined?(module_name)
4
+ }
5
+ ensure_module_defined[Stringex, :StringExtensions]
6
+ ensure_module_defined[Stringex::StringExtensions, :PublicInstanceMethods]
7
+ ensure_module_defined[Stringex::StringExtensions, :PublicClassMethods]
8
+
9
+ String.send :include, Stringex::StringExtensions::PublicInstanceMethods
10
+ String.send :extend, Stringex::StringExtensions::PublicClassMethods
@@ -5,6 +5,12 @@ module Stringex
5
5
  LOAD_PATH_BASE = File.join(File.expand_path(File.dirname(__FILE__)), '..', '..', '..', '..', 'locales')
6
6
 
7
7
  class << self
8
+ def reset!
9
+ super
10
+ @locale = nil
11
+ ::I18n.reload! if defined?(::I18n) && ::I18n.respond_to?(:reload!)
12
+ end
13
+
8
14
  def locale
9
15
  @locale || ::I18n.locale
10
16
  end
@@ -26,7 +32,7 @@ module Stringex
26
32
  end
27
33
 
28
34
  def store_translations(locale, scope, data)
29
- ::I18n.backend.store_translations(locale, { :stringex => { scope => data } })
35
+ ::I18n.backend.store_translations(locale, {stringex: {scope => data}})
30
36
  reset_translations_cache
31
37
  end
32
38
 
@@ -41,19 +47,26 @@ module Stringex
41
47
 
42
48
  def load_translations(locale = nil)
43
49
  locale ||= self.locale
44
- path = Dir[File.join(LOAD_PATH_BASE, "#{locale}.yml")]
45
50
  ::I18n.load_path |= Dir[File.join(LOAD_PATH_BASE, "#{locale}.yml")]
46
51
  ::I18n.backend.load_translations
47
52
  reset_translations_cache
48
53
  end
49
54
 
50
55
  def i18n_translations_for(locale)
51
- ::I18n.translate("stringex", :locale => locale, :default => {})
56
+ ensure_locales_enforced_or_not
57
+ ::I18n.translate("stringex", locale: locale, default: {})
52
58
  end
53
59
 
54
60
  def reset_translations_cache
55
61
  @translations = nil
56
62
  end
63
+
64
+ def ensure_locales_enforced_or_not
65
+ return unless ::I18n.respond_to?(:enforce_available_locales)
66
+ # Allow users to have set this to false manually but default to true
67
+ return unless ::I18n.enforce_available_locales == nil
68
+ ::I18n.enforce_available_locales = ::I18n.available_locales != []
69
+ end
57
70
  end
58
71
  end
59
72