rails-settings-cached 2.3.5 → 2.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +98 -23
- data/lib/rails-settings-cached.rb +1 -0
- data/lib/rails-settings/base.rb +28 -18
- data/lib/rails-settings/request_cache.rb +30 -0
- data/lib/rails-settings/version.rb +1 -1
- metadata +12 -25
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e423b44c4e49c3d0ffb953ffee50e1b268262a770eba8a9114b23c494458861
|
4
|
+
data.tar.gz: d5997e14e9288ec4c0fdf858a1029ea3a379b1e1aecf05b2ed8bb9158bf45bbb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edf9eff836688ce1f82d3de681c34a7fd9c782e526e952ac42430d7f559b7aae51c3f73f4a749f167302f31b4b3286dce2d5f21dc504a6735981db6a0d259b6f
|
7
|
+
data.tar.gz: dfcbf34fcbb3f0af4d0161601537db441c8d07632ffc2b964857b10fcaa6af8b88f2cbd2c758d21bf3e9676a7dc8a1ea607230c3e06560fcf65feef2c7fff434
|
data/README.md
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
# Rails Settings Cached
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
that uses simple ActiveRecord like methods for manipulation. Keep track of any global
|
6
|
-
|
7
|
-
of object. Strings, numbers, arrays, or any object.
|
3
|
+
The best solution for store global settings in Rails applications.
|
4
|
+
|
5
|
+
This gem will managing a table of а global key, value pairs easy. Think of it like a global Hash stored in your database, that uses simple ActiveRecord like methods for manipulation. Keep track of any global setting that you don't want to hard code into your rails app.
|
6
|
+
|
7
|
+
You can store any kind of object. Strings, numbers, arrays, booleans, or any object.
|
8
8
|
|
9
9
|
[![Gem Version](https://badge.fury.io/rb/rails-settings-cached.svg)](https://rubygems.org/gems/rails-settings-cached) [![CI Status](https://travis-ci.org/huacnlee/rails-settings-cached.svg)](http://travis-ci.org/huacnlee/rails-settings-cached) [![codecov.io](https://codecov.io/github/huacnlee/rails-settings-cached/coverage.svg?branch=master)](https://codecov.io/github/huacnlee/rails-settings-cached?branch=master)
|
10
10
|
|
@@ -30,9 +30,9 @@ You will get `app/models/setting.rb`
|
|
30
30
|
```rb
|
31
31
|
class Setting < RailsSettings::Base
|
32
32
|
# cache_prefix { "v1" }
|
33
|
-
field :app_name, default: "Rails Settings"
|
33
|
+
field :app_name, default: "Rails Settings", validates: { presence: true, length: { in: 2..20 } }
|
34
34
|
field :host, default: "http://example.com", readonly: true
|
35
|
-
field :default_locale, default: "zh-CN"
|
35
|
+
field :default_locale, default: "zh-CN", validates: { presence: true, inclusion: { in: %w[zh-CN en jp] } }
|
36
36
|
field :readonly_item, type: :integer, default: 100, readonly: true
|
37
37
|
field :user_limits, type: :integer, default: 20
|
38
38
|
field :exchange_rate, type: :float, default: 0.123
|
@@ -49,11 +49,11 @@ class Setting < RailsSettings::Base
|
|
49
49
|
}
|
50
50
|
|
51
51
|
# lambda default value
|
52
|
-
field :welcome_message, type: :string, default: -> { "welcome to #{self.app_name}" }
|
52
|
+
field :welcome_message, type: :string, default: -> { "welcome to #{self.app_name}" }, validates: { length: { maximum: 255 } }
|
53
53
|
end
|
54
54
|
```
|
55
55
|
|
56
|
-
You must use `field` method to statement the setting keys, otherwise you can't use it.
|
56
|
+
You must use the `field` method to statement the setting keys, otherwise you can't use it.
|
57
57
|
|
58
58
|
Now just put that migration in the database with:
|
59
59
|
|
@@ -126,7 +126,6 @@ irb > Setting.notification_options
|
|
126
126
|
}
|
127
127
|
```
|
128
128
|
|
129
|
-
|
130
129
|
### Get defined fields
|
131
130
|
|
132
131
|
> version 2.3+
|
@@ -151,9 +150,56 @@ Setting.get_field("app_name")
|
|
151
150
|
=> { key: "app_name", type: :string, default: "Rails Settings", readonly: false }
|
152
151
|
```
|
153
152
|
|
154
|
-
##
|
153
|
+
## Validations
|
154
|
+
|
155
|
+
You can use `validates` options to special the [Rails Validation](https://api.rubyonrails.org/classes/ActiveModel/Validations/ClassMethods.html#method-i-validates) for fields.
|
156
|
+
|
157
|
+
```rb
|
158
|
+
class Setting < RailsSettings::Base
|
159
|
+
# cache_prefix { "v1" }
|
160
|
+
field :app_name, default: "Rails Settings", validates: { presence: true, length: { in: 2..20 } }
|
161
|
+
field :default_locale, default: "zh-CN", validates: { presence: true, inclusion: { in: %w[zh-CN en jp], message: "is not included in [zh-CN, en, jp]" } }
|
162
|
+
end
|
163
|
+
```
|
164
|
+
|
165
|
+
Now validate will work on record save:
|
155
166
|
|
156
|
-
|
167
|
+
```rb
|
168
|
+
irb> Setting.app_name = ""
|
169
|
+
ActiveRecord::RecordInvalid: (Validation failed: App name can't be blank)
|
170
|
+
irb> Setting.app_name = "Rails Settings"
|
171
|
+
"Rails Settings"
|
172
|
+
irb> Setting.default_locale = "zh-TW"
|
173
|
+
ActiveRecord::RecordInvalid: (Validation failed: Default locale is not included in [zh-CN, en, jp])
|
174
|
+
irb> Setting.default_locale = "en"
|
175
|
+
"en"
|
176
|
+
```
|
177
|
+
|
178
|
+
Validate by `save` / `valid?` method:
|
179
|
+
|
180
|
+
```rb
|
181
|
+
|
182
|
+
setting = Setting.find_or_initialize_by(var: :app_name)
|
183
|
+
setting.value = ""
|
184
|
+
setting.valid?
|
185
|
+
# => false
|
186
|
+
setting.errors.full_messages
|
187
|
+
# => ["App name can't be blank", "App name too short (minimum is 2 characters)"]
|
188
|
+
|
189
|
+
setting = Setting.find_or_initialize_by(var: :default_locale)
|
190
|
+
setting.value = "zh-TW"
|
191
|
+
setting.save
|
192
|
+
# => false
|
193
|
+
setting.errors.full_messages
|
194
|
+
# => ["Default locale is not included in [zh-CN, en, jp]"]
|
195
|
+
setting.value = "en"
|
196
|
+
setting.valid?
|
197
|
+
# => true
|
198
|
+
```
|
199
|
+
|
200
|
+
## Use Setting in Rails initializing:
|
201
|
+
|
202
|
+
In `version 2.3+` you can use Setting before Rails is initialized.
|
157
203
|
|
158
204
|
For example `config/initializers/devise.rb`
|
159
205
|
|
@@ -174,10 +220,9 @@ end
|
|
174
220
|
|
175
221
|
## Readonly field
|
176
222
|
|
177
|
-
You may also want use Setting
|
223
|
+
You may also want use Setting before Rails initialize:
|
178
224
|
|
179
225
|
```
|
180
|
-
config/application.rb
|
181
226
|
config/environments/*.rb
|
182
227
|
```
|
183
228
|
|
@@ -200,14 +245,19 @@ class Setting < RailsSettings::Base
|
|
200
245
|
end
|
201
246
|
```
|
202
247
|
|
248
|
+
config/environments/production.rb
|
249
|
+
|
203
250
|
```rb
|
251
|
+
# You must require_relative directly in Rails 6.1+ in config/environments/production.rb
|
252
|
+
require_relative "../../app/models/setting"
|
253
|
+
|
204
254
|
Rails.application.configure do
|
205
255
|
config.action_mailer.delivery_method = :smtp
|
206
256
|
config.action_mailer.smtp_settings = Setting.mailer_options.deep_symbolize_keys
|
207
257
|
end
|
208
258
|
```
|
209
259
|
|
210
|
-
|
260
|
+
## Caching flow:
|
211
261
|
|
212
262
|
```
|
213
263
|
Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
|
@@ -217,7 +267,7 @@ Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
|
|
217
267
|
Return default value or nil
|
218
268
|
```
|
219
269
|
|
220
|
-
In each Setting keys call, we will load the cache/db and save in [
|
270
|
+
In each Setting keys call, we will load the cache/db and save in [ActiveSupport::CurrentAttributes](https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html) to avoid hit cache/db.
|
221
271
|
|
222
272
|
Each key update will expire the cache, so do not add some frequent update key.
|
223
273
|
|
@@ -242,7 +292,7 @@ class ActiveSupport::TestCase
|
|
242
292
|
end
|
243
293
|
```
|
244
294
|
|
245
|
-
|
295
|
+
---
|
246
296
|
|
247
297
|
## How to manage Settings in the admin interface?
|
248
298
|
|
@@ -256,19 +306,32 @@ namespace :admin do
|
|
256
306
|
end
|
257
307
|
```
|
258
308
|
|
259
|
-
|
260
309
|
app/controllers/admin/settings_controller.rb
|
261
310
|
|
262
311
|
```rb
|
263
312
|
module Admin
|
264
313
|
class SettingsController < ApplicationController
|
265
|
-
before_action :get_setting, only: [:edit, :update]
|
266
|
-
|
267
314
|
def create
|
315
|
+
@errors = ActiveModel::Errors.new
|
316
|
+
setting_params.keys.each do |key|
|
317
|
+
next if setting_params[key].nil?
|
318
|
+
|
319
|
+
setting = Setting.new(var: key)
|
320
|
+
setting.value = setting_params[key].strip
|
321
|
+
unless setting.valid?
|
322
|
+
@errors.merge!(setting.errors)
|
323
|
+
end
|
324
|
+
end
|
325
|
+
|
326
|
+
if @errors.any?
|
327
|
+
render :new
|
328
|
+
end
|
329
|
+
|
268
330
|
setting_params.keys.each do |key|
|
269
331
|
Setting.send("#{key}=", setting_params[key].strip) unless setting_params[key].nil?
|
270
332
|
end
|
271
|
-
|
333
|
+
|
334
|
+
redirect_to admin_settings_path, notice: "Setting was successfully updated."
|
272
335
|
end
|
273
336
|
|
274
337
|
private
|
@@ -284,6 +347,16 @@ app/views/admin/settings/show.html.erb
|
|
284
347
|
|
285
348
|
```erb
|
286
349
|
<%= form_for(Setting.new, url: admin_settings_path) do |f| %>
|
350
|
+
<% if @errors.any? %>
|
351
|
+
<div class="alert alert-block alert-danger">
|
352
|
+
<ul>
|
353
|
+
<% @errors.full_messages.each do |msg| %>
|
354
|
+
<li><%= msg %></li>
|
355
|
+
<% end %>
|
356
|
+
</ul>
|
357
|
+
</div>
|
358
|
+
<% end %>
|
359
|
+
|
287
360
|
<div class="form-group">
|
288
361
|
<label class="control-label">Host</label>
|
289
362
|
<%= f.text_field :host, value: Setting.host, class: "form-control", placeholder: "http://localhost" %>
|
@@ -349,9 +422,11 @@ end
|
|
349
422
|
- [forem/forem](https://github.com/forem/forem) - 2.x
|
350
423
|
- [siwapp/siwapp](https://github.com/siwapp/siwapp) - 2.x
|
351
424
|
- [aidewoode/black_candy](https://github.com/aidewoode/black_candy) - 2.x
|
352
|
-
- [
|
425
|
+
- [huacnlee/bluedoc](https://github.com/huacnlee/bluedoc) - 2.x
|
426
|
+
- [getzealot/zealot](https://github.com/getzealot/zealot) - 2.x
|
427
|
+
- [kaishuu0123/rebacklogs](https://github.com/kaishuu0123/rebacklogs) - 2.x
|
353
428
|
- [tootsuite/mastodon](https://github.com/tootsuite/mastodon) - 0.6.x
|
354
429
|
- [helpyio/helpy](https://github.com/helpyio/helpy) - 0.5.x
|
355
|
-
|
430
|
+
- [daqing/rabel](https://github.com/daqing/rabel) - 0.4.x
|
356
431
|
|
357
432
|
And more than [1K repositories](https://github.com/huacnlee/rails-settings-cached/network/dependents) used.
|
data/lib/rails-settings/base.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require "request_store"
|
4
|
-
|
5
3
|
module RailsSettings
|
6
4
|
class Base < ActiveRecord::Base
|
7
5
|
class SettingNotFound < RuntimeError; end
|
@@ -25,12 +23,13 @@ module RailsSettings
|
|
25
23
|
|
26
24
|
class << self
|
27
25
|
def clear_cache
|
28
|
-
|
26
|
+
RequestCache.reset
|
29
27
|
Rails.cache.delete(cache_key)
|
30
28
|
end
|
31
29
|
|
32
30
|
def field(key, **opts)
|
33
|
-
_define_field(key, default: opts[:default], type: opts[:type], readonly: opts[:readonly],
|
31
|
+
_define_field(key, default: opts[:default], type: opts[:type], readonly: opts[:readonly],
|
32
|
+
separator: opts[:separator], validates: opts[:validates])
|
34
33
|
end
|
35
34
|
|
36
35
|
def get_field(key)
|
@@ -61,10 +60,12 @@ module RailsSettings
|
|
61
60
|
|
62
61
|
private
|
63
62
|
|
64
|
-
def _define_field(key, default: nil, type: :string, readonly: false, separator: nil)
|
63
|
+
def _define_field(key, default: nil, type: :string, readonly: false, separator: nil, validates: nil)
|
64
|
+
key = key.to_s
|
65
|
+
|
65
66
|
@defined_fields ||= []
|
66
67
|
@defined_fields << {
|
67
|
-
key: key
|
68
|
+
key: key,
|
68
69
|
default: default,
|
69
70
|
type: type || :string,
|
70
71
|
readonly: readonly.nil? ? false : readonly
|
@@ -91,7 +92,7 @@ module RailsSettings
|
|
91
92
|
end
|
92
93
|
|
93
94
|
define_singleton_method("#{key}=") do |value|
|
94
|
-
var_name = key
|
95
|
+
var_name = key
|
95
96
|
|
96
97
|
record = find_by(var: var_name) || new(var: var_name)
|
97
98
|
value = send(:_convert_string_to_typeof_value, type, value, separator: separator)
|
@@ -101,6 +102,15 @@ module RailsSettings
|
|
101
102
|
|
102
103
|
value
|
103
104
|
end
|
105
|
+
|
106
|
+
if validates
|
107
|
+
validates[:if] = proc { |item| item.var.to_s == key }
|
108
|
+
send(:validates, key, **validates)
|
109
|
+
|
110
|
+
define_method(:read_attribute_for_validation) do |_key|
|
111
|
+
self.value
|
112
|
+
end
|
113
|
+
end
|
104
114
|
end
|
105
115
|
|
106
116
|
if type == :boolean
|
@@ -115,19 +125,19 @@ module RailsSettings
|
|
115
125
|
|
116
126
|
case type
|
117
127
|
when :boolean
|
118
|
-
|
128
|
+
["true", "1", 1, true].include?(value)
|
119
129
|
when :array
|
120
130
|
value.split(separator || SEPARATOR_REGEXP).reject { |str| str.empty? }.map(&:strip)
|
121
131
|
when :hash
|
122
132
|
value = begin
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
133
|
+
begin
|
134
|
+
YAML.load(value).to_h
|
135
|
+
rescue StandardError
|
136
|
+
eval(value).to_h
|
137
|
+
end
|
138
|
+
rescue StandardError
|
139
|
+
{}
|
140
|
+
end
|
131
141
|
value.deep_stringify_keys!
|
132
142
|
ActiveSupport::HashWithIndifferentAccess.new(value)
|
133
143
|
when :integer
|
@@ -148,7 +158,7 @@ module RailsSettings
|
|
148
158
|
return nil
|
149
159
|
end
|
150
160
|
|
151
|
-
_all_settings[var_name
|
161
|
+
_all_settings[var_name]
|
152
162
|
end
|
153
163
|
|
154
164
|
def _table_exists?
|
@@ -162,7 +172,7 @@ module RailsSettings
|
|
162
172
|
end
|
163
173
|
|
164
174
|
def _all_settings
|
165
|
-
|
175
|
+
RequestCache.settings ||= begin
|
166
176
|
Rails.cache.fetch(cache_key, expires_in: 1.week) do
|
167
177
|
vars = unscoped.select("var, value")
|
168
178
|
result = {}
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module RailsSettings
|
2
|
+
if defined? ActiveSupport::CurrentAttributes
|
3
|
+
# For storage all settings in Current, it will reset after per request completed.
|
4
|
+
# Base on ActiveSupport::CurrentAttributes
|
5
|
+
# https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html
|
6
|
+
class RequestCache < ActiveSupport::CurrentAttributes
|
7
|
+
attribute :settings
|
8
|
+
end
|
9
|
+
else
|
10
|
+
# https://github.com/steveklabnik/request_store
|
11
|
+
# For Rails 5.0
|
12
|
+
require "request_store"
|
13
|
+
|
14
|
+
class RequestCache
|
15
|
+
class << self
|
16
|
+
def reset
|
17
|
+
self.settings = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def settings
|
21
|
+
RequestStore.store[:rails_settings_all_settings]
|
22
|
+
end
|
23
|
+
|
24
|
+
def settings=(val)
|
25
|
+
RequestStore.store[:rails_settings_all_settings]
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-settings-cached
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Lee
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-21 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,28 +16,14 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version:
|
19
|
+
version: 5.0.0
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version:
|
27
|
-
- !ruby/object:Gem::Dependency
|
28
|
-
name: request_store
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
30
|
-
requirements:
|
31
|
-
- - ">="
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
34
|
-
type: :runtime
|
35
|
-
prerelease: false
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
37
|
-
requirements:
|
38
|
-
- - ">="
|
39
|
-
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
26
|
+
version: 5.0.0
|
41
27
|
- !ruby/object:Gem::Dependency
|
42
28
|
name: codecov
|
43
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -122,11 +108,11 @@ dependencies:
|
|
122
108
|
- - ">="
|
123
109
|
- !ruby/object:Gem::Version
|
124
110
|
version: '0'
|
125
|
-
description: "\n
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
111
|
+
description: "\n The best solution for store global settings in Rails applications.\n\n
|
112
|
+
\ This gem will managing a table of а global key, value pairs easy. Think of it
|
113
|
+
like a \n global Hash stored in your database, that uses simple ActiveRecord like
|
114
|
+
methods for manipulation.\n\n Keep track of any global setting that you dont want
|
115
|
+
to hard code into your rails app.\n You can store any kind of object. Strings,
|
130
116
|
numbers, arrays, or any object.\n "
|
131
117
|
email: huacnlee@gmail.com
|
132
118
|
executables: []
|
@@ -142,6 +128,7 @@ files:
|
|
142
128
|
- lib/rails-settings-cached.rb
|
143
129
|
- lib/rails-settings/base.rb
|
144
130
|
- lib/rails-settings/railtie.rb
|
131
|
+
- lib/rails-settings/request_cache.rb
|
145
132
|
- lib/rails-settings/version.rb
|
146
133
|
homepage: https://github.com/huacnlee/rails-settings-cached
|
147
134
|
licenses:
|
@@ -162,8 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
162
149
|
- !ruby/object:Gem::Version
|
163
150
|
version: '0'
|
164
151
|
requirements: []
|
165
|
-
rubygems_version: 3.
|
152
|
+
rubygems_version: 3.1.4
|
166
153
|
signing_key:
|
167
154
|
specification_version: 4
|
168
|
-
summary:
|
155
|
+
summary: The best solution for store global settings in Rails applications.
|
169
156
|
test_files: []
|