active_permalink 0.2.0 → 0.3.0

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: 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