active_permalink 0.2.0 → 0.3.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e97292918ed86b8b4f35528c3ad2af732fce12271b76b13847700fbfc82b8fdf
4
- data.tar.gz: 899e0657462da00c685560076368fc988f607d2c7d77e3f1e01cc692803e4f34
3
+ metadata.gz: b16f6386aa52361de778a4b894b3479fd489e44a4144e116076c73f7b21cce68
4
+ data.tar.gz: a43e93473637eded10cb189a4ee2a9829579bc11b32b749ac470adf66558eb5a
5
5
  SHA512:
6
- metadata.gz: 821a04f9468ecdde47b33485745b44229b3fde119765e35cbb5520db3170e67e7cdf31d600f7c62367de0476d2201bb991632a571f9a6685387d80366884ffd5
7
- data.tar.gz: a223244a92a8dddc3525e1b763dbbafe07b122ea9d63e713ff80c6d02d2a2b4fe03e825704068bad3b1796fcd70410dfae40bb5de286a0940108f80b8735f798
6
+ metadata.gz: 8db0d6f4e65f9fe4dc46e36f2555371040a7851d95a39b860e3f5fef42080dda00bd576048b80fc4a7ec77516e28869987b800c8db99c9d13c720d949a5818b1
7
+ data.tar.gz: 89a4f9e787ac3dc150204dceac4cb88836c92bc736502567c974842e98ef9c6199d1ac6d7e90d64b53e2da692e1922ec3ce7444bf3d0ddccab44d9351a038c4c
@@ -8,6 +8,8 @@ module ActivePermalink
8
8
 
9
9
  autoload :Permalink
10
10
  autoload :Generator
11
+ autoload :Persistence
12
+ autoload :Localizer
11
13
  autoload :Querying
12
14
  autoload :Loader
13
15
  end
@@ -1,60 +1,107 @@
1
1
  module ActivePermalink
2
2
  class Generator
3
- def initialize(record, field, old_value, new_value, options = {})
4
- @record = record
5
- @field = field
6
- @old_value = old_value
3
+ def initialize(record, options = {})
4
+ @record = record
5
+ @options = options
6
+ @field = options[:field]
7
+ @scope = options.fetch(:scope, :global)
8
+ end
9
+
10
+ def generate(new_value)
7
11
  @new_value = new_value
8
- @options = options
9
- @scope = options.fetch :scope, :global
12
+ return unless changed?
13
+
14
+ deactivate_active_permalink
15
+ assign_active_permalink
10
16
  end
11
17
 
12
- def slug_candidates
13
- @new_value.present? ? @new_value : @record.send(@field)
18
+ def permalinks
19
+ @permalinks ||= @record.permalinks
14
20
  end
15
21
 
16
- def slug_from_column
17
- @column_slug ||= slug_candidates.to_s.to_url
22
+ private
23
+
24
+ def locale
25
+ I18n.locale.to_s
18
26
  end
19
27
 
20
- def scope_unique_slug
21
- unique = slug_from_column
22
- index = 1
28
+ def changed?
29
+ @new_value.blank? || @new_value != active_permalink.try(:slug)
30
+ end
23
31
 
24
- while not Permalink.where(scope: @scope, slug: unique).count.zero?
25
- unique = "#{slug_from_column}-#{(index += 1)}"
26
- end
32
+ def localized?
33
+ @options[:localized].present?
34
+ end
27
35
 
28
- unique
36
+ def locale_column
37
+ @options[:locale_column]
29
38
  end
30
39
 
31
- def deactivate_old_permalink
32
- return if @record.active_permalink.new_record?
40
+ def exists?(slug)
41
+ params = localize(scope: @scope, slug: slug)
42
+ Permalink.where(params).count.zero?
43
+ end
44
+
45
+ def localize(**params)
46
+ params[locale_column] = locale if localized?
47
+ params
48
+ end
49
+
50
+ def available_permalinks
51
+ if localized?
52
+ permalinks.select { |item| item.send(locale_column) == locale }
53
+ else
54
+ permalinks
55
+ end
56
+ end
33
57
 
