rails-settings-cached 2.3.4 → 2.5.1

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: '08fedca17d5c8848f9503a0b9a2d45403fd545406ec656d899af182334d6c3ac'
4
- data.tar.gz: 1b928531e53c09d4ac3c582785aad54dee23f81c00721857009c0495ee1a7f30
3
+ metadata.gz: 29703d30ef00244c99b49047ce3a05edd212ee71a23433cb581d5bf69c6a02c6
4
+ data.tar.gz: 7f1d2dffdf1c552faca1b7afdbaaeaa52039897afb5364b8aef37de3d93389c4
5
5
  SHA512:
6
- metadata.gz: 8f742e343ecfe97413a17aafefead8f5e49a49d407e269962a90e08a3f8ad89441f0ba95f4496a80b8528f68d5edecccf930f00af39627020d75a8e947ac28a5
7
- data.tar.gz: 970ef16a4a2f2c3c552f0d80d8386d5124e3821c0f9ed54d2ad3b0dd57e3c37a7cf94a6342c14d4cb585a6e188c2659ba13034607768eb2dfd29680c5c084a5f
6
+ metadata.gz: 6e1b41ac975dd31fadf90c5d9c059542aaeb09a0bfbf3f137266a32ae58c30557afedbe33c775af9a2683a8f8b56b85ee0f94b4a063a27e5c79176b5c1714d0d
7
+ data.tar.gz: a5ee74e8dd391aab429db68904b5d78a79581fd41de6304aece887fcdf9be8b023f4fff03a2fedbfdbc81cff964be5b695a90c5e4c3f908d49bed01c0fb70f83
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,58 @@ 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
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
- Sometimes you may need to use Setting before Rails is initialized, for example `config/devise.rb`
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.
203
+
204
+ For example `config/initializers/devise.rb`
157
205
 
158
206
  ```rb
159
207
  Devise.setup do |config|
@@ -163,37 +211,53 @@ Devise.setup do |config|
163
211
  end
164
212
  ```
165
213
 
166
- In this case, you must define the `readonly` field:
167
-
168
214
  ```rb
169
215
  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
216
+ field :omniauth_google_client_id, default: ENV["OMNIAUTH_GOOGLE_CLIENT_ID"]
217
+ field :omniauth_google_client_secret, default: ENV["OMNIAUTH_GOOGLE_CLIENT_SECRET"]
173
218
  end
174
219
  ```
175
220
 
176
- ## Use Setting in Rails initalizing:
221
+ ## Readonly field
177
222
 
178
- You can't use Setting in these locations:
223
+ You may also want use Setting before Rails initialize:
179
224
 
180
225
  ```
181
- config/application.rb
182
226
  config/environments/*.rb
183
227
  ```
184
228
 
185
- If you wants do that, put the setting into `config/initializers/*.rb`
229
+ If you want do that do that, the setting field must has `readonly: true`.
186
230
 
187
231
  For example:
188
232
 
189
233
  ```rb
190
- # config/initializers/devise.rb
191
- Devise.setup do |config|
192
- config.omniauth :twitter, Setting.twitter_api_key, Setting.twitter_api_secret
234
+ class Setting < RailsSettings::Base
235
+ field :mailer_provider, default: (ENV["mailer_provider"] || "smtp"), readonly: true
236
+ field :mailer_options, type: :hash, readonly: true, default: {
237
+ address: ENV["mailer_options.address"],
238
+ port: ENV["mailer_options.port"],
239
+ domain: ENV["mailer_options.domain"],
240
+ user_name: ENV["mailer_options.user_name"],
241
+ password: ENV["mailer_options.password"],
242
+ authentication: ENV["mailer_options.authentication"] || "login",
243
+ enable_starttls_auto: ENV["mailer_options.enable_starttls_auto"]
244
+ }
245
+ end
246
+ ```
247
+
248
+ config/environments/production.rb
249
+
250
+ ```rb
251
+ # You must require_relative directly in Rails 6.1+ in config/environments/production.rb
252
+ require_relative "../../app/models/setting"
253
+
254
+ Rails.application.configure do
255
+ config.action_mailer.delivery_method = :smtp
256
+ config.action_mailer.smtp_settings = Setting.mailer_options.deep_symbolize_keys
193
257
  end
194
258
  ```
195
259
 
196
- ### Caching flow:
260
+ ## Caching flow:
197
261
 
198
262
  ```
199
263
  Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
@@ -203,7 +267,7 @@ Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
203
267
  Return default value or nil
204
268
  ```
205
269
 
206
- 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.
207
271
 
208
272
  Each key update will expire the cache, so do not add some frequent update key.
209
273
 
@@ -228,7 +292,7 @@ class ActiveSupport::TestCase
228
292
  end
229
293
  ```
230
294
 
231
- -----
295
+ ---
232
296
 
233
297
  ## How to manage Settings in the admin interface?
234
298
 
@@ -242,19 +306,32 @@ namespace :admin do
242
306
  end
243
307
  ```
244
308
 
245
-
246
309
  app/controllers/admin/settings_controller.rb
247
310
 
248
311
  ```rb
249
312
  module Admin
250
313
  class SettingsController < ApplicationController
251
- before_action :get_setting, only: [:edit, :update]
252
-
253
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
+
254
330
  setting_params.keys.each do |key|
255
331
  Setting.send("#{key}=", setting_params[key].strip) unless setting_params[key].nil?
256
332
  end
257
- redirect_to settings_path, notice: "Setting was successfully updated."
333
+
334
+ redirect_to admin_settings_path, notice: "Setting was successfully updated."
258
335
  end
259
336
 
260
337
  private
@@ -270,6 +347,16 @@ app/views/admin/settings/show.html.erb
270
347
 
271
348
  ```erb
272
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
+
273
360
  <div class="form-group">
274
361
  <label class="control-label">Host</label>
275
362
  <%= f.text_field :host, value: Setting.host, class: "form-control", placeholder: "http://localhost" %>
@@ -335,9 +422,11 @@ end
335
422
  - [forem/forem](https://github.com/forem/forem) - 2.x
336
423
  - [siwapp/siwapp](https://github.com/siwapp/siwapp) - 2.x
337
424
  - [aidewoode/black_candy](https://github.com/aidewoode/black_candy) - 2.x
338
- - [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
339
428
  - [tootsuite/mastodon](https://github.com/tootsuite/mastodon) - 0.6.x
340
429
  - [helpyio/helpy](https://github.com/helpyio/helpy) - 0.5.x
341
-
430
+ - [daqing/rabel](https://github.com/daqing/rabel) - 0.4.x
342
431
 
343
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,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,
@@ -101,6 +99,15 @@ module RailsSettings
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,20 +149,19 @@ 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
- rescue => e
153
- if e.message.include?("connect")
154
- puts "WARNING: `#{name}.#{var_name}` called but no connection, fallback to returns the default value."
155
- return nil
156
- end
159
+ end
157
160
 
158
- raise e
161
+ def _table_exists?
162
+ table_exists?
163
+ rescue => e
164
+ false
159
165
  end
160
166
 
161
167
  def rails_initialized?
@@ -163,7 +169,7 @@ module RailsSettings
163
169
  end
164
170
 
165
171
  def _all_settings
166
- RequestStore.store[:rails_settings_all_settings] ||= begin
172
+ RequestCache.settings ||= begin
167
173
  Rails.cache.fetch(cache_key, expires_in: 1.week) do
168
174
  vars = unscoped.select("var, value")
169
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.4"
6
+ "2.5.1"
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.4
4
+ version: 2.5.1
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-09 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.2.0
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: []