-
Notifications
You must be signed in to change notification settings - Fork 202
/
base.rb
139 lines (110 loc) · 3.45 KB
/
base.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
# frozen_string_literal: true
module RailsSettings
class Base < ActiveRecord::Base
PROTECTED_KEYS = %w[var value]
self.table_name = table_name_prefix + "settings"
after_commit :clear_cache, on: %i[create update destroy]
# get the value field, YAML decoded
def value
# rubocop:disable Security/YAMLLoad
payload = self[:value]
if payload.present?
YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(payload) : YAML.load(payload)
end
end
# set the value field, YAML encoded
def value=(new_value)
self[:value] = new_value.to_yaml
end
def clear_cache
self.class.clear_cache
end
class << self
def clear_cache
RequestCache.reset
cache_storage.delete(cache_key)
end
def field(key, **opts)
_define_field(key, **opts)
end
alias_method :_rails_scope, :scope
def scope(*args, &block)
name = args.shift
body = args.shift
if body.respond_to?(:call)
return _rails_scope(name, body, &block)
end
@scope = name.to_sym
yield block
@scope = nil
end
def get_field(key)
@defined_fields.find { |field| field.key == key.to_s }.to_h || {}
end
def cache_prefix(&block)
@cache_prefix = block
end
def cache_key
key_parts = ["rails-settings-cached"]
key_parts << @cache_prefix.call if @cache_prefix
key_parts.join("/")
end
def keys
@defined_fields.map(&:key)
end
def editable_keys
@defined_fields.reject(&:readonly).map(&:key)
end
def readonly_keys
@defined_fields.select(&:readonly).map(&:key)
end
attr_reader :defined_fields
private
def _define_field(key, default: nil, type: :string, readonly: false, separator: nil, validates: nil, **opts)
key = key.to_s
raise ProtectedKeyError.new(key) if PROTECTED_KEYS.include?(key)
field = ::RailsSettings::Fields::Base.generate(
scope: @scope, key: key, default: default,
type: type, readonly: readonly, options: opts,
separator: separator, parent: self
)
@defined_fields ||= []
@defined_fields << field
define_singleton_method(key) { field.read }
unless readonly
define_singleton_method("#{key}=") { |value| field.save!(value: value) }
if validates
validates[:if] = proc { |item| item.var.to_s == key }
send(:validates, key, **validates)
define_method(:read_attribute_for_validation) { |_key| self.value }
end
end
if type == :boolean
define_singleton_method("#{key}?") do
send(key)
end
end
# delegate instance get method to class for support:
# setting = Setting.new
# setting.admin_emails
define_method(key) do
self.class.public_send(key)
end
end
def rails_initialized?
Rails.application&.initialized?
end
def _all_settings
RequestCache.all_settings ||= cache_storage.fetch(cache_key, expires_in: 1.week) do
vars = unscoped.select("var, value")
result = {}
vars.each { |record| result[record.var] = record.value }
result.with_indifferent_access
end
end
def cache_storage
RailsSettings.config.cache_storage
end
end
end
end