34
- parameters = { slug: @old_value, active: true }
35
- permalink = @record.old_permalinks.rewhere(parameters).first
58
+ def active_permalink
59
+ available_permalinks.find { |item| item.active == true }
60
+ end
36
61
 
37
- permalink.update_column(:active, false) unless permalink.nil?
62
+ def build_permalink
63
+ params = localize(scope: @scope, active: true)
64
+ active_permalink || permalinks.build(params)
38
65
  end
39
66
 
40
- def reassign_old_permalink
41
- permalink = @record.old_permalinks.find_by(slug: slug_from_column)
42
- return if permalink.nil?
67
+ def old_permalink
68
+ params = localize(slug: slug_from_column)
43
69
 
44
- permalink.update(active: true)
45
- permalink
70
+ available_permalinks.find do |item|
71
+ params.all? { |key, value| item.send(key) == value }
72
+ end
46
73
  end
47
74
 
48
- def build_new_permalink
49
- parameters = { slug: scope_unique_slug, scope: @scope, active: true }
50
- @record.build_active_permalink(parameters)
75
+ def slug_from_column
76
+ @slug_from_column ||= begin
77
+ value = @new_value.presence || @record.send(@field)
78
+ value.to_s.to_url
79
+ end
80
+ end
81
+
82
+ def scope_unique_slug
83
+ unique = slug_from_column
84
+ index = 1
85
+
86
+ while not exists?(unique)
87
+ unique = "#{slug_from_column}-#{(index += 1)}"
88
+ end
89
+
90
+ unique
51
91
  end
52
92
 
53
- def new_permalink
54
- deactivate_old_permalink
55
- @record.reload_active_permalink
93
+ def deactivate_active_permalink
94
+ available_permalinks.each do |item|
95
+ item.active = false unless item.new_record?
96
+ end
97
+ end
56
98
 
57
- reassign_old_permalink || build_new_permalink
99
+ def assign_active_permalink
100
+ if old_permalink
101
+ old_permalink.write_attribute(:active, true)
102
+ else
103
+ build_permalink.write_attribute(:slug, scope_unique_slug)
104
+ end
58
105
  end
59
106
  end
60
107
  end
@@ -3,23 +3,43 @@ module ActivePermalink
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  class_methods do
6
- def has_permalink(field, options = {})
6
+ def has_permalink(field, localized: false, locale_column: :locale, **options)
7
7
  include ActiveDelegate
8
- include Querying
9
8
 
10
- assoc_opts = { as: :sluggable, class_name: 'ActivePermalink::Permalink', dependent: :destroy }
11
- has_many :permalinks, assoc_opts
12
- has_many :old_permalinks, -> { where active: false }, assoc_opts
9
+ class_attribute :permalink_options
10
+
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
18
+ has_many :permalinks,
19
+ dependent: :destroy,
20
+ autosave: true
21
+
22
+ has_many :old_permalinks,
23
+ -> { inactive }
13
24
 
14
- has_one :active_permalink, -> { where active: true }, assoc_opts.merge(autosave: true)
15
- delegate_attribute :slug, :string, to: :active_permalink
25
+ if localized
26
+ has_many :active_permalinks,
27
+ -> { active }
16
28
 
17
- before_save do |record|
18
- if slug.blank? or slug_changed?
19
- premalink_generator = Generator.new(record, field, slug_was, slug, options)
20
- self.active_permalink = premalink_generator.new_permalink
29
+ has_one :active_permalink,
30
+ -> { active.where(locale_column => I18n.locale) }
31
+ else
32
+ has_one :active_permalink,
33
+ -> { active }
21
34
  end
22
35
  end
36
+
37
+ delegate_attribute :slug, :string,
38
+ to: :active_permalink
39
+
40
+ include Persistence
41
+ include Querying
42
+ include Localizer if localized
23
43
  end
24
44
  end
25
45
  end
