rails-settings-cached 2.8.3 → 2.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 619f840c2f93682aec9caef59cb4a59404ce145fbb3b55e77dc259b0fc5b3abd
4
- data.tar.gz: c2b49addab5c52403dbb0c3f883276b4c06a870ae4466140b876444dcbaf371f
3
+ metadata.gz: 4f2fb5c3b8b6bd86c138a0650c9d0462df1bede6e446600d6fdfe7064c9d1d2c
4
+ data.tar.gz: ac5d5ab2b3f26bbdc92a3b5dbe7a879d8feb11d5a0bd664ce9e6cae87b79d336
5
5
  SHA512:
6
- metadata.gz: dcefa7f181b49c310ce6aff7bccb85e004c9048488f3a40cd24d0ed29b31d55d76cbfe6678f1c5eaf9ead4c4d84d1565ef1f0a00e04d02ed2fa58c6bfaf4c6dc
7
- data.tar.gz: 585da097235e2bccd5731500a4bb862a8bdfbc9996f9aa11938b9f6d7f0c5a75f2f88b68388a87bc3898496c1562a6fbf3652ac4b0b6b6610b03a1b1b1221fad
6
+ metadata.gz: 91aa31a22a69142164d52ee13792a6622b9a9088cd353ef9dd310919e60bbecf2be4a9c1ecd4a6729684fdd850cc1862988090143e78860ab46574d9573969b9
7
+ data.tar.gz: a2f5b013f134246ecb8f1a64a2ba0a3a947ae2fb6af1c06ad6b3d8f050d6de4fc05b7526fcc36ef72099095cde3975ef1e80e1fd11232dddfc1e29e5f14b5240
data/README.md CHANGED
@@ -161,6 +161,55 @@ Setting.get_field("default_locale")[:options]
161
161
  => { option_values: %w[en zh-CN jp], help_text: "Bla bla ..." }
