thecore_settings 1.1.15 → 2.0.5
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 +4 -4
- data/.devcontainer/Dockerfile +20 -0
- data/.devcontainer/devcontainer.json +33 -0
- data/.github/workflows/gempush.yml +34 -0
- data/.gitignore +542 -0
- data/.rakeTasks +7 -0
- data/.rspec +1 -0
- data/.ruby-version +1 -0
- data/.travis.yml +31 -0
- data/CHANGELOG.md +81 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +275 -0
- data/LICENSE.txt +22 -0
- data/README.md +169 -0
- data/README.rdoc +68 -0
- data/Rakefile +6 -34
- data/app/{assets/config/thecore_settings_manifest.js → models/.keep} +0 -0
- data/app/models/thecore_settings/setting.rb +77 -0
- data/app/views/.keep +0 -0
- data/app/views/rails_admin/main/_setting_value.html.haml +41 -0
- data/bin/rails +13 -0
- data/config/locales/en.yml +29 -0
- data/config/locales/{thecore_settings.it.yml → it.yml} +2 -2
- data/config/locales/pt-BR.yml +28 -0
- data/config/locales/ru.yml +29 -0
- data/db/migrate/20161227101954_create_rails_admin_settings.rb +4 -4
- data/gemfiles/mongoid-6.0.gemfile +5 -0
- data/gemfiles/mongoid-6.3.gemfile +5 -0
- data/lib/generators/thecore_settings/migration_generator.rb +15 -0
- data/lib/generators/thecore_settings/templates/db/migrate/20161227101954_create_thecore_settings.rb +29 -0
- data/lib/generators/thecore_settings/templates/migration.rb +29 -0
- data/lib/thecore_settings/determine_mime_type.rb +193 -0
- data/lib/thecore_settings/dumper.rb +12 -0
- data/lib/thecore_settings/engine.rb +17 -3
- data/lib/thecore_settings/fallback.rb +21 -0
- data/lib/thecore_settings/hex_color_validator.rb +11 -0
- data/lib/thecore_settings/kinds.rb +34 -0
- data/lib/thecore_settings/mongoid.rb +19 -0
- data/lib/thecore_settings/namespaced.rb +210 -0
- data/lib/thecore_settings/processing.rb +217 -0
- data/lib/thecore_settings/rails_admin_config.rb +71 -0
- data/lib/thecore_settings/require_helpers.rb +86 -0
- data/lib/thecore_settings/settings.rb +95 -0
- data/lib/thecore_settings/storage/carrier_wave_uploader.rb +9 -0
- data/lib/thecore_settings/storage/shrine_uploader.rb +14 -0
- data/lib/thecore_settings/tasks.rb +35 -0
- data/lib/thecore_settings/uploads.rb +57 -0
- data/lib/thecore_settings/validation.rb +126 -0
- data/lib/thecore_settings/version.rb +1 -1
- data/lib/thecore_settings.rb +115 -123
- data/spec/advanced_usage_spec.rb +11 -0
- data/spec/carrierwave_spec.rb +41 -0
- data/spec/database_trickery_spec.rb +48 -0
- data/spec/defaults_spec.rb +87 -0
- data/spec/enabling_spec.rb +29 -0
- data/spec/factories/setting.rb +8 -0
- data/spec/label_spec.rb +16 -0
- data/spec/migration_spec.rb +20 -0
- data/spec/model_spec.rb +105 -0
- data/spec/namespaced_spec.rb +67 -0
- data/spec/paperclip_spec.rb +38 -0
- data/spec/settings_spec.rb +75 -0
- data/spec/shrine_spec.rb +34 -0
- data/spec/spec_helper.rb +85 -0
- data/spec/support/1024x768.gif +0 -0
- data/spec/support/database_cleaner.rb +10 -0
- data/spec/support/defaults.yml +23 -0
- data/spec/support/defaults_w_file.yml +19 -0
- data/spec/support/mongoid.rb +6 -0
- data/spec/support/mongoid.yml +6 -0
- data/spec/types_spec.rb +101 -0
- data/thecore_settings.gemspec +44 -0
- metadata +326 -63
- data/app/assets/stylesheets/rich/editor.css +0 -20
- data/config/initializers/rails_admin_requirements.rb +0 -22
- data/config/initializers/thecore_settings_abilities.rb +0 -22
- data/config/initializers/thecore_settings_post_init.rb +0 -9
- data/config/routes.rb +0 -3
- data/db/migrate/20161227101956_add_app_name.rb +0 -5
- data/lib/tasks/thecore_settings_tasks.rake +0 -4
@@ -0,0 +1,217 @@
|
|
1
|
+
module ThecoreSettings
|
2
|
+
module Processing
|
3
|
+
ThecoreSettings.kinds.each do |dkind|
|
4
|
+
define_method "#{dkind}_kind?" do
|
5
|
+
dkind == kind
|
6
|
+
end
|
7
|
+
define_method "#{dkind}_type?" do
|
8
|
+
dkind == kind
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def text_kind?
|
13
|
+
(ThecoreSettings.kinds - ['phone', 'phones', 'integer', 'float', 'yaml', 'json', 'boolean']).include? kind
|
14
|
+
end
|
15
|
+
|
16
|
+
def upload_kind?
|
17
|
+
['file', 'image'].include? kind
|
18
|
+
end
|
19
|
+
|
20
|
+
def html_kind?
|
21
|
+
['html', 'code', 'sanitize', 'sanitize_code', 'strip_tags', 'simple_format', 'simple_format_raw', 'sanitized'].include? kind
|
22
|
+
end
|
23
|
+
|
24
|
+
def preprocessed_kind?
|
25
|
+
['sanitize', 'sanitize_code', 'strip_tags', 'simple_format', 'simple_format_raw', 'sanitized'].include? kind
|
26
|
+
end
|
27
|
+
|
28
|
+
alias_method :text_type?, :text_kind?
|
29
|
+
alias_method :upload_type?, :upload_kind?
|
30
|
+
alias_method :html_type?, :html_kind?
|
31
|
+
|
32
|
+
def value
|
33
|
+
if upload_kind?
|
34
|
+
unless defined?(Shrine)
|
35
|
+
if file?
|
36
|
+
file.url
|
37
|
+
else
|
38
|
+
nil
|
39
|
+
end
|
40
|
+
else
|
41
|
+
file.url if file.present?
|
42
|
+
end
|
43
|
+
elsif raw.blank? || disabled?
|
44
|
+
default_value
|
45
|
+
else
|
46
|
+
processed_value
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def blank?
|
51
|
+
if file_kind?
|
52
|
+
file.url.nil?
|
53
|
+
elsif raw.blank? || disabled?
|
54
|
+
true
|
55
|
+
else
|
56
|
+
false
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def to_s
|
61
|
+
if yaml_kind? || json_kind? || phone_kind? || integer_kind? || float_kind?
|
62
|
+
|
63
|
+
raw
|
64
|
+
else
|
65
|
+
value
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def preprocess_value
|
72
|
+
case kind
|
73
|
+
# just to raise error if not in rails
|
74
|
+
when 'simple_format'
|
75
|
+
require_rails do
|
76
|
+
end
|
77
|
+
when 'simple_format_raw'
|
78
|
+
require_rails do
|
79
|
+
end
|
80
|
+
when 'strip_tags'
|
81
|
+
require_rails do
|
82
|
+
self.raw = ActionController::Base.helpers.strip_tags(raw)
|
83
|
+
end
|
84
|
+
when 'sanitize', 'sanitize_code'
|
85
|
+
require_rails do
|
86
|
+
self.raw = ThecoreSettings.scrubber.sanitize(raw)
|
87
|
+
end
|
88
|
+
when 'sanitized'
|
89
|
+
require_sanitize do
|
90
|
+
self.raw = Sanitize.clean(value, Sanitize::Config::RELAXED)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def default_value
|
96
|
+
if html_kind?
|
97
|
+
''.html_safe
|
98
|
+
elsif text_kind?
|
99
|
+
''
|
100
|
+
elsif integer_kind?
|
101
|
+
0
|
102
|
+
elsif float_kind?
|
103
|
+
0
|
104
|
+
elsif yaml_kind?
|
105
|
+
nil
|
106
|
+
elsif json_kind?
|
107
|
+
nil
|
108
|
+
elsif boolean_kind?
|
109
|
+
false
|
110
|
+
elsif phone_kind?
|
111
|
+
require_russian_phone do
|
112
|
+
RussianPhone::Number.new('')
|
113
|
+
end
|
114
|
+
elsif phones_kind?
|
115
|
+
[]
|
116
|
+
else
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def default_serializable_value
|
122
|
+
if phones_kind?
|
123
|
+
''
|
124
|
+
elsif boolean_type?
|
125
|
+
'false'
|
126
|
+
else
|
127
|
+
default_value
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
def process_html_types(text)
|
132
|
+
case kind
|
133
|
+
when 'simple_format'
|
134
|
+
require_rails do
|
135
|
+
text = ActionController::Base.helpers.simple_format(text)
|
136
|
+
end
|
137
|
+
when 'simple_format_raw'
|
138
|
+
require_rails do
|
139
|
+
text = ActionController::Base.helpers.simple_format(text, {}, sanitize: false)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
text
|
143
|
+
end
|
144
|
+
|
145
|
+
def process_text
|
146
|
+
text = raw.dup
|
147
|
+
text.gsub!('{{year}}', Time.now.strftime('%Y'))
|
148
|
+
text.gsub! /\{\{year\|([\d]{4})\}\}/ do
|
149
|
+
if Time.now.strftime('%Y') == $1
|
150
|
+
$1
|
151
|
+
else
|
152
|
+
"#{$1}-#{Time.now.strftime('%Y')}"
|
153
|
+
end
|
154
|
+
end
|
155
|
+
text = process_html_types(text)
|
156
|
+
text = text.html_safe if html_kind?
|
157
|
+
text
|
158
|
+
end
|
159
|
+
|
160
|
+
def load_phone
|
161
|
+
require_russian_phone do
|
162
|
+
RussianPhone::Number.new(raw)
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
def load_phones
|
167
|
+
require_russian_phone do
|
168
|
+
raw.gsub("\r", '').split("\n").map{|i| RussianPhone::Number.new(i)}
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
def load_yaml
|
173
|
+
if defined?(Psych) && Psych.respond_to?(:safe_load)
|
174
|
+
Psych.safe_load(raw)
|
175
|
+
else
|
176
|
+
require_safe_yaml do
|
177
|
+
YAML.safe_load(raw)
|
178
|
+
end
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
def load_json
|
183
|
+
JSON.load(raw)
|
184
|
+
end
|
185
|
+
|
186
|
+
def processed_value
|
187
|
+
if text_kind?
|
188
|
+
process_text
|
189
|
+
elsif integer_kind?
|
190
|
+
raw.to_i
|
191
|
+
elsif float_kind?
|
192
|
+
raw.to_f
|
193
|
+
elsif yaml_kind?
|
194
|
+
load_yaml
|
195
|
+
elsif json_kind?
|
196
|
+
load_json
|
197
|
+
elsif boolean_kind?
|
198
|
+
raw == 'true'
|
199
|
+
elsif phone_kind?
|
200
|
+
load_phone
|
201
|
+
elsif phones_kind?
|
202
|
+
load_phones
|
203
|
+
elsif file_kind?
|
204
|
+
file.url
|
205
|
+
else
|
206
|
+
puts "[thecore_settings] Unknown field kind: #{kind}"
|
207
|
+
nil
|
208
|
+
end
|
209
|
+
end
|
210
|
+
|
211
|
+
def self.included(base)
|
212
|
+
base.class_eval do
|
213
|
+
alias_method :val, :value
|
214
|
+
end
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module ThecoreSettings
|
2
|
+
module RailsAdminConfig
|
3
|
+
def self.included(base)
|
4
|
+
if base.respond_to?(:rails_admin)
|
5
|
+
base.rails_admin do
|
6
|
+
navigation_label I18n.t('admin.settings.label')
|
7
|
+
list do
|
8
|
+
if Object.const_defined?('RailsAdminToggleable')
|
9
|
+
field :enabled, :toggle
|
10
|
+
else
|
11
|
+
field :enabled
|
12
|
+
end
|
13
|
+
field :kind
|
14
|
+
field :ns
|
15
|
+
field :name
|
16
|
+
field :raw do
|
17
|
+
pretty_value do
|
18
|
+
if bindings[:object].file_kind? and !defined?(Shrine) and bindings[:object].to_path.present?
|
19
|
+
if bindings[:object].file.url.blank?
|
20
|
+
"-"
|
21
|
+
else
|
22
|
+
"<a href='#{CGI::escapeHTML(bindings[:object].file.url)}'>#{CGI::escapeHTML(bindings[:object].to_path)}</a>".html_safe
|
23
|
+
end
|
24
|
+
elsif bindings[:object].image_kind? and !defined?(Shrine) and !bindings[:object].file.nil?
|
25
|
+
if bindings[:object].file.url.blank?
|
26
|
+
"-"
|
27
|
+
else
|
28
|
+
"<a href='#{CGI::escapeHTML(bindings[:object].file.url)}'><img src='#{CGI::escapeHTML(bindings[:object].file.url)}' /></a>".html_safe
|
29
|
+
end
|
30
|
+
else
|
31
|
+
value
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
if ::Settings.table_exists?
|
36
|
+
nss = ::ThecoreSettings::Setting.pluck(:ns).uniq.map { |c| "ns_#{c.gsub('-', '_')}".to_sym }
|
37
|
+
scopes([nil] + nss)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
edit do
|
42
|
+
field :enabled
|
43
|
+
field :label do
|
44
|
+
read_only true
|
45
|
+
help false
|
46
|
+
end
|
47
|
+
field :kind do
|
48
|
+
read_only true
|
49
|
+
help false
|
50
|
+
end
|
51
|
+
field :raw do
|
52
|
+
partial "setting_value"
|
53
|
+
visible do
|
54
|
+
!bindings[:object].upload_kind?
|
55
|
+
end
|
56
|
+
end
|
57
|
+
if Settings.file_uploads_supported
|
58
|
+
field :file, Settings.file_uploads_engine do
|
59
|
+
visible do
|
60
|
+
bindings[:object].upload_kind?
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
else
|
67
|
+
puts "[thecore_settings] Problem: model does not respond to rails_admin: this should not happen"
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module ThecoreSettings
|
2
|
+
class NoRailsError < StandardError
|
3
|
+
def initialize(message)
|
4
|
+
@message = message
|
5
|
+
end
|
6
|
+
def to_s
|
7
|
+
@message
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
module RequireHelpers
|
12
|
+
private
|
13
|
+
|
14
|
+
def require_russian_phone
|
15
|
+
begin
|
16
|
+
require 'russian_phone'
|
17
|
+
yield
|
18
|
+
rescue LoadError => e
|
19
|
+
e.message << " [thecore_settings] Please add gem 'russian_phone' to use phone settings"
|
20
|
+
raise e
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def require_safe_yaml
|
25
|
+
begin
|
26
|
+
require 'safe_yaml'
|
27
|
+
yield
|
28
|
+
rescue LoadError => e
|
29
|
+
e.message << " [thecore_settings] Please add gem 'safe_yaml' to your Gemfile to use yaml settings"
|
30
|
+
raise e
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def require_sanitize
|
35
|
+
begin
|
36
|
+
require 'sanitize'
|
37
|
+
yield
|
38
|
+
rescue LoadError => e
|
39
|
+
e.message << " [thecore_settings] Please add gem 'sanitize' to your Gemfile to use sanitized settings"
|
40
|
+
raise e
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def require_rails
|
45
|
+
if defined?(Rails) &&
|
46
|
+
defined?(ActionController) &&
|
47
|
+
defined?(ActionController::Base) &&
|
48
|
+
!ThecoreSettings.scrubber.nil?
|
49
|
+
yield
|
50
|
+
else
|
51
|
+
raise NoRailsError.new("[thecore_settings] sanitize, simple_format and strip_tags types require Rails, please add this gem after Rails in your Gemfile")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def require_validates_email_format_of
|
56
|
+
begin
|
57
|
+
require 'validates_email_format_of'
|
58
|
+
yield
|
59
|
+
rescue LoadError => e
|
60
|
+
e.message << " [thecore_settings] Please add gem 'validates_email_format_of' to your Gemfile to use email kind settings"
|
61
|
+
raise e
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def require_geocoder
|
66
|
+
begin
|
67
|
+
require 'geocoder'
|
68
|
+
yield
|
69
|
+
rescue LoadError => e
|
70
|
+
e.message << " [thecore_settings] Please add gem 'validates_email_format_of' to your Gemfile to use email kind settings"
|
71
|
+
raise e
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def require_addressable
|
76
|
+
begin
|
77
|
+
require 'addressable/uri'
|
78
|
+
yield
|
79
|
+
rescue LoadError => e
|
80
|
+
e.message << " [thecore_settings] Please add gem 'addressable' to your Gemfile to use url/domain kind settings"
|
81
|
+
raise e
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'thread'
|
2
|
+
|
3
|
+
# we are inheriting from BasicObject so we don't get a bunch of methods from
|
4
|
+
# Kernel or Object
|
5
|
+
class Settings < BasicObject
|
6
|
+
cattr_accessor :file_uploads_supported, :file_uploads_engine
|
7
|
+
@@file_uploads_supported = false
|
8
|
+
@@file_uploads_engine = false
|
9
|
+
@@namespaces = {}
|
10
|
+
@@mutex = ::Mutex.new
|
11
|
+
|
12
|
+
@@ns_default = 'main'
|
13
|
+
@@ns_fallback = nil
|
14
|
+
cattr_accessor :ns_default, :ns_fallback, :namespaces
|
15
|
+
|
16
|
+
cattr_reader :mutex
|
17
|
+
|
18
|
+
class << self
|
19
|
+
def ns(name, options = {})
|
20
|
+
options.symbolize_keys!
|
21
|
+
if name.nil? || name == @@ns_default
|
22
|
+
name = @@ns_default.to_s
|
23
|
+
else
|
24
|
+
name = name.to_s
|
25
|
+
end
|
26
|
+
if options.key?(:type)
|
27
|
+
options[:kind] = options.delete(:type)
|
28
|
+
end
|
29
|
+
@@mutex.synchronize do
|
30
|
+
@@namespaces[name] ||= ::ThecoreSettings::Namespaced.new(name.to_s)
|
31
|
+
end
|
32
|
+
fallback = options.key?(:fallback) ? options[:fallback] : @@ns_fallback
|
33
|
+
::ThecoreSettings::Fallback.new(@@namespaces[name], fallback)
|
34
|
+
end
|
35
|
+
|
36
|
+
def get_default_ns
|
37
|
+
ns(nil, fallback: @@ns_fallback)
|
38
|
+
end
|
39
|
+
|
40
|
+
def table_exists?
|
41
|
+
ThecoreSettings.mongoid? || ThecoreSettings::Setting.table_exists?
|
42
|
+
rescue ActiveRecord::NoDatabaseError
|
43
|
+
false
|
44
|
+
end
|
45
|
+
|
46
|
+
def unload!
|
47
|
+
@@mutex.synchronize do
|
48
|
+
@@namespaces.values.map(&:unload!)
|
49
|
+
@@namespaces = {}
|
50
|
+
@@ns_default = 'main'
|
51
|
+
@@ns_fallback = nil
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def destroy_all!
|
56
|
+
ThecoreSettings::Setting.destroy_all
|
57
|
+
unload!
|
58
|
+
end
|
59
|
+
|
60
|
+
def root_file_path
|
61
|
+
if defined?(Rails)
|
62
|
+
Rails.root
|
63
|
+
else
|
64
|
+
Pathname.new(File.dirname(__FILE__)).join('../..')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def apply_defaults!(file, verbose = false)
|
69
|
+
ThecoreSettings.apply_defaults!(file, verbose)
|
70
|
+
end
|
71
|
+
|
72
|
+
def get(key, options = {})
|
73
|
+
options.symbolize_keys!
|
74
|
+
ns(options[:ns], options).get(key, options)
|
75
|
+
end
|
76
|
+
|
77
|
+
def set(key, value = nil, options = {})
|
78
|
+
options.symbolize_keys!
|
79
|
+
ns(options[:ns], options).set(key, value, options)
|
80
|
+
end
|
81
|
+
|
82
|
+
def save_default(key, value, options = {})
|
83
|
+
set(key, value, options.merge(overwrite: false))
|
84
|
+
end
|
85
|
+
|
86
|
+
def create_setting(key, value, options = {})
|
87
|
+
set(key, nil, options.merge(overwrite: false))
|
88
|
+
end
|
89
|
+
|
90
|
+
def method_missing(*args)
|
91
|
+
get_default_ns.__send__(*args)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|