rails-settings-cached 2.3.3 → 2.5.0

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: d9fb44e09bad24a4d3c6cf36fda107fe18ce214964b713de318e5f3efc083851
4
- data.tar.gz: 75ee5df473cff1fc07b963b6441152f559de8d0a5652267530c5c0f62cac93f9
3
+ metadata.gz: f37f8d9bad4b40dd60dbf30806e1e530e1d292448ba803db06bdcca5f562c62e
4
+ data.tar.gz: 2900b13077db46b60b2c22cfa3a21b7af5704b86d874d485672508c8ef866475
5
5
  SHA512:
6
- metadata.gz: 6bf0b841b4b2ee46b7da5f51a54d2e3f17f984f2fe1f72841bc056966efc29fd5ad70ea54b0b5559f4ea493927ef796cbc956302b404e18ec61059c40d620904
7
- data.tar.gz: 76a594a2df28a1490c6d67b1fff1a4d776572cc1240c9c07549d6d0349c048a017ee10f828d7c38e41bdf4c7158af9108f9c9181af3ee015af72654cd23831ff
6
+ metadata.gz: c696568044b97ce9a9112de42682a7e484e13a8220e0d7b1b52d5977f56358f82109e4bb1dd8b227f89089d060a49454b2bd1c86ac4cc7fbfc2c275bf0a48c55
7
+ data.tar.gz: c2eb40491e08ce8eefe6d96e6d987fd9a02efbad708e9a1ae0442d98b82e626300ee90eda5664be385aa81178c4be4a19b190d623a2ff8cdb0d8e0f8b53d0649
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,44 @@ Setting.get_field("app_name")
151
150
  => { key: "app_name", type: :string, default: "Rails Settings", readonly: false }
152
151
  ```
153
152
 
154
- ## Readonly field
153
+ ## Validations
155
154
 
156
- Sometimes you may need to use Setting before Rails is initialized, for example `config/devise.rb`
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.
166
+
167
+ ```rb
168
+ setting = Setting.find_or_initialize_by(var: :app_name)
169
+ setting.value = ""
170
+ setting.valid?
171
+ # => false
172
+ setting.errors.full_messages
173
+ # => ["App name can't be blank", "App name too short (minimum is 2 characters)"]
174
+
175
+ setting = Setting.find_or_initialize_by(var: :default_locale)
176
+ setting.value = "zh-TW"
177
+ setting.save
178
+ # => false
179
+ setting.errors.full_messages
180
+ # => ["Default locale is not included in [zh-CN, en, jp]"]
181
+ setting.value = "en"
182
+ setting.valid?
183
+ # => true
184
+ ```
185
+
186
+ ## Use Setting in Rails initializing:
187
+
188
+ In `version 2.3+` you can use Setting before Rails is initialized.
189
+
190
+ For example `config/initializers/devise.rb`
157
191
 
158
192
  ```rb
159
193
  Devise.setup do |config|
@@ -163,17 +197,53 @@ Devise.setup do |config|
163
197
  end
