active_permalink 0.3.2 → 0.5.2

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