@@ -0,0 +1,86 @@
1
+ module ActivePermalink
2
+ module Localizer
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ def permalink_reader
7
+ PermalinkReader.new(permalinks, permalink_options)
8
+ end
9
+
10
+ def slug?
11
+ permalink_reader.exists?
12
+ end
13
+
14
+ def slug
15
+ permalink_reader.value
16
+ end
17
+
18
+ I18n.available_locales.each do |locale|
19
+ define_method(:"slug_#{locale}?") do
20
+ I18n.with_locale(locale) { slug? }
21
+ end
22
+
23
+ define_method(:"slug_#{locale}") do
24
+ I18n.with_locale(locale) { slug }
25
+ end
26
+
27
+ define_method(:"slug_#{locale}=") do |value|
28
+ I18n.with_locale(locale) { send(:slug=, value) }
29
+ end
30
+ end
31
+ end
32
+
33
+ class PermalinkReader
34
+ attr_reader :permalinks, :options
35
+
36
+ def initialize(permalinks, options)
37
+ @permalinks = permalinks
38
+ @options = options
39
+ end
40
+
41
+ def fallbacks?
42
+ options[:fallbacks].present?
43
+ end
44
+
45
+ def exists?
46
+ find_permalink(I18n.locale).present?
47
+ end
48
+
49
+ def value
50
+ find_slug(I18n.locale)
51
+ end
52
+
53
+ private
54
+
55
+ def locale_column
56
+ @options[:locale_column]
57
+ end
58
+
59
+ def find_permalink(locale)
60
+ permalinks.find do |permalink|
61
+ permalink.send(locale_column) == locale.to_s
62
+ end
63
+ end
64
+
65
+ 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
76
+ end
77
+
78
+ def find_slug(locale)
79
+ permalink = find_permalink(locale)
80
+ permalink = find_fallback(locale) if permalink.blank?
81
+
82
+ permalink.try(:slug)
83
+ end
84
+ end
85
+ end
86
+ end
@@ -4,7 +4,9 @@ module ActivePermalink
4
4
 
5
5
  default_scope { order created_at: :desc }
6
6
 
7
- scope :global, -> { where scope: :global }
7
+ scope :global, -> { where scope: :global }
8
+ scope :active, -> { where active: true }
9
+ scope :inactive, -> { where active: false }
8
10
 
9
11
  belongs_to :sluggable, polymorphic: true, optional: true
10
12
  end
@@ -0,0 +1,22 @@
1
+ module ActivePermalink
2
+ module Persistence
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ before_validation do
7
+ self.slug = self[:slug]
8
+ end
9
+
10
+ after_update do
11
+ permalinks.reload
12
+ end
13
+
14
+ def slug=(value)
15
+ generator = Generator.new(self, permalink_options)
16
+ generator.generate(value)
17
+
18
+ self.permalinks = generator.permalinks
19
+ end
20
+ end
21
+ end
22
+ end
@@ -3,25 +3,20 @@ module ActivePermalink
3
3
  extend ActiveSupport::Concern
4
4
 
5
5
  class_methods do
6
- def find_by_slug(value)
7
- _find_by_permalink_slug(value)
6
+ def permalink_locator
7
+ PermalinkLocator.new(self, permalink_options)
8
8
  end
9
9
 
10
- def find_by_slug!(value)
11
- _find_by_permalink_slug(value, true)
10
+ def with_slug(*args)
11
+ permalink_locator.scope(*args)
12
12
  end
13
13
 
14
- private
15
-
16
- def _find_by_permalink_slug(value, raise_error = false)
17
- method = raise_error ? :find_by! : :find_by
18
- record = includes(:permalinks).send(method, permalinks: { slug: value })
19
-
20
- unless record.nil?
21
- record.found_by_slug = value
22
- end
14
+ def find_by_slug(*args)
15
+ permalink_locator.locate(*args)
16
+ end
23
17
 
24
- record
18
+ def find_by_slug!(*args)
19
+ permalink_locator.locate!(*args)
25
20
  end
26
21
  end
27
22
 