164
198
  ```
165
199
 
166
- In this case, you must define the `readonly` field:
200
+ ```rb
201
+ class Setting < RailsSettings::Base
202
+ field :omniauth_google_client_id, default: ENV["OMNIAUTH_GOOGLE_CLIENT_ID"]
203
+ field :omniauth_google_client_secret, default: ENV["OMNIAUTH_GOOGLE_CLIENT_SECRET"]
204
+ end
205
+ ```
206
+
207
+ ## Readonly field
208
+
209
+ You may also want use Setting before Rails initialize:
210
+
211
+ ```
212
+ config/environments/*.rb
213
+ ```
214
+
215
+ If you want do that do that, the setting field must has `readonly: true`.
216
+
217
+ For example:
167
218
 
168
219
  ```rb
169
220
  class Setting < RailsSettings::Base
170
- # cache_prefix { "v1" }
171
- field :omniauth_google_client_id, default: ENV["OMNIAUTH_GOOGLE_CLIENT_ID"], readonly: true
172
- field :omniauth_google_client_secret, default: ENV["OMNIAUTH_GOOGLE_CLIENT_SECRET"], readonly: true
221
+ field :mailer_provider, default: (ENV["mailer_provider"] || "smtp"), readonly: true
222
+ field :mailer_options, type: :hash, readonly: true, default: {
223
+ address: ENV["mailer_options.address"],
224
+ port: ENV["mailer_options.port"],
225
+ domain: ENV["mailer_options.domain"],
226
+ user_name: ENV["mailer_options.user_name"],
227
+ password: ENV["mailer_options.password"],
228
+ authentication: ENV["mailer_options.authentication"] || "login",
229
+ enable_starttls_auto: ENV["mailer_options.enable_starttls_auto"]
230
+ }
231
+ end
232
+ ```
233
+
234
+ config/environments/production.rb
235
+
236
+ ```rb
237
+ # You must require_relative directly in Rails 6.1+ in config/environments/production.rb
238
+ require_relative "../../app/models/setting"
239
+
240
+ Rails.application.configure do
241
+ config.action_mailer.delivery_method = :smtp
242
+ config.action_mailer.smtp_settings = Setting.mailer_options.deep_symbolize_keys
173
243
  end
174
244
  ```
175
245
 
176
- ### Caching flow:
246
+ ## Caching flow:
177
247
 
178
248
  ```
179
249
  Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
@@ -183,7 +253,7 @@ Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
183
253
  Return default value or nil
184
254
  ```
185
255
 
186
- 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.
256
+ 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.
187
257
 
188
258
  Each key update will expire the cache, so do not add some frequent update key.
189
259
 
@@ -208,7 +278,7 @@ class ActiveSupport::TestCase
208
278
  end
209
279
  ```
210
280
 
211
- -----
281
+ ---
212
282
 
213
283
  ## How to manage Settings in the admin interface?
214
284
 
@@ -222,19 +292,32 @@ namespace :admin do
222
292
  end
223
293
  ```
224
294
 
225
-
226
295
  app/controllers/admin/settings_controller.rb
227
296
 
228
297
  ```rb
229
298
  module Admin
230
299
  class SettingsController < ApplicationController
231
- before_action :get_setting, only: [:edit, :update]
232
-
233
300
  def create
301
+ @errors = ActiveModel::Errors.new
302
+ setting_params.keys.each do |key|
303
+ next if setting_params[key].nil?
304
+
305
+ setting = Setting.new(var: key)
306
+ setting.value = setting_params[key].strip
307
+ unless setting.valid?
308
+ @errors.merge!(setting.errors)
309
+ end
310
+ end
311
+
312
+ if @errors.any?
313
+ render :new
314
+ end
315
+
234
316
  setting_params.keys.each do |key|
235
317
  Setting.send("#{key}=", setting_params[key].strip) unless setting_params[key].nil?
236
318
  end
237
- redirect_to settings_path, notice: "Setting was successfully updated."
319
+
320
+ redirect_to admin_settings_path, notice: "Setting was successfully updated."
238
321
  end
239
322
 
240
323
  private
@@ -250,6 +333,16 @@ app/views/admin/settings/show.html.erb
250
333
 
251
334
  ```erb
252
335
  <%= form_for(Setting.new, url: admin_settings_path) do |f| %>
336
+ <% if @errors.any? %>
337
+ <div class="alert alert-block alert-danger">
338
+ <ul>
339
+ <% @errors.full_messages.each do |msg| %>
340
+ <li><%= msg %></li>
341
+ <% end %>
342
+ </ul>
343
+ </div>
344
+ <% end %>
345
+
253
346
  <div class="form-group">
254
347
  <label class="control-label">Host</label>
255
348
  <%= f.text_field :host, value: Setting.host, class: "form-control", placeholder: "http://localhost" %>
@@ -315,9 +408,11 @@ end
315
408
  - [forem/forem](https://github.com/forem/forem) - 2.x
316
409
  - [siwapp/siwapp](https://github.com/siwapp/siwapp) - 2.x
317
410
  - [aidewoode/black_candy](https://github.com/aidewoode/black_candy) - 2.x
318
- - [thebluedoc/bluedoc](https://github.com/thebluedoc/bluedoc/blob/master/app/models/setting.rb) - 2.x
411
+ - [huacnlee/bluedoc](https://github.com/huacnlee/bluedoc) - 2.x
412
+ - [getzealot/zealot](https://github.com/getzealot/zealot) - 2.x
413
+ - [kaishuu0123/rebacklogs](https://github.com/kaishuu0123/rebacklogs) - 2.x
319
414
  - [tootsuite/mastodon](https://github.com/tootsuite/mastodon) - 0.6.x
320
415
  - [helpyio/helpy](https://github.com/helpyio/helpy) - 0.5.x
321
-
416
+ - [daqing/rabel](https://github.com/daqing/rabel) - 0.4.x
322
417
 
323
418
  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,12 @@ 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], separator: opts[:separator], validates: opts[:validates])
34
32
  end
35
33
 
36
34
  def get_field(key)
@@ -61,7 +59,7 @@ module RailsSettings
61
59
 
62
60
  private
63
61
 
64
- def _define_field(key, default: nil, type: :string, readonly: false, separator: nil)
62
+ def _define_field(key, default: nil, type: :string, readonly: false, separator: nil, validates: nil)
65
63
  @defined_fields ||= []
66
64
  @defined_fields << {
67
65
  key: key.to_s,
@@ -97,10 +95,19 @@ module RailsSettings
97
95
  value = send(:_convert_string_to_typeof_value, type, value, separator: separator)
98
96
 
99
97
  record.value = value
100
- record.save!
98
+ record.save(validate: false)
101
99
 
102
100
  value
103
101
  end
102
+
103
+ if validates
104
+ validates[:if] = Proc.new { |item| item.var.to_s == key.to_s }
105
+ send(:validates, key, **validates)
106
+
107
+ define_method(:read_attribute_for_validation) do |_key|
108
+ self.value
109
+ end
110
+ end
104
111
  end
105
112
 
106
113
  if type == :boolean
@@ -142,23 +149,27 @@ module RailsSettings
142
149
  end
143
150
 
144
151
  def _value_of(var_name)
145
- unless table_exists?
152
+ unless _table_exists?
146
153
  # Fallback to default value if table was not ready (before migrate)
147
- puts "WARNING: table: \"#{table_name}\" does not exist, `#{name}.#{var_name}` fallback to returns the default value."
154
+ puts "WARNING: table: \"#{table_name}\" does not exist or not database connection, `#{name}.#{var_name}` fallback to returns the default value."
148
155
  return nil
149
156
  end
150
157
 
151
158
  _all_settings[var_name.to_s]
152
159
  end
153
160
 
161
+ def _table_exists?
162
+ table_exists?
163
+ rescue => e
164
+ false
165
+ end
166
+
154
167
  def rails_initialized?
155
168
  Rails.application&.initialized?
156
169
  end
157
170
 
158
171
  def _all_settings
159
- raise "You cannot use settings before Rails initialize." unless rails_initialized?
160
-
161
- RequestStore.store[:rails_settings_all_settings] ||= begin
172
+ RequestCache.settings ||= begin
162
173
  Rails.cache.fetch(cache_key, expires_in: 1.week) do
163
174
  vars = unscoped.select("var, value")
164
175
  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.3"
6
+ "2.5.0"
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.3
4
+ version: 2.5.0
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-16 00:00:00.000000000 Z
11
+ date: 2020-12-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,22 +16,22 @@ 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
26
+ version: 5.0.0
27
27
  - !ruby/object:Gem::Dependency
28
- name: request_store
28
+ name: codecov
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - ">="
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
- type: :runtime
34
+ type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
@@ -39,7 +39,7 @@ dependencies:
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
- name: codecov
42
+ name: minitest
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
45
  - - ">="
@@ -53,7 +53,7 @@ dependencies:
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
56
- name: minitest
56
+ name: pg
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
59
  - - ">="
@@ -108,11 +108,11 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description: "\n This is improved from rails-settings, added caching.\n Settings
112
- plugin for Rails that makes managing a table of global key,\n value pairs easy.
113
- Think of it like a global Hash stored in you database,\n that uses simple ActiveRecord
114
- like methods for manipulation.\n\n Keep track of any global setting that you dont
115
- 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,
116
116
  numbers, arrays, or any object.\n "
117
117
  email: huacnlee@gmail.com
118
118
  executables: []
@@ -128,6 +128,7 @@ files:
128
128
  - lib/rails-settings-cached.rb
129
129
  - lib/rails-settings/base.rb
130
130
  - lib/rails-settings/railtie.rb
131
+ - lib/rails-settings/request_cache.rb
131
132
  - lib/rails-settings/version.rb
132
133
  homepage: https://github.com/huacnlee/rails-settings-cached
133
134
  licenses:
@@ -148,8 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
148
149
  - !ruby/object:Gem::Version
149
150
  version: '0'
150
151
  requirements: []
151
- rubygems_version: 3.0.3
152
+ rubygems_version: 3.0.8
152
153
  signing_key:
153
154
  specification_version: 4
154
- 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.
155
156
  test_files: []