162
162
  ```
163
163
 
164
+ ### Custom type for setting
165
+
166
+ > Since: 2.9.0
167
+
168
+ You can write your custom field type by under `RailsSettings::Fields` module.
169
+
170
+ #### For example
171
+
172
+ ```rb
173
+ module RailsSettings
174
+ module Fields
175
+ class YesNo < ::RailsSettings::Fields::Base
176
+ def serialize(value)
177
+ case value
178
+ when true then "YES"
179
+ when false then "NO"
180
+ else raise StandardError, 'invalid value'
181
+ end
182
+ end
183
+
184
+ def deserialize(value)
185
+ case value
186
+ when "YES" then true
187
+ when "NO" then false
188
+ else nil
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end
194
+ ```
195
+
196
+ Now you can use `yes_no` type in you setting:
197
+
198
+ ```rb
199
+ class Setting
200
+ field :custom_item, type: :yes_no, default: 'YES'
201
+ end
202
+ ```
203
+
204
+ ```rb
205
+ irb> Setting.custom_item = 'YES'
206
+ irb> Setting.custom_item
207
+ true
208
+ irb> Setting.custom_item = 'NO'
209
+ irb> Setting.custom_item
210
+ false
211
+ ```
212
+
164
213
  #### Get All defined fields
165
214
 
166
215
  > version 2.7.0+
@@ -8,7 +8,6 @@ module RailsSettings
8
8
  end
9
9
 
10
10
  class Base < ActiveRecord::Base
11
- SEPARATOR_REGEXP = /[\n,;]+/
12
11
  PROTECTED_KEYS = %w[var value]
13
12
  self.table_name = table_name_prefix + "settings"
14
13
 
@@ -55,7 +54,7 @@ module RailsSettings
55
54
  end
56
55
 
57
56
  def get_field(key)
58
- @defined_fields.find { |field| field[:key] == key.to_s } || {}
57
+ @defined_fields.find { |field| field.key == key.to_s }.to_h || {}
59
58
  end
60
59
 
61
60
  def cache_prefix(&block)
@@ -69,15 +68,15 @@ module RailsSettings
69
68
  end
70
69
 
71
70
  def keys
72
- @defined_fields.map { |field| field[:key] }
71
+ @defined_fields.map(&:key)
73
72
  end
74
73
 
75
74
  def editable_keys
76
- @defined_fields.reject { |field| field[:readonly] }.map { |field| field[:key] }
75
+ @defined_fields.reject(&:readonly).map(&:key)
77
76
  end
78
77
 
79
78
  def readonly_keys
80
- @defined_fields.select { |field| field[:readonly] }.map { |field| field[:key] }
79
+ @defined_fields.select(&:readonly).map(&:key)
81
80
  end
82
81
 
83
82
  attr_reader :defined_fields
@@ -89,56 +88,23 @@ module RailsSettings
89
88
 
90
89
  raise ProtectedKeyError.new(key) if PROTECTED_KEYS.include?(key)
91
90
 
91
+ field = ::RailsSettings::Fields::Base.generate(
92
+ scope: @scope, key: key, default: default,
93
+ type: type, readonly: readonly, options: opts,
94
+ separator: separator, parent: self
95
+ )
92
96
  @defined_fields ||= []
93
- @defined_fields << {
94
- scope: @scope,
95
- key: key,
96
- default: default,
97
- type: type || :string,
98
- readonly: readonly.nil? ? false : readonly,
99
- options: opts
100
- }
101
-
102
- if readonly
103
- define_singleton_method(key) do
104
- result = default.is_a?(Proc) ? default.call : default
105
- send(:_convert_string_to_typeof_value, type, result, separator: separator)
106
- end
107
- else
108
- define_singleton_method(key) do
109
- val = send(:_value_of, key)
110
- result = nil
111
- if !val.nil?
112
- result = val
113
- else
114
- result = default
115
- result = default.call if default.is_a?(Proc)
116
- end
117
-
118
- result = send(:_convert_string_to_typeof_value, type, result, separator: separator)
119
-
120
- result
121
- end
122
-
123
- define_singleton_method("#{key}=") do |value|
124
- var_name = key
125
-
126
- record = find_by(var: var_name) || new(var: var_name)
127
- value = send(:_convert_string_to_typeof_value, type, value, separator: separator)
97
+ @defined_fields << field
128
98
 
129
- record.value = value
130
- record.save!
99
+ define_singleton_method(key) { field.read }
131
100
 
132
- value
133
- end
101
+ unless readonly
102
+ define_singleton_method("#{key}=") { |value| field.save!(value: value) }
134
103
 
135
104
  if validates
136
105
  validates[:if] = proc { |item| item.var.to_s == key }
137
106
  send(:validates, key, **validates)
138
-
139
- define_method(:read_attribute_for_validation) do |_key|
140
- self.value
141
- end
107
+ define_method(:read_attribute_for_validation) { |_key| self.value }
142
108
  end
143
109
  end
144
110
 
@@ -156,49 +122,6 @@ module RailsSettings
156
122
  end
157
123
  end
158
124
 
159
- def _convert_string_to_typeof_value(type, value, separator: nil)
160
- return value unless [String, Integer, Float, BigDecimal].include?(value.class)
161
-
162
- case type
163
- when :boolean
164
- ["true", "1", 1, true].include?(value)
165
- when :array
166
- value.split(separator || SEPARATOR_REGEXP).reject { |str| str.empty? }.map(&:strip)
167
- when :hash
168
- value = begin
169
- YAML.safe_load(value).to_h
170
- rescue
171
- {}
172
- end
173
- value.deep_stringify_keys!
174
- ActiveSupport::HashWithIndifferentAccess.new(value)
175
- when :integer
176
- value.to_i
177
- when :float
178
- value.to_f
179
- when :big_decimal
180
- value.to_d
181
- else
182
- value
183
- end
184
- end
185
-
186
- def _value_of(var_name)
187
- unless _table_exists?
188
- # Fallback to default value if table was not ready (before migrate)
189
- puts "WARNING: table: \"#{table_name}\" does not exist or not database connection, `#{name}.#{var_name}` fallback to returns the default value."
190
- return nil
191
- end
192
-
193
- _all_settings[var_name]
194
- end
195
-
196
- def _table_exists?
197
- table_exists?
198
- rescue
199
- false
200
- end
201
-
202
125
  def rails_initialized?
203
126
  Rails.application&.initialized?
204
127
  end
