rails-settings-cached 2.4.0 → 2.5.3

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: 603b7101883a17d76bfb33682ce421b7259101bfc7d3b0fea450d02466adcb03
4
- data.tar.gz: '088348b905fba8727569b052468ca194c74fcde740976e0d4cfe6b780063144f'
3
+ metadata.gz: fc604a3e9ea5a7ed498250820ca7e93ec44e38adb88380b24b0f7b2d5dc164b8
4
+ data.tar.gz: 9e62d3f49c59e981655a22924d2c32d346ba4618a6c98b4b8b1a0dfb6fd6db24
5
5
  SHA512:
6
- metadata.gz: eeaed942036ec6c70fbd0f8a687000032e87cbef17324eca6329c32e1f7b69b6f38a7d295ec00441ec1fd1601f53c8cbe162df33e0f5d4f518658f6cb3236835
7
- data.tar.gz: 13f87d6cac9234fcf48b50b3e67723aac4977d4a9e8fb71528bf8d12fd29eb27372d9b5705a496f694550ad988dba613f9dc3bf069fa699a910ebd1f4c5b8506
6
+ metadata.gz: 7bfc23cb9fadddad15c1f3c341973bae5571cdb324ebb7d71f8c075c3877912d7f40b2792cbeaa582a79f22bcde166def831506c95d90444cd7193077492d4a7
7
+ data.tar.gz: dc55136872ad58751d08f745d93a7707e3e815f6ffc99adcc5d63b19e980594a7874c11484976b7342932ca511ace408c8d48bdd5de5666854b544d908345678
data/README.md CHANGED
@@ -1,12 +1,12 @@
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.
8
4
 
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)
5
+ This gem will make 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
+
9
+ [![Gem Version](https://badge.fury.io/rb/rails-settings-cached.svg)](https://rubygems.org/gems/rails-settings-cached) [![build](https://github.com/huacnlee/rails-settings-cached/workflows/build/badge.svg)](https://github.com/huacnlee/rails-settings-cached/actions?query=workflow%3Abuild) [![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
 
11
11
  ## Installation
12
12
 
@@ -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
 
@@ -150,9 +150,56 @@ Setting.get_field("app_name")
150
150
  => { key: "app_name", type: :string, default: "Rails Settings", readonly: false }
151
151
  ```
152
152
 
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:
166
+
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
+
153
200
  ## Use Setting in Rails initializing:
154
201
 
155
- In `version 2.3+` we allows you to use Setting before Rails is initialized.
202
+ In `version 2.3+` you can use Setting before Rails is initialized.
156
203
 
157
204
  For example `config/initializers/devise.rb`
158
205
 
@@ -265,9 +312,25 @@ app/controllers/admin/settings_controller.rb
265
312
  module Admin
266
313
  class SettingsController < ApplicationController
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
333
+
271
334
  redirect_to admin_settings_path, notice: "Setting was successfully updated."
272
335
  end
273
336
 
@@ -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,8 +422,12 @@ 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
428
+ - [texterify/texterify](https://github.com/texterify/texterify) - 2.x
353
429
  - [tootsuite/mastodon](https://github.com/tootsuite/mastodon) - 0.6.x
354
430
  - [helpyio/helpy](https://github.com/helpyio/helpy) - 0.5.x
431
+ - [daqing/rabel](https://github.com/daqing/rabel) - 0.4.x
355
432
 
356
433
  And more than [1K repositories](https://github.com/huacnlee/rails-settings-cached/network/dependents) used.
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require_relative "rails-settings/base"
4
- require_relative "rails-settings/request_store"
4
+ require_relative "rails-settings/request_cache"
5
5
  require_relative "rails-settings/railtie"
6
6
  require_relative "rails-settings/version"
7
7
 
@@ -4,11 +4,12 @@ module RailsSettings
4
4
  class Base < ActiveRecord::Base
5
5
  class SettingNotFound < RuntimeError; end
6
6
 
7
- SEPARATOR_REGEXP = /[\n,;]+/.freeze
7
+ SEPARATOR_REGEXP = /[\n,;]+/
8
8
  self.table_name = table_name_prefix + "settings"
9
9
 
10
10
  # get the value field, YAML decoded
11
11
  def value
12
+ # rubocop:disable Security/YAMLLoad
12
13
  YAML.load(self[:value]) if self[:value].present?
13
14
  end
14
15
 
@@ -23,12 +24,13 @@ module RailsSettings
23
24
 
24
25
  class << self
25
26
  def clear_cache
26
- RequestStore.reset
27
+ RequestCache.reset
27
28
  Rails.cache.delete(cache_key)
28
29
  end
29
30
 
30
31
  def field(key, **opts)
31
- _define_field(key, default: opts[:default], type: opts[:type], readonly: opts[:readonly], separator: opts[:separator])
32
+ _define_field(key, default: opts[:default], type: opts[:type], readonly: opts[:readonly],
33
+ separator: opts[:separator], validates: opts[:validates])
32
34
  end
33
35
 
34
36
  def get_field(key)
@@ -59,10 +61,12 @@ module RailsSettings
59
61
 
60
62
  private
61
63
 
62
- def _define_field(key, default: nil, type: :string, readonly: false, separator: nil)
64
+ def _define_field(key, default: nil, type: :string, readonly: false, separator: nil, validates: nil)
65
+ key = key.to_s
66
+
63
67
  @defined_fields ||= []
64
68
  @defined_fields << {
65
- key: key.to_s,
69
+ key: key,
66
70
  default: default,
67
71
  type: type || :string,
68
72
  readonly: readonly.nil? ? false : readonly
@@ -70,7 +74,8 @@ module RailsSettings
70
74
 
71
75
  if readonly
72
76
  define_singleton_method(key) do
73
- send(:_convert_string_to_typeof_value, type, default, separator: separator)
77
+ result = default.is_a?(Proc) ? default.call : default
78
+ send(:_convert_string_to_typeof_value, type, result, separator: separator)
74
79
  end
75
80
  else
76
81
  define_singleton_method(key) do
@@ -89,7 +94,7 @@ module RailsSettings
89
94
  end
90
95
 
91
96
  define_singleton_method("#{key}=") do |value|
92
- var_name = key.to_s
97
+ var_name = key
93
98
 
94
99
  record = find_by(var: var_name) || new(var: var_name)
95
100
  value = send(:_convert_string_to_typeof_value, type, value, separator: separator)
@@ -99,6 +104,15 @@ module RailsSettings
99
104
 
100
105
  value
101
106
  end
107
+
108
+ if validates
109
+ validates[:if] = proc { |item| item.var.to_s == key }
110
+ send(:validates, key, **validates)
111
+
112
+ define_method(:read_attribute_for_validation) do |_key|
113
+ self.value
114
+ end
115
+ end
102
116
  end
103
117
 
104
118
  if type == :boolean
@@ -113,19 +127,15 @@ module RailsSettings
113
127
 
114
128
  case type
115
129
  when :boolean
116
- value == "true" || value == "1" || value == 1 || value == true
130
+ ["true", "1", 1, true].include?(value)
117
131
  when :array
118
132
  value.split(separator || SEPARATOR_REGEXP).reject { |str| str.empty? }.map(&:strip)
119
133
  when :hash
120
134
  value = begin
121
- begin
122
- YAML.load(value).to_h
123
- rescue StandardError
124
- eval(value).to_h
125
- end
126
- rescue StandardError
127
- {}
128
- end
135
+ YAML.safe_load(value).to_h
136
+ rescue
137
+ {}
138
+ end
129
139
  value.deep_stringify_keys!
130
140
  ActiveSupport::HashWithIndifferentAccess.new(value)
131
141
  when :integer
@@ -146,12 +156,12 @@ module RailsSettings
146
156
  return nil
147
157
  end
148
158
 
149
- _all_settings[var_name.to_s]
159
+ _all_settings[var_name]
150
160
  end
151
161
 
152
162
  def _table_exists?
153
163
  table_exists?
154
- rescue => e
164
+ rescue
155
165
  false
156
166
  end
157
167
 
@@ -160,13 +170,11 @@ module RailsSettings
160
170
  end
161
171
 
162
172
  def _all_settings
163
- RequestStore.settings ||= begin
164
- Rails.cache.fetch(cache_key, expires_in: 1.week) do
165
- vars = unscoped.select("var, value")
166
- result = {}
167
- vars.each { |record| result[record.var] = record.value }
168
- result.with_indifferent_access
169
- end
173
+ RequestCache.settings ||= Rails.cache.fetch(cache_key, expires_in: 1.week) do
174
+ vars = unscoped.select("var, value")
175
+ result = {}
176
+ vars.each { |record| result[record.var] = record.value }
177
+ result.with_indifferent_access
170
178
  end
171
179
  end
172
180
  end
@@ -3,7 +3,7 @@
3
3
  module RailsSettings
4
4
  class Railtie < Rails::Railtie
5
5
  initializer "rails_settings.active_record.initialization" do
6
- RailsSettings::Base.after_commit :clear_cache, on: %i(create update destroy)
6
+ RailsSettings::Base.after_commit :clear_cache, on: %i[create update destroy]
7
7
  end
8
8
  end
9
9
  end
@@ -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.4.0"
6
+ "2.5.3"
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.4.0
4
+ version: 2.5.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Lee
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-12-03 00:00:00.000000000 Z
11
+ date: 2021-06-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +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
26
+ version: 5.0.0
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: codecov
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -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,13 +128,13 @@ 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_store.rb
131
+ - lib/rails-settings/request_cache.rb
132
132
  - lib/rails-settings/version.rb
133
133
  homepage: https://github.com/huacnlee/rails-settings-cached
134
134
  licenses:
135
135
  - MIT
136
136
  metadata: {}
137
- post_install_message:
137
+ post_install_message:
138
138
  rdoc_options: []
139
139
  require_paths:
140
140
  - lib
@@ -149,8 +149,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
149
149
  - !ruby/object:Gem::Version
150
150
  version: '0'
151
151
  requirements: []
152
- rubygems_version: 3.1.2
153
- signing_key:
152
+ rubygems_version: 3.2.3
153
+ signing_key:
154
154
  specification_version: 4
155
- 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.
156
156
  test_files: []
@@ -1,8 +0,0 @@
1
- module RailsSettings
2
- # For storage all settings in Current, it will reset after per request completed.
3
- # Base on ActiveSupport::CurrentAttributes
4
- # https://api.rubyonrails.org/classes/ActiveSupport/CurrentAttributes.html
5
- class RequestStore < ActiveSupport::CurrentAttributes
6
- attribute :settings
7
- end
8
- end