active_permalink 0.3.2 → 0.5.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 243ba41f7bbc808001e4aec17f7212499f5c1fdc938b2e20b72db13f25febca0
4
- data.tar.gz: 32b11a18881be60c779b2ad58c96231d21c8ce5e2377a0dfbc6ec8a06cfb8f09
3
+ metadata.gz: 5fa20c1f3b8d87d139d4a4dd071f4eaf254e920f9c548d8972bee1d039d50447
4
+ data.tar.gz: fcfc097109ae5c2a061d248047d3afce7846281caca1af726531d957b8ce19a6
5
5
  SHA512:
6
- metadata.gz: 226c6d785ea23b9bd67d8dea472188985cc992b5406e50163219e9318698eec5cb8612829cddb018e255992058331b3865f39dc55a1a25f2c7dd52c01e1572c1
7
- data.tar.gz: de0bc4c7f9201cc9bdd33ff2cb26505ad603ea45c5107f894302f78ebe7f898624a381b153d1429deff36ce00ebe7a8fa041238a0cf820d31f2ac1e202c26c3f
6
+ metadata.gz: 983b44808444eac00eec9208294601a8dd354e63ea2fe301b1ac6e18e704923d323dab9cb9a04ac1a0ae4ef3d799bdba1cd475083fe82e6b6362853b57e6ea69
7
+ data.tar.gz: 73f7a8cf127e57656898024e6f6c9f80b7111a1d32a347cfc585ad3dd41327482f428cc826e7dd8c77557298cf8124d7cd196c3d36136389c90bbfdfc2a3a9a9
@@ -1,4 +1,3 @@
1
- require 'stringex'
2
1
  require 'active_record'
3
2
  require 'active_delegate'
4
3
  require 'active_permalink/version'
@@ -12,6 +11,17 @@ module ActivePermalink
12
11
  autoload :Localizer
13
12
  autoload :Querying
14
13
  autoload :Loader
14
+ autoload :Config
15
+
16
+ class << self
17
+ def config
18
+ @config ||= Config.new
19
+ end
20
+
21
+ def setup
22
+ yield config
23
+ end
24
+ end
15
25
  end
16
26
 
17
27
  ActiveSupport.on_load(:active_record) do
@@ -0,0 +1,27 @@
1
+ require 'active_support/configurable'
2
+
3
+ module ActivePermalink
4
+ class Config
5
+ include ActiveSupport::Configurable
6
+
7
+ config_accessor(:class_name) { 'ActivePermalink::Permalink' }
8
+ config_accessor(:querying) { true }
9
+ config_accessor(:localized) { false }
10
+ config_accessor(:locale_column) { :locale }
11
+ config_accessor(:locale_accessors) { true }
12
+ config_accessor(:fallthrough_accessors) { false }
13
+ config_accessor(:fallbacks) { false }
14
+
15
+ def options_for(**options)
16
+ options.reverse_merge(
17
+ class_name: class_name,
18
+ querying: querying,
19
+ localized: localized,
20
+ locale_column: locale_column,
21
+ locale_accessors: locale_accessors,
22
+ fallthrough_accessors: fallthrough_accessors,
23
+ fallbacks: fallbacks
24
+ )
25
+ end
26
+ end
27
+ end
@@ -1,6 +1,22 @@
1
+ require 'any_ascii'
2
+
1
3
  module ActivePermalink
2
4
  class Generator
5
+ class << self
6
+ def generate(record, value, locale = nil)
7
+ return if value.nil? && !record.slug_should_generate?
8
+
9
+ options = record.permalink_options.merge(locale: locale)
10
+ generator = Generator.new(record, options)
11
+ generator.generate(value)
12
+
13
+ record.permalinks = generator.permalinks
14
+ end
15
+ end
16
+
3
17
  def initialize(record, options = {})
18
+ options[:locale] = options.fetch(:locale, I18n.locale).to_s
19
+
4
20
  @record = record
5
21
  @options = options
6
22
  @field = options[:field]
@@ -22,7 +38,7 @@ module ActivePermalink
22
38
  private
23
39
 
24
40
  def locale
25
- I18n.locale.to_s
41
+ @options[:locale]
26
42
  end
27
43
 
28
44
  def changed?
@@ -75,7 +91,10 @@ module ActivePermalink
75
91
  def slug_from_column
76
92
  @slug_from_column ||= begin
77
93
  value = @new_value.presence || @record.send(@field)
78
- value.to_s.to_url
94
+ return if value.blank?
95
+
96
+ value = AnyAscii.transliterate(value)
97
+ value.parameterize
79
98
  end
80
99
  end
81
100
 