@@ -0,0 +1,15 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class Array < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ return value unless value.is_a?(::String)
6
+
7
+ value.split(separator).reject(&:empty?).map(&:strip)
8
+ end
9
+
10
+ def serialize(value)
11
+ deserialize(value)
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,71 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class Base < Struct.new(:scope, :key, :default, :parent, :readonly, :separator, :type, :options, keyword_init: true)
4
+ SEPARATOR_REGEXP = /[\n,;]+/
5
+
6
+ def initialize(scope:, key:, default:, parent:, readonly:, separator:, type:, options:)
7
+ super
8
+ self.readonly = !!readonly
9
+ self.type ||= :string
10
+ self.separator ||= SEPARATOR_REGEXP
11
+ end
12
+
13
+ def save!(value:)
14
+ serialized_value = serialize(value)
15
+ parent_record = parent.find_by(var: key) || parent.new(var: key)
16
+ parent_record.value = serialized_value
17
+ parent_record.save!
18
+ parent_record.value
19
+ end
20
+
21
+ def saved_value
22
+ return parent.send(:_all_settings)[key] if table_exists?
23
+
24
+ # Fallback to default value if table was not ready (before migrate)
25
+ puts "WARNING: table: \"#{parent.table_name}\" does not exist or not database connection, `#{parent.name}.#{key}` fallback to returns the default value."
26
+ nil
27
+ end
28
+
29
+ def default_value
30
+ default.is_a?(Proc) ? default.call : default
31
+ end
32
+
33
+ def read
34
+ return deserialize(default_value) if readonly || saved_value.nil?
35
+
36
+ deserialize(saved_value)
37
+ end
38
+
39
+ def deserialize(value)
40
+ raise NotImplementedError
41
+ end
42
+
43
+ def serialize(value)
44
+ raise NotImplementedError
45
+ end
46
+
47
+ def to_h
48
+ super.slice(:scope, :key, :default, :type, :readonly, :options)
49
+ end
50
+
51
+ def table_exists?
52
+ parent.table_exists?
53
+ rescue StandardError
54
+ false
55
+ end
56
+
57
+ class << self
58
+ def generate(**args)
59
+ fetch_field_class(args[:type]).new(**args)
60
+ end
61
+
62
+ private
63
+
64
+ def fetch_field_class(type)
65
+ field_class_name = type.to_s.split('_').map(&:capitalize).join('')
66
+ const_get("::RailsSettings::Fields::#{field_class_name}")
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,13 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class BigDecimal < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ value.to_d
6
+ end
7
+
8
+ def serialize(value)
9
+ deserialize(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class Boolean < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ ["true", "1", 1, true].include?(value)
6
+ end
7
+
8
+ def serialize(value)
9
+ deserialize(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class Float < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ value.to_f
6
+ end
7
+
8
+ def serialize(value)
9
+ deserialize(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,21 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class Hash < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ return value unless value.is_a?(::String)
6
+
7
+ load_value(value).deep_stringify_keys.with_indifferent_access
8
+ end
9
+
10
+ def serialize(value)
11
+ deserialize(value)
12
+ end
13
+
14
+ def load_value(value)
15
+ YAML.safe_load(value).to_h
16
+ rescue StandardError
17
+ {}
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,13 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class Integer < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ value.to_i
6
+ end
7
+
8
+ def serialize(value)
9
+ deserialize(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ module RailsSettings
2
+ module Fields
3
+ class String < ::RailsSettings::Fields::Base
4
+ def deserialize(value)
5
+ value
6
+ end
7
+
8
+ def serialize(value)
9
+ deserialize(value)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -3,7 +3,7 @@
3
3
  module RailsSettings
4
4
  class << self
5
5
  def version
6
- "2.8.3"
6
+ "2.9.0"
7
7
  end
8
8
  end
9
9
  end
@@ -1,5 +1,14 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require_relative "rails-settings/fields/base"
4
+ require_relative "rails-settings/fields/array"
5
+ require_relative "rails-settings/fields/big_decimal"
6
+ require_relative "rails-settings/fields/boolean"
7
+ require_relative "rails-settings/fields/float"
8
+ require_relative "rails-settings/fields/hash"
9
+ require_relative "rails-settings/fields/integer"
10
+ require_relative "rails-settings/fields/string"
11
+
3
12
  require_relative "rails-settings/base"
4
13
  require_relative "rails-settings/request_cache"
5
14
  require_relative "rails-settings/middleware"
@@ -7,4 +16,6 @@ require_relative "rails-settings/railtie"
7
16
  require_relative "rails-settings/version"
8
17
 
9
18
  module RailsSettings
19
+ module Fields
20
+ end
10
21
  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.8.3
4
+ version: 2.9.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: 2022-12-19 00:00:00.000000000 Z
11
+ date: 2023-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: railties
@@ -127,6 +127,14 @@ files:
127
127
  - lib/generators/settings/templates/model.rb
128
128
  - lib/rails-settings-cached.rb
129
129
  - lib/rails-settings/base.rb
130
+ - lib/rails-settings/fields/array.rb
131
+ - lib/rails-settings/fields/base.rb
132
+ - lib/rails-settings/fields/big_decimal.rb
133
+ - lib/rails-settings/fields/boolean.rb
134
+ - lib/rails-settings/fields/float.rb
135
+ - lib/rails-settings/fields/hash.rb
136
+ - lib/rails-settings/fields/integer.rb
137
+ - lib/rails-settings/fields/string.rb
130
138
  - lib/rails-settings/middleware.rb
131
139
  - lib/rails-settings/railtie.rb
132
140
  - lib/rails-settings/request_cache.rb