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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 23b68e0d113892e9f08e29c3e70e39d79f3ce58aed36a981c55fe81593b8f3a9
4
- data.tar.gz: c144240c649762ee4495fee8e2eef504244ae37746e43c294cef3512ea813a4c
3
+ metadata.gz: 3e423b44c4e49c3d0ffb953ffee50e1b268262a770eba8a9114b23c494458861
4
+ data.tar.gz: d5997e14e9288ec4c0fdf858a1029ea3a379b1e1aecf05b2ed8bb9158bf45bbb
5
5
  SHA512:
6
- metadata.gz: f094b5b2485041c04885b1097715bf046e3a5525b88d800242479edaa3190fba4b3f164729840f2b11c519862387893c69ce58085d5867deab74093f75bfee1b
7
- data.tar.gz: 20d36398a118661a50d45cbfbc16b416f280ef46376c96acbae2a15226ac1f2c70483adcdaacc56530169d6a96ad1e9ac4f79234766c13e2e80a5faaf5e289f6
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
- This a plugin that makes managing a table of
4
- а global key, value pairs easy. Think of it like a global Hash stored in your database,
5
- that uses simple ActiveRecord like methods for manipulation. Keep track of any global
6
- setting that you don't want to hard code into your rails app. You can store any kind
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
- ## Use Setting in Rails initalizing:
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
- In `version 2.3+` we allows you to use Setting before Rails is initialized.
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 in these locations:
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
- ### Caching flow:
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 [RequestStore](https://github.com/steveklabnik/request_store) to avoid hit cache/db.
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
- redirect_to settings_path, notice: "Setting was successfully updated."
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
- - [thebluedoc/bluedoc](https://github.com/thebluedoc/bluedoc/blob/master/app/models/setting.rb) - 2.x
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.
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "rails-settings/base"
4
+ require_relative "rails-settings/request_cache"
4
5
  require_relative "rails-settings/railtie"
5
6
  require_relative "rails-settings/version"
6
7
 
@@ -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
- RequestStore.store[:rails_settings_all_settings] = nil
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], separator: opts[:separator])
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.to_s,
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.to_s
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
- value == "true" || value == "1" || value == 1 || value == true
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
- begin
124
- YAML.load(value).to_h
125
- rescue StandardError
126
- eval(value).to_h
127
- end
128
- rescue StandardError
129
- {}
130
- end
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.to_s]
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
- RequestStore.store[:rails_settings_all_settings] ||= begin
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
@@ -3,7 +3,7 @@
3
3
  module RailsSettings
4
4
  class << self
5
5
  def version
6
- "2.3.5"
6
+ "2.5.2"
7
7
  end
8
8
  end
9
9
  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.3.5
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-10-17 00:00:00.000000000 Z
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: 4.2.0
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: 4.2.0
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 This is improved from rails-settings, added caching.\n Settings
126
- plugin for Rails that makes managing a table of global key,\n value pairs easy.
127
- Think of it like a global Hash stored in you database,\n that uses simple ActiveRecord
128
- like methods for manipulation.\n\n Keep track of any global setting that you dont
129
- want to hard code into your rails app.\n You can store any kind of object. Strings,
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.0.3
152
+ rubygems_version: 3.1.4
166
153
  signing_key:
167
154
  specification_version: 4
168
- summary: Settings plugin for Rails that makes managing a table of global keys.
155
+ summary: The best solution for store global settings in Rails applications.
169
156
  test_files: []