@@ -3,18 +3,13 @@ module ActivePermalink
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  class_methods do
6
- def has_permalink(field, localized: false, locale_column: :locale, **options)
7
- include ActiveDelegate
6
+ def has_permalink(field, **options)
7
+ options = ActivePermalink.config.options_for(field: field, **options)
8
8
 
9
9
  class_attribute :permalink_options
10
+ self.permalink_options = options
10
11
 
11
- self.permalink_options = options.merge(
12
- field: field,
13
- localized: localized,
14
- locale_column: locale_column
15
- )
16
-
17
- with_options(as: :sluggable, class_name: 'ActivePermalink::Permalink') do
12
+ with_options(as: :sluggable, class_name: options[:class_name]) do
18
13
  has_many :permalinks,
19
14
  dependent: :destroy,
20
15
  autosave: true
@@ -22,24 +17,22 @@ module ActivePermalink
22
17
  has_many :old_permalinks,
23
18
  -> { inactive }
24
19
 
25
- if localized
20
+ if options[:localized]
26
21
  has_many :active_permalinks,
27
22
  -> { active }
28
23
 
29
24
  has_one :active_permalink,
30
- -> { active.where(locale_column => I18n.locale) }
25
+ -> { active.where(options[:locale_column] => I18n.locale) }
31
26
  else
32
27
  has_one :active_permalink,
33
28
  -> { active }
34
29
  end
35
30
  end
36
31
 
37
- delegate_attribute :slug, :string,
38
- to: :active_permalink
39
-
40
32
  include Persistence
41
- include Querying
42
- include Localizer if localized
33
+
34
+ include Querying if options[:querying]
35
+ include Localizer if options[:localized]
43
36
  end
44
37
  end
45
38
  end
@@ -3,76 +3,91 @@ module ActivePermalink
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- def permalink_reader
7
- PermalinkReader.new(permalinks, permalink_options)
6
+ def slug_backend
7
+ @slug_backend ||= PermalinkBackend.new(self)
8
8
  end
9
9
 
10
- def slug?
11
- permalink_reader.exists?
10
+ alias permalink_reader slug_backend
11
+
12
+ def slug?(locale: nil)
13
+ slug_backend.exists?(locale || I18n.locale)
12
14
  end
13
15
 
14
- def slug
15
- permalink_reader.value
16
+ def slug(locale: nil)
17
+ slug_backend.read(locale || I18n.locale)
16
18
  end
17
19
 
18
- I18n.available_locales.each do |locale|
19
- define_method(:"slug_#{locale}?") do
20
- I18n.with_locale(locale) { slug? }
21
- end
20
+ def slug=(value, locale: nil)
21
+ slug_backend.write(value, locale || I18n.locale)
22
+ end
22
23
 
23
- define_method(:"slug_#{locale}") do
24
- I18n.with_locale(locale) { slug }
25
- end
24
+ if permalink_options[:locale_accessors]
25
+ include SlugLocaleAccessors
26
+ elsif permalink_options[:fallthrough_accessors]
27
+ include SlugFallthroughAccessors
28
+ end
26
29
 
27
- define_method(:"slug_#{locale}=") do |value|
28
- I18n.with_locale(locale) { send(:slug=, value) }
29
- end
30
+ private
31
+
32
+ def _generate_permalink_slug(value)
33
+ slug_backend.write(value, I18n.locale)
30
34
  end
31
35
  end
32
36
 
33
- class PermalinkReader
34
- attr_reader :permalinks, :options
37
+ class InvalidLocale < I18n::InvalidLocale
38
+ end
39
+
40
+ class PermalinkBackend
41
+ attr_reader :record, :permalinks, :options
35
42
 
36
- def initialize(permalinks, options)
37
- @permalinks = permalinks
38
- @options = options
43
+ def initialize(record)
44
+ @record = record
45
+ @options = record.permalink_options
46
+ @permalinks = record.permalinks.to_a
39
47
  end
40
48
 
41
49
  def fallbacks?
42
50
  options[:fallbacks].present?
43
51
  end
44
52
 
45
- def exists?
46
- find_permalink(I18n.locale).present?
53
+ def exists?(locale)
54
+ enforce_available_locales!(locale)
55
+ find_permalink(locale).present?
56
+ end
57
+
58
+ def read(locale)
59
+ enforce_available_locales!(locale)
60
+ find_slug(locale)
47
61
  end
48
62
 
49
- def value
50
- find_slug(I18n.locale)
63
+ def write(value, locale)
64
+ enforce_available_locales!(locale)
65
+ update_slug(value, locale)
51
66
  end
52
67
 
53
68
  private
54
69
 
