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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/.devcontainer/Dockerfile +20 -0
  3. data/.devcontainer/devcontainer.json +33 -0
  4. data/.github/workflows/gempush.yml +34 -0
  5. data/.gitignore +542 -0
  6. data/.rakeTasks +7 -0
  7. data/.rspec +1 -0
  8. data/.ruby-version +1 -0
  9. data/.travis.yml +31 -0
  10. data/CHANGELOG.md +81 -0
  11. data/Gemfile +4 -0
  12. data/Gemfile.lock +275 -0
  13. data/LICENSE.txt +22 -0
  14. data/README.md +169 -0
  15. data/README.rdoc +68 -0
  16. data/Rakefile +6 -34
  17. data/app/{assets/config/thecore_settings_manifest.js → models/.keep} +0 -0
  18. data/app/models/thecore_settings/setting.rb +77 -0
  19. data/app/views/.keep +0 -0
  20. data/app/views/rails_admin/main/_setting_value.html.haml +41 -0
  21. data/bin/rails +13 -0
  22. data/config/locales/en.yml +29 -0
  23. data/config/locales/{thecore_settings.it.yml → it.yml} +2 -2
  24. data/config/locales/pt-BR.yml +28 -0
  25. data/config/locales/ru.yml +29 -0
  26. data/db/migrate/20161227101954_create_rails_admin_settings.rb +4 -4
  27. data/gemfiles/mongoid-6.0.gemfile +5 -0
  28. data/gemfiles/mongoid-6.3.gemfile +5 -0
  29. data/lib/generators/thecore_settings/migration_generator.rb +15 -0
  30. data/lib/generators/thecore_settings/templates/db/migrate/20161227101954_create_thecore_settings.rb +29 -0
  31. data/lib/generators/thecore_settings/templates/migration.rb +29 -0
  32. data/lib/thecore_settings/determine_mime_type.rb +193 -0
  33. data/lib/thecore_settings/dumper.rb +12 -0
  34. data/lib/thecore_settings/engine.rb +17 -3
  35. data/lib/thecore_settings/fallback.rb +21 -0
  36. data/lib/thecore_settings/hex_color_validator.rb +11 -0
  37. data/lib/thecore_settings/kinds.rb +34 -0
  38. data/lib/thecore_settings/mongoid.rb +19 -0
  39. data/lib/thecore_settings/namespaced.rb +210 -0
  40. data/lib/thecore_settings/processing.rb +217 -0
  41. data/lib/thecore_settings/rails_admin_config.rb +71 -0
  42. data/lib/thecore_settings/require_helpers.rb +86 -0
  43. data/lib/thecore_settings/settings.rb +95 -0
  44. data/lib/thecore_settings/storage/carrier_wave_uploader.rb +9 -0
  45. data/lib/thecore_settings/storage/shrine_uploader.rb +14 -0
  46. data/lib/thecore_settings/tasks.rb +35 -0
  47. data/lib/thecore_settings/uploads.rb +57 -0
  48. data/lib/thecore_settings/validation.rb +126 -0
  49. data/lib/thecore_settings/version.rb +1 -1
  50. data/lib/thecore_settings.rb +115 -123
  51. data/spec/advanced_usage_spec.rb +11 -0
  52. data/spec/carrierwave_spec.rb +41 -0
  53. data/spec/database_trickery_spec.rb +48 -0
  54. data/spec/defaults_spec.rb +87 -0
  55. data/spec/enabling_spec.rb +29 -0
  56. data/spec/factories/setting.rb +8 -0
  57. data/spec/label_spec.rb +16 -0
  58. data/spec/migration_spec.rb +20 -0
  59. data/spec/model_spec.rb +105 -0
  60. data/spec/namespaced_spec.rb +67 -0
  61. data/spec/paperclip_spec.rb +38 -0
  62. data/spec/settings_spec.rb +75 -0
  63. data/spec/shrine_spec.rb +34 -0
  64. data/spec/spec_helper.rb +85 -0
  65. data/spec/support/1024x768.gif +0 -0
  66. data/spec/support/database_cleaner.rb +10 -0
  67. data/spec/support/defaults.yml +23 -0
  68. data/spec/support/defaults_w_file.yml +19 -0
  69. data/spec/support/mongoid.rb +6 -0
  70. data/spec/support/mongoid.yml +6 -0
  71. data/spec/types_spec.rb +101 -0
  72. data/thecore_settings.gemspec +44 -0
  73. metadata +326 -63
  74. data/app/assets/stylesheets/rich/editor.css +0 -20
  75. data/config/initializers/rails_admin_requirements.rb +0 -22
  76. data/config/initializers/thecore_settings_abilities.rb +0 -22
  77. data/config/initializers/thecore_settings_post_init.rb +0 -9
  78. data/config/routes.rb +0 -3
  79. data/db/migrate/20161227101956_add_app_name.rb +0 -5
  80. 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
+