@@ -34,7 +29,7 @@ module ActivePermalink
34
29
  end
35
30
 
36
31
  def found_by_slug?
37
- !found_by_slug.nil?
32
+ found_by_slug.present?
38
33
  end
39
34
 
40
35
  def needs_redirect?
@@ -44,5 +39,50 @@ module ActivePermalink
44
39
  def old_slugs
45
40
  @old_slugs ||= old_permalinks.pluck(:slug)
46
41
  end
42
+
43
+ class PermalinkLocator
44
+ attr_reader :model, :options
45
+
46
+ def initialize(model, options)
47
+ @model = model
48
+ @options = options
49
+ end
50
+
51
+ def scope(value, locale: nil)
52
+ params = localize(slug: value, locale: locale)
53
+ model.joins(:permalinks).where(permalinks: params)
54
+ end
55
+
56
+ def locate(*args)
57
+ find_record(:find_by, *args)
58
+ end
59
+
60
+ def locate!(*args)
61
+ find_record(:find_by!, *args)
62
+ end
63
+
64
+ private
65
+
66
+ def localized?
67
+ options[:localized].present?
68
+ end
69
+
70
+ def locale_column
71
+ options[:locale_column]
72
+ end
73
+
74
+ def localize(locale: nil, **params)
75
+ params[locale_column] = (locale || I18n.locale) if localized?
76
+ params
77
+ end
78
+
79
+ def find_record(method, value, locale: nil)
80
+ params = localize(slug: value, locale: locale)
81
+ record = model.joins(:permalinks).send(method, permalinks: params)
82
+
83
+ record.found_by_slug = value if record.present?
84
+ record
85
+ end
86
+ end
47
87
  end
48
88
  end
@@ -1,3 +1,3 @@
1
1
  module ActivePermalink
2
- VERSION = '0.2.0'
2
+ VERSION = '0.3.0'
3
3
  end
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: active_permalink
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jonian Guveli
8
8
  autorequire:
9
- bindir: exe
9
+ bindir: bin
10
10
  cert_chain: []
11
- date: 2019-01-06 00:00:00.000000000 Z
11
+ date: 2019-10-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
19
  version: '5.0'
20
+ - - "<"
21
+ - !ruby/object:Gem::Version
22
+ version: '7.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
25
28
  - !ruby/object:Gem::Version
26
29
  version: '5.0'
30
+ - - "<"
31
+ - !ruby/object:Gem::Version
32
+ version: '7.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: active_delegate
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -58,14 +64,14 @@ dependencies:
58
64
  requirements:
59
65
  - - "~>"
60
66
  - !ruby/object:Gem::Version
61
- version: '1.14'
67
+ version: '2.0'
62
68
  type: :development
63
69
  prerelease: false
64
70
  version_requirements: !ruby/object:Gem::Requirement
65
71
  requirements:
66
72
  - - "~>"
67
73
  - !ruby/object:Gem::Version
68
- version: '1.14'
74
+ version: '2.0'
69
75
  - !ruby/object:Gem::Dependency
70
76
  name: rake
71
77
  requirement: !ruby/object:Gem::Requirement
@@ -108,7 +114,9 @@ files:
108
114
  - lib/active_permalink.rb
109
115
  - lib/active_permalink/generator.rb
110
116
  - lib/active_permalink/loader.rb
117
+ - lib/active_permalink/localizer.rb
111
118
  - lib/active_permalink/permalink.rb
119
+ - lib/active_permalink/persistence.rb
112
120
  - lib/active_permalink/querying.rb
113
121
  - lib/active_permalink/version.rb
114
122
  - lib/generators/active_permalink/install_generator.rb
@@ -132,8 +140,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
132
140
  - !ruby/object:Gem::Version
133
141
  version: '0'
134
142
  requirements: []
135
- rubyforge_project:
136
- rubygems_version: 2.7.7
143
+ rubygems_version: 3.0.6
137
144
  signing_key:
138
145
  specification_version: 4
139
146
  summary: Add permalinks to ActiveRecord models