70
+ def enforce_available_locales!(locale)
71
+ return unless I18n.enforce_available_locales
72
+ return if I18n.available_locales.include?(locale.to_sym)
73
+
74
+ raise InvalidLocale.new(locale)
75
+ end
76
+
55
77
  def locale_column
56
78
  @options[:locale_column]
57
79
  end
58
80
 
59
- def find_permalink(locale)
60
- permalinks.find do |permalink|
61
- permalink.send(locale_column) == locale.to_s
81
+ def find_permalink(*locales)
82
+ permalinks.select(&:active?).find do |permalink|
83
+ locale = permalink.send(locale_column)
84
+ locales.include?(locale.to_sym)
62
85
  end
63
86
  end
64
87
 
65
88
  def find_fallback(locale)
66
- fallbacks = I18n.try(:fallbacks) || {}
67
- fallbacks = fallbacks.fetch(locale, [I18n.default_locale])
68
- permalink = nil
69
-
70
- fallbacks.find do |fallback|
71
- permalink = find_permalink(fallback)
72
- permalink.present?
73
- end
74
-
75
- permalink
89
+ locales = I18n.fallbacks[locale]
90
+ find_permalink(*locales) if locales.present?
76
91
  end
77
92
 
78
93
  def find_slug(locale)
@@ -81,6 +96,53 @@ module ActivePermalink
81
96
 
82
97
  permalink.try(:slug)
83
98
  end
99
+
100
+ def update_slug(value, locale)
101
+ Generator.generate(record, value, locale)
102
+ @permalinks = record.permalinks.to_a
103
+ end
104
+ end
105
+
106
+ module SlugLocaleAccessors
107
+ extend ActiveSupport::Concern
108
+
109
+ included do
110
+ I18n.available_locales.each do |locale|
111
+ define_method(:"slug_#{locale}?") do
112
+ slug_backend.exists?(locale)
113
+ end
114
+
115
+ define_method(:"slug_#{locale}") do
116
+ slug_backend.read(locale)
117
+ end
118
+
119
+ define_method(:"slug_#{locale}=") do |value|
120
+ slug_backend.write(value, locale)
121
+ end
122
+ end
123
+ end
124
+ end
125
+
126
+ module SlugFallthroughAccessors
127
+ extend ActiveSupport::Concern
128
+
129
+ included do
130
+ method_name_regex = /\Aslug_([a-z]{2}(_[a-z]{2})?)(=?|\??)\z/.freeze
131
+
132
+ define_method :method_missing do |method_name, *arguments, **options, &block|
133
+ if method_name =~ method_name_regex
134
+ locale, suffix = $1.split('_')
135
+ locale = "#{locale}-#{suffix.upcase}" if suffix
136
+ public_send("slug#{$3}", *arguments, **options, locale: locale.to_sym)
137
+ else
138
+ super(method_name, *arguments, &block)
139
+ end
140
+ end
141
+
142
+ define_method :respond_to_missing? do |method_name, include_private = false|
143
+ (method_name =~ method_name_regex) || super(method_name, include_private)
144
+ end
145
+ end
84
146
  end
85
147
  end
86
148
  end
@@ -2,8 +2,6 @@ module ActivePermalink
2
2
  class Permalink < ActiveRecord::Base
3
3
  self.table_name = 'permalinks'
4
4
 
5
- default_scope { order created_at: :desc }
6
-
7
5
  scope :global, -> { where scope: :global }
8
6
  scope :active, -> { where active: true }
9
7
  scope :inactive, -> { where active: false }
@@ -3,21 +3,42 @@ module ActivePermalink
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  included do
6
- before_validation on: :create do
7
- self.slug = slug
6
+ include ActiveDelegate
7
+
8
+ delegate_attribute :slug, :string,
9
+ to: :active_permalink
10
+
11
+ before_validation :slug_should_generate!,
12
+ on: [:create, :update],
13
+ if: :slug_needs_generate?
14
+
15
+ def slug=(value)
16
+ _generate_permalink_slug(value)
8
17
  end
9
18
 
10
- after_update do
11
- permalinks.reload
19
+ def old_slugs
20
+ @old_slugs ||= old_permalinks.pluck(:slug)
12
21
  end
13
22
 
14
- def slug=(value)
15
- return if value.nil? && !new_record?
23
+ def slug_should_generate?
24
+ @slug_should_generate == true
25
+ end
26
+
27
+ private
16
28
 
17
- generator = Generator.new(self, permalink_options)
18
- generator.generate(value)
29
+ def slug_needs_generate?
30
+ !slug? && send(:"#{permalink_options[:field]}_changed?")
31
+ end
32
+
33
+ def slug_should_generate!
34
+ @slug_should_generate = true
35
+ _generate_permalink_slug(self[:slug])
36
+ ensure
37
+ @slug_should_generate = false
38
+ end
19
39
 
