dibbler 1.0.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +73 -0
- data/app/models/dibbler/slug.rb +17 -0
- data/config/locales/cs.yml +18 -0
- data/config/locales/en.yml +18 -0
- data/config/routes.rb +13 -0
- data/db/migrate/20150721151036_create_slugs.rb +11 -0
- data/lib/dibbler.rb +199 -0
- data/lib/dibbler/engine.rb +17 -0
- data/lib/dibbler/helpers/url_helper.rb +26 -0
- data/lib/dibbler/middlewares/locale.rb +62 -0
- data/lib/dibbler/middlewares/slug.rb +49 -0
- data/lib/dibbler/models/hierarchical_slug_generator.rb +148 -0
- data/lib/dibbler/models/slug.rb +414 -0
- data/lib/dibbler/models/slug_generator.rb +111 -0
- data/lib/dibbler/railtie.rb +18 -0
- data/lib/dibbler/utils/enum.rb +133 -0
- metadata +75 -0
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# *****************************************************************************
|
|
2
|
+
# * Copyright (c) 2019 Matěj Outlý
|
|
3
|
+
# *****************************************************************************
|
|
4
|
+
# *
|
|
5
|
+
# * Request translation based on DB slugs
|
|
6
|
+
# *
|
|
7
|
+
# * Author: Matěj Outlý
|
|
8
|
+
# * Date : 21. 7. 2015
|
|
9
|
+
# *
|
|
10
|
+
# *****************************************************************************
|
|
11
|
+
|
|
12
|
+
module Dibbler
|
|
13
|
+
module Middlewares
|
|
14
|
+
class Slug
|
|
15
|
+
|
|
16
|
+
def initialize(app)
|
|
17
|
+
@app = app
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def call(env)
|
|
21
|
+
if filter(env)
|
|
22
|
+
@app.call(env)
|
|
23
|
+
else
|
|
24
|
+
|
|
25
|
+
# Match locale from path
|
|
26
|
+
locale, translation = Dibbler.disassemble(env["PATH_INFO"])
|
|
27
|
+
|
|
28
|
+
# Translate to original and modify request
|
|
29
|
+
original = Dibbler.slug_model.translation_to_original(I18n.locale, translation) # Previously matched locale used
|
|
30
|
+
unless original.nil?
|
|
31
|
+
original = Dibbler.assemble(locale, original)
|
|
32
|
+
env["REQUEST_PATH"] = original
|
|
33
|
+
env["PATH_INFO"] = original
|
|
34
|
+
env["REQUEST_URI"] = original + "?" + env["QUERY_STRING"]
|
|
35
|
+
end
|
|
36
|
+
@app.call(env)
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
protected
|
|
41
|
+
|
|
42
|
+
def filter(env)
|
|
43
|
+
return true if env["PATH_INFO"].start_with?("/assets/")
|
|
44
|
+
false
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# *****************************************************************************
|
|
2
|
+
# * Copyright (c) 2019 Matěj Outlý
|
|
3
|
+
# *****************************************************************************
|
|
4
|
+
# *
|
|
5
|
+
# * Hierarchical slug generator
|
|
6
|
+
# *
|
|
7
|
+
# * Author: Matěj Outlý
|
|
8
|
+
# * Date : 21. 7. 2015
|
|
9
|
+
# *
|
|
10
|
+
# *****************************************************************************
|
|
11
|
+
|
|
12
|
+
module Dibbler
|
|
13
|
+
module Models
|
|
14
|
+
module HierarchicalSlugGenerator
|
|
15
|
+
extend ActiveSupport::Concern
|
|
16
|
+
|
|
17
|
+
included do
|
|
18
|
+
|
|
19
|
+
after_commit :generate_slugs
|
|
20
|
+
before_destroy :destroy_slugs_before, prepend: true
|
|
21
|
+
after_destroy :destroy_slugs_after
|
|
22
|
+
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
module ClassMethods
|
|
26
|
+
|
|
27
|
+
def generate_slugs(options = {})
|
|
28
|
+
self.roots.each do |item|
|
|
29
|
+
item.generate_slugs(options)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def disable_slug_generator
|
|
36
|
+
@disable_slug_generator = true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def enable_slug_generator
|
|
40
|
+
@disable_slug_generator = false
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# *************************************************************
|
|
44
|
+
# Hooks
|
|
45
|
+
# *************************************************************
|
|
46
|
+
|
|
47
|
+
def generate_slugs(options = {})
|
|
48
|
+
return if @disable_slug_generator
|
|
49
|
+
ActiveRecord::Base.transaction do
|
|
50
|
+
|
|
51
|
+
# Generate slug in this model
|
|
52
|
+
unless Dibbler.slug_model.nil?
|
|
53
|
+
I18n.available_locales.each do |locale|
|
|
54
|
+
self._destroy_slug_was(Dibbler.slug_model, locale)
|
|
55
|
+
self._generate_slug(Dibbler.slug_model, locale)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Propagate to other models
|
|
62
|
+
if options[:disable_propagation] != true
|
|
63
|
+
|
|
64
|
+
# Propagate to parent
|
|
65
|
+
self.parent.generate_slugs(disable_propagation: true) if self.parent
|
|
66
|
+
|
|
67
|
+
# Propagate to descendants
|
|
68
|
+
self.descendants.each do |descendant|
|
|
69
|
+
descendant.generate_slugs(disable_propagation: true)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def destroy_slugs_before(options = {})
|
|
77
|
+
|
|
78
|
+
# Destroy slug of this model
|
|
79
|
+
unless Dibbler.slug_model.nil?
|
|
80
|
+
I18n.available_locales.each do |locale|
|
|
81
|
+
self._destroy_slug(Dibbler.slug_model, locale)
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
# Propagate to other models
|
|
86
|
+
if options[:disable_propagation] != true
|
|
87
|
+
|
|
88
|
+
# Propagate to descendants
|
|
89
|
+
self.descendants.each do |descendant|
|
|
90
|
+
descendant.destroy_slugs_before(disable_propagation: true)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def destroy_slugs_after(options = {})
|
|
98
|
+
|
|
99
|
+
# Propagate to other models
|
|
100
|
+
if options[:disable_propagation] != true
|
|
101
|
+
|
|
102
|
+
# Propagate to parent
|
|
103
|
+
self.parent.generate_slugs(disable_propagation: true) if self.parent
|
|
104
|
+
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
def url_original
|
|
110
|
+
if @url_original.nil?
|
|
111
|
+
@url_original = self._url_original
|
|
112
|
+
end
|
|
113
|
+
@url_original
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def compose_slug_translation(locale)
|
|
117
|
+
self._compose_slug_translation(locale)
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
protected
|
|
121
|
+
|
|
122
|
+
# *************************************************************
|
|
123
|
+
# Callbacks to be defined in application
|
|
124
|
+
# *************************************************************
|
|
125
|
+
|
|
126
|
+
def _url_original
|
|
127
|
+
raise "To be defined in application."
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def _compose_slug_translation(locale)
|
|
131
|
+
raise "To be defined in application."
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def _generate_slug(slug_model, locale)
|
|
135
|
+
raise "To be defined in application."
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def _destroy_slug(slug_model, locale)
|
|
139
|
+
raise "To be defined in application."
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def _destroy_slug_was(slug_model, locale)
|
|
143
|
+
raise "To be defined in application."
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
end
|
|
147
|
+
end
|
|
148
|
+
end
|
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
# *****************************************************************************
|
|
2
|
+
# * Copyright (c) 2019 Matěj Outlý
|
|
3
|
+
# *****************************************************************************
|
|
4
|
+
# *
|
|
5
|
+
# * Slug
|
|
6
|
+
# *
|
|
7
|
+
# * Author: Matěj Outlý
|
|
8
|
+
# * Date : 21. 7. 2015
|
|
9
|
+
# *
|
|
10
|
+
# *****************************************************************************
|
|
11
|
+
|
|
12
|
+
module Dibbler
|
|
13
|
+
module Models
|
|
14
|
+
module Slug
|
|
15
|
+
extend ActiveSupport::Concern
|
|
16
|
+
|
|
17
|
+
module ClassMethods
|
|
18
|
+
|
|
19
|
+
# Clear slug cache. Must be done if data changed in DB
|
|
20
|
+
def clear_cache
|
|
21
|
+
@o2t = nil
|
|
22
|
+
@t2o = nil
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# Load specific locale to cache
|
|
26
|
+
def load_cache(locale)
|
|
27
|
+
|
|
28
|
+
# Initialize cache structures
|
|
29
|
+
@o2t = {} if @o2t.nil?
|
|
30
|
+
@t2o = {} if @t2o.nil?
|
|
31
|
+
|
|
32
|
+
# Fill cache if empty
|
|
33
|
+
if @o2t[locale.to_sym].nil? || @t2o[locale.to_sym].nil?
|
|
34
|
+
|
|
35
|
+
# Preset
|
|
36
|
+
@o2t[locale.to_sym] = {}
|
|
37
|
+
@t2o[locale.to_sym] = {}
|
|
38
|
+
|
|
39
|
+
# Static data from config
|
|
40
|
+
if Dibbler.static_slugs
|
|
41
|
+
Dibbler.static_slugs.each do |item|
|
|
42
|
+
if item[:locale].to_s == locale.to_s
|
|
43
|
+
translation_as_key = item[:translation]
|
|
44
|
+
translation_as_key = translation_as_key.downcase if Dibbler.downcase_translations == true
|
|
45
|
+
if Dibbler.use_filter
|
|
46
|
+
if Dibbler.current_app_filter.to_s == item[:filter] # Slug belongs to current application
|
|
47
|
+
@o2t[locale.to_sym][item[:original]] = item[:translation]
|
|
48
|
+
@t2o[locale.to_sym][translation_as_key] = item[:original]
|
|
49
|
+
elsif !item[:filter].blank? # Slug belongs to other application
|
|
50
|
+
url = Dibbler.available_filter_urls[item[:filter].to_sym]
|
|
51
|
+
@o2t[locale.to_sym][item[:original]] = url.trim("/") + item[:translation] unless url.blank?
|
|
52
|
+
end
|
|
53
|
+
else
|
|
54
|
+
@o2t[locale.to_sym][item[:original]] = item[:translation]
|
|
55
|
+
@t2o[locale.to_sym][translation_as_key] = item[:original]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# Dynamic data from DB
|
|
62
|
+
data = where(locale: locale.to_s)
|
|
63
|
+
data.each do |item|
|
|
64
|
+
translation_as_key = item.translation
|
|
65
|
+
translation_as_key = translation_as_key.downcase if Dibbler.downcase_translations == true
|
|
66
|
+
if Dibbler.use_filter
|
|
67
|
+
if Dibbler.current_app_filter.to_s == item.filter # Slug belongs to current application
|
|
68
|
+
@o2t[locale.to_sym][item.original] = item.translation
|
|
69
|
+
@t2o[locale.to_sym][translation_as_key] = item.original
|
|
70
|
+
elsif !item.filter.blank? # Slug belongs to other application
|
|
71
|
+
url = Dibbler.available_filter_urls[item.filter.to_sym]
|
|
72
|
+
@o2t[locale.to_sym][item.original] = url.trim("/") + item.translation unless url.blank?
|
|
73
|
+
end
|
|
74
|
+
else
|
|
75
|
+
@o2t[locale.to_sym][item.original] = item.translation
|
|
76
|
+
@t2o[locale.to_sym][translation_as_key] = item.original
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
# Get translation according to original
|
|
85
|
+
def original_to_translation(locale, original)
|
|
86
|
+
return nil if original.nil?
|
|
87
|
+
load_cache(locale)
|
|
88
|
+
|
|
89
|
+
# First priority translation (without IDs)
|
|
90
|
+
result = @o2t[locale.to_sym][original.to_s]
|
|
91
|
+
if result.nil?
|
|
92
|
+
|
|
93
|
+
# Ensure single "/" on right
|
|
94
|
+
original = original.rtrim("/") + "/"
|
|
95
|
+
|
|
96
|
+
# Create array of all matched IDs alongside with string ":id" (i.e. [["1", ":id"], ["2", ":id"]])
|
|
97
|
+
# Substitute all numeric IDs in original to string ":id"
|
|
98
|
+
matched_ids = []
|
|
99
|
+
product_1 = []
|
|
100
|
+
original = original.gsub(/\/[0-9]+\//) do |matched|
|
|
101
|
+
matched_id = matched[1..-2]
|
|
102
|
+
matched_ids << matched_id
|
|
103
|
+
product_1 << [matched_id, ":id"]
|
|
104
|
+
"/:id/"
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
unless product_1.empty?
|
|
108
|
+
|
|
109
|
+
# Create product of matched IDs (i.e. [["1", "2"], ["1", ":id"], [":id", "2"], [":id", ":id"]])
|
|
110
|
+
product_2 = product_1.first.product(*product_1[1..-1])
|
|
111
|
+
|
|
112
|
+
# Try to find some result for all combinations (except first one, which is already tried and failed)
|
|
113
|
+
result_ids = nil
|
|
114
|
+
product_2[1..-1].each do |combined_ids|
|
|
115
|
+
|
|
116
|
+
# IDs missing in this combination
|
|
117
|
+
result_ids = []
|
|
118
|
+
|
|
119
|
+
# Generate original according to current combination (i.e. "/nodes/1/photos/:id" or "/nodes/:id/photos/:id")
|
|
120
|
+
index = 0
|
|
121
|
+
product_original = original.gsub(/\/:id\//) do
|
|
122
|
+
result_ids << matched_ids[index] if combined_ids.first == ":id"
|
|
123
|
+
index += 1
|
|
124
|
+
"/#{combined_ids.shift.to_s}/"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
# Remove "/" on right
|
|
128
|
+
product_original = product_original.rtrim("/")
|
|
129
|
+
|
|
130
|
+
# Try to translate current combination and break if match found
|
|
131
|
+
result = @o2t[locale.to_sym][product_original.to_s]
|
|
132
|
+
break unless result.nil?
|
|
133
|
+
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
# Correct result if any
|
|
137
|
+
unless result.nil?
|
|
138
|
+
|
|
139
|
+
# Ensure single "/" on right
|
|
140
|
+
result = result.rtrim("/") + "/"
|
|
141
|
+
|
|
142
|
+
# Substitute :id to numeric IDS matched from translation
|
|
143
|
+
result = result.gsub(/\/:id\//) do
|
|
144
|
+
"/#{result_ids.shift.to_s}/"
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Remove "/" on right
|
|
148
|
+
result = result.rtrim("/")
|
|
149
|
+
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
result
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
# Get original according to translation
|
|
160
|
+
def translation_to_original(locale, translation)
|
|
161
|
+
return nil if translation.nil?
|
|
162
|
+
load_cache(locale)
|
|
163
|
+
|
|
164
|
+
# Downcase if necessary
|
|
165
|
+
translation = translation.downcase if Dibbler.downcase_translations
|
|
166
|
+
|
|
167
|
+
# First priority translation (without IDs)
|
|
168
|
+
result = @t2o[locale.to_sym][translation.to_s]
|
|
169
|
+
if result.nil?
|
|
170
|
+
|
|
171
|
+
# Ensure single "/" on right
|
|
172
|
+
translation = translation.rtrim("/") + "/"
|
|
173
|
+
|
|
174
|
+
# Substitute numeric parts to :id
|
|
175
|
+
matched_ids = []
|
|
176
|
+
translation = translation.gsub(/\/[0-9]+\//) do |matched|
|
|
177
|
+
matched_ids << matched[1..-2]
|
|
178
|
+
"/:id/"
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Remove "/" on right
|
|
182
|
+
translation = translation.rtrim("/")
|
|
183
|
+
|
|
184
|
+
# Second priority translation (width IDs)
|
|
185
|
+
result = @t2o[locale.to_sym][translation.to_s]
|
|
186
|
+
unless result.nil?
|
|
187
|
+
|
|
188
|
+
# Ensure single "/" on right
|
|
189
|
+
result = result.rtrim("/") + "/"
|
|
190
|
+
|
|
191
|
+
# Substitute :id to numeric IDS matched from translation
|
|
192
|
+
result = result.gsub(/\/:id\//) do
|
|
193
|
+
"/#{matched_ids.shift.to_s}/"
|
|
194
|
+
end
|
|
195
|
+
|
|
196
|
+
# Remove "/" on right
|
|
197
|
+
result = result.rtrim("/")
|
|
198
|
+
|
|
199
|
+
end
|
|
200
|
+
end
|
|
201
|
+
|
|
202
|
+
result
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
# Add new slug or edit existing
|
|
206
|
+
def add_slug(locale, original, translation, filter = nil, uniquer = "")
|
|
207
|
+
|
|
208
|
+
# Do not process blank
|
|
209
|
+
return if original.blank? # || translation.blank? blank translation means that original translates to root
|
|
210
|
+
|
|
211
|
+
# Prepare
|
|
212
|
+
locale = locale.to_s
|
|
213
|
+
original = "/" + original.to_s.trim("/")
|
|
214
|
+
translation = "/" + translation.to_s.trim("/")
|
|
215
|
+
not_uniq_translation = "/" + translation.gsub(":uniquer", "").to_s.trim("/")
|
|
216
|
+
if uniquer
|
|
217
|
+
uniq_translation = "/" + translation.gsub(":uniquer", uniquer).to_s.trim("/")
|
|
218
|
+
else
|
|
219
|
+
uniq_translation = not_uniq_translation
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
# Root is not slugged
|
|
223
|
+
return if original == "/"
|
|
224
|
+
|
|
225
|
+
# Find occupations, if found some, translation must be uniqued with token
|
|
226
|
+
occupations = all
|
|
227
|
+
occupations = occupations.where.not(original: original)
|
|
228
|
+
occupations = occupations.where(locale: locale, translation: not_uniq_translation)
|
|
229
|
+
occupations = occupations.where(filter: filter) if Dibbler.use_filter
|
|
230
|
+
if occupations.count > 0
|
|
231
|
+
translation = uniq_translation
|
|
232
|
+
else
|
|
233
|
+
translation = not_uniq_translation
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
# Try to find existing record
|
|
237
|
+
slug = where(locale: locale, original: original).first
|
|
238
|
+
if slug.nil?
|
|
239
|
+
slug = new
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# TODO duplicate translations
|
|
243
|
+
|
|
244
|
+
# Save
|
|
245
|
+
slug.locale = locale
|
|
246
|
+
slug.filter = filter if Dibbler.use_filter
|
|
247
|
+
slug.original = original
|
|
248
|
+
slug.translation = translation
|
|
249
|
+
slug.save
|
|
250
|
+
|
|
251
|
+
# Clear cache
|
|
252
|
+
clear_cache
|
|
253
|
+
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
# Remove existing slug if exists
|
|
257
|
+
def remove_slug(locale, original)
|
|
258
|
+
|
|
259
|
+
# Prepare
|
|
260
|
+
locale = locale.to_s
|
|
261
|
+
original = "/" + original.to_s.trim("/")
|
|
262
|
+
|
|
263
|
+
# Try to find existing record
|
|
264
|
+
slug = where(locale: locale, original: original).first
|
|
265
|
+
unless slug.nil?
|
|
266
|
+
slug.destroy
|
|
267
|
+
end
|
|
268
|
+
|
|
269
|
+
# Clear cache
|
|
270
|
+
clear_cache
|
|
271
|
+
|
|
272
|
+
end
|
|
273
|
+
|
|
274
|
+
# Compose translation from various models
|
|
275
|
+
# Obsolete, please define own translation composition method
|
|
276
|
+
def compose_translation(locale, models)
|
|
277
|
+
|
|
278
|
+
# Convert to array
|
|
279
|
+
unless models.is_a? Array
|
|
280
|
+
models = [models]
|
|
281
|
+
end
|
|
282
|
+
|
|
283
|
+
# Result
|
|
284
|
+
result = ""
|
|
285
|
+
last_model = nil
|
|
286
|
+
last_model_is_category = false
|
|
287
|
+
|
|
288
|
+
models.each do |section_options|
|
|
289
|
+
|
|
290
|
+
# Input check
|
|
291
|
+
unless section_options.is_a? Hash
|
|
292
|
+
raise "Incorrect input, expecting hash with :label and :models or :model items."
|
|
293
|
+
end
|
|
294
|
+
if section_options[:models].nil? && !section_options[:model].nil?
|
|
295
|
+
section_options[:models] = [section_options[:model]]
|
|
296
|
+
end
|
|
297
|
+
if section_options[:models].nil? || section_options[:label].nil?
|
|
298
|
+
raise "Incorrect input, expecting hash with :label and :models or :model items."
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
# "Is category" option
|
|
302
|
+
last_model_is_category = section_options[:is_category] == true
|
|
303
|
+
|
|
304
|
+
section_options[:models].each do |model|
|
|
305
|
+
|
|
306
|
+
# Get part
|
|
307
|
+
if model.respond_to?("#{section_options[:label].to_s}_#{locale.to_s}".to_sym)
|
|
308
|
+
part = model.send("#{section_options[:label].to_s}_#{locale.to_s}".to_sym)
|
|
309
|
+
elsif model.respond_to?(section_options[:label].to_sym)
|
|
310
|
+
part = model.send(section_options[:label].to_sym)
|
|
311
|
+
else
|
|
312
|
+
part = nil
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
# Add part to result
|
|
316
|
+
result += "/" + part.to_url if part
|
|
317
|
+
|
|
318
|
+
# Save last model
|
|
319
|
+
last_model = model
|
|
320
|
+
|
|
321
|
+
end
|
|
322
|
+
|
|
323
|
+
end
|
|
324
|
+
|
|
325
|
+
# Truncate correctly
|
|
326
|
+
unless result.blank?
|
|
327
|
+
if last_model_is_category || (last_model.hierarchically_ordered? && !last_model.leaf?)
|
|
328
|
+
result += "/"
|
|
329
|
+
else
|
|
330
|
+
#result += ".html"
|
|
331
|
+
result += ""
|
|
332
|
+
end
|
|
333
|
+
end
|
|
334
|
+
|
|
335
|
+
result
|
|
336
|
+
end
|
|
337
|
+
|
|
338
|
+
# *********************************************************
|
|
339
|
+
# Columns
|
|
340
|
+
# *********************************************************
|
|
341
|
+
|
|
342
|
+
def permitted_columns
|
|
343
|
+
[
|
|
344
|
+
:locale,
|
|
345
|
+
:original,
|
|
346
|
+
:translation,
|
|
347
|
+
:filter,
|
|
348
|
+
]
|
|
349
|
+
end
|
|
350
|
+
|
|
351
|
+
def filter_columns
|
|
352
|
+
[
|
|
353
|
+
:locale,
|
|
354
|
+
:original,
|
|
355
|
+
:translation,
|
|
356
|
+
:filter,
|
|
357
|
+
]
|
|
358
|
+
end
|
|
359
|
+
|
|
360
|
+
# *********************************************************
|
|
361
|
+
# Scopes
|
|
362
|
+
# *********************************************************
|
|
363
|
+
|
|
364
|
+
def filter(params = {})
|
|
365
|
+
|
|
366
|
+
# Preset
|
|
367
|
+
result = all
|
|
368
|
+
|
|
369
|
+
# Locale
|
|
370
|
+
unless params[:locale].blank?
|
|
371
|
+
if Dibbler.disable_unaccent
|
|
372
|
+
result = result.where("lower(locale) LIKE ('%' || lower(trim(?)) || '%')", params[:locale].to_s)
|
|
373
|
+
else
|
|
374
|
+
result = result.where("lower(unaccent(locale)) LIKE ('%' || lower(unaccent(trim(?))) || '%')", params[:locale].to_s)
|
|
375
|
+
end
|
|
376
|
+
end
|
|
377
|
+
|
|
378
|
+
# Original
|
|
379
|
+
unless params[:original].blank?
|
|
380
|
+
if Dibbler.disable_unaccent
|
|
381
|
+
result = result.where("lower(original) LIKE ('%' || lower(trim(?)) || '%')", params[:original].to_s)
|
|
382
|
+
else
|
|
383
|
+
result = result.where("lower(unaccent(original)) LIKE ('%' || lower(unaccent(trim(?))) || '%')", params[:original].to_s)
|
|
384
|
+
end
|
|
385
|
+
end
|
|
386
|
+
|
|
387
|
+
# Translation
|
|
388
|
+
unless params[:translation].blank?
|
|
389
|
+
if Dibbler.disable_unaccent
|
|
390
|
+
result = result.where("lower(translation) LIKE ('%' || lower(trim(?)) || '%')", params[:translation].to_s)
|
|
391
|
+
else
|
|
392
|
+
result = result.where("lower(unaccent(translation)) LIKE ('%' || lower(unaccent(trim(?))) || '%')", params[:translation].to_s)
|
|
393
|
+
end
|
|
394
|
+
end
|
|
395
|
+
|
|
396
|
+
# Filter
|
|
397
|
+
if Dibbler.use_filter == true
|
|
398
|
+
unless params[:filter].blank?
|
|
399
|
+
if Dibbler.disable_unaccent
|
|
400
|
+
result = result.where("lower(filter) LIKE ('%' || lower(trim(?)) || '%')", params[:filter].to_s)
|
|
401
|
+
else
|
|
402
|
+
result = result.where("lower(unaccent(filter)) LIKE ('%' || lower(unaccent(trim(?))) || '%')", params[:filter].to_s)
|
|
403
|
+
end
|
|
404
|
+
end
|
|
405
|
+
end
|
|
406
|
+
|
|
407
|
+
result
|
|
408
|
+
end
|
|
409
|
+
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
end
|
|
413
|
+
end
|
|
414
|
+
end
|