20
- self.permalinks = generator.permalinks
40
+ def _generate_permalink_slug(value)
41
+ Generator.generate(self, value)
21
42
  end
22
43
  end
23
44
  end
@@ -36,10 +36,6 @@ module ActivePermalink
36
36
  found_by_slug? && found_by_slug != slug
37
37
  end
38
38
 
39
- def old_slugs
40
- @old_slugs ||= old_permalinks.pluck(:slug)
41
- end
42
-
43
39
  class PermalinkLocator
44
40
  attr_reader :model, :options
45
41
 
@@ -1,3 +1,3 @@
1
1
  module ActivePermalink
2
- VERSION = '0.3.2'
2
+ VERSION = '0.5.2'
3
3
  end
@@ -13,6 +13,10 @@ module ActivePermalink
13
13
  migration_template 'migration.rb', 'db/migrate/create_permalinks.rb'
14
14
  end
15
15
 
16
+ def create_config_file
17
+ template 'initializer.rb', 'config/initializers/active_permalink.rb'
18
+ end
19
+
16
20
  def self.next_migration_number(dirname)
17
21
  ::ActiveRecord::Generators::Base.next_migration_number(dirname)
18
22
  end
@@ -0,0 +1,8 @@
1
+ ActivePermalink.setup do |config|
2
+ # config.class_name = 'ActivePermalink::Permalink'
3
+ # config.querying = true
4
+ # config.localized = false
5
+ # config.locale_column = :locale
6
+ # config.locale_accessors = true
7
+ # config.fallbacks = false
8
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_permalink
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonian Guveli
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-02-18 00:00:00.000000000 Z
11
+ date: 2020-12-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -45,19 +45,19 @@ dependencies:
45
45
  - !ruby/object:Gem::Version
46
46
  version: '1.0'
47
47
  - !ruby/object:Gem::Dependency
48
- name: stringex
48
+ name: any_ascii
49
49
  requirement: !ruby/object:Gem::Requirement
50
50
  requirements:
51
51
  - - "~>"
52
52
  - !ruby/object:Gem::Version
53
- version: '2.0'
53
+ version: '0.1'
54
54
  type: :runtime
55
55
  prerelease: false
56
56
  version_requirements: !ruby/object:Gem::Requirement
57
57
  requirements:
58
58
  - - "~>"
59
59
  - !ruby/object:Gem::Version
60
- version: '2.0'
60
+ version: '0.1'
61
61
  - !ruby/object:Gem::Dependency
62
62
  name: bundler
63
63
  requirement: !ruby/object:Gem::Requirement
@@ -78,14 +78,14 @@ dependencies:
78
78
  requirements:
79
79
  - - "~>"
80
80
  - !ruby/object:Gem::Version
81
- version: '10.0'
81
+ version: '13.0'
82
82
  type: :development
83
83
  prerelease: false
84
84
  version_requirements: !ruby/object:Gem::Requirement
85
85
  requirements:
86
86
  - - "~>"
87
87
  - !ruby/object:Gem::Version
88
- version: '10.0'
88
+ version: '13.0'
89
89
  - !ruby/object:Gem::Dependency
90
90
  name: minitest
91
91
  requirement: !ruby/object:Gem::Requirement
@@ -112,6 +112,7 @@ files:
112
112
  - README.md
113
113
  - Rakefile
114
114
  - lib/active_permalink.rb
115
+ - lib/active_permalink/config.rb
115
116
  - lib/active_permalink/generator.rb
116
117
  - lib/active_permalink/loader.rb
117
118
  - lib/active_permalink/localizer.rb
@@ -120,12 +121,13 @@ files:
120
121
  - lib/active_permalink/querying.rb
121
122
  - lib/active_permalink/version.rb
122
123
  - lib/generators/active_permalink/install_generator.rb
124
+ - lib/generators/active_permalink/templates/initializer.rb
123
125
  - lib/generators/active_permalink/templates/migration.rb
124
126
  homepage: https://github.com/hardpixel/active-permalink
125
127
  licenses:
126
128
  - MIT
127
129
  metadata: {}
128
- post_install_message:
130
+ post_install_message:
129
131
  rdoc_options: []
130
132
  require_paths:
131
133
  - lib
@@ -140,8 +142,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
140
142
  - !ruby/object:Gem::Version
141
143
  version: '0'
142
144
  requirements: []
143
- rubygems_version: 3.0.6
144
- signing_key:
145
+ rubygems_version: 3.1.4
146
+ signing_key:
145
147
  specification_version: 4
146
148
  summary: Add permalinks to ActiveRecord models
147
149
  test_files: []