activeadmin_settings_cached 2.2.0 → 3.0.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 +5 -5
- data/.github/stale.yml +17 -0
- data/.github/workflows/ci.yml +27 -0
- data/Appraisals +4 -12
- data/CHANGELOG.md +24 -0
- data/Dockerfile +3 -16
- data/Gemfile +5 -1
- data/Makefile +14 -3
- data/README.md +61 -15
- data/activeadmin_settings_cached.gemspec +3 -7
- data/app/views/admin/settings/_index.html.erb +20 -13
- data/config/locales/de.yml +1 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/ru.yml +1 -0
- data/docker-compose.yml +9 -5
- data/gemfiles/{rails4.2.gemfile → rails7.2.gemfile} +4 -2
- data/gemfiles/rails8.0.gemfile +14 -0
- data/lib/activeadmin_settings_cached/dsl.rb +17 -9
- data/lib/activeadmin_settings_cached/engine.rb +0 -3
- data/lib/activeadmin_settings_cached/model.rb +64 -67
- data/lib/activeadmin_settings_cached/options.rb +1 -2
- data/lib/activeadmin_settings_cached/version.rb +1 -1
- data/lib/activeadmin_settings_cached.rb +3 -0
- data/spec/model_spec.rb +75 -120
- data/spec/settings_spec.rb +112 -195
- data/spec/spec_helper.rb +3 -26
- data/spec/support/admin.rb +3 -10
- data/spec/support/rails_template.rb +36 -22
- data/tasks/test.rake +4 -6
- metadata +23 -80
- data/.travis.yml +0 -17
- data/gemfiles/rails5.0.gemfile +0 -14
- data/gemfiles/rails5.1.gemfile +0 -14
- data/lib/activeadmin_settings_cached/coercions.rb +0 -57
- data/spec/coercions_spec.rb +0 -80
|
@@ -4,6 +4,8 @@ module ActiveadminSettingsCached
|
|
|
4
4
|
class Model
|
|
5
5
|
include ::ActiveModel::Model
|
|
6
6
|
|
|
7
|
+
NUMERIC_TYPES = %i[integer float big_decimal].freeze
|
|
8
|
+
|
|
7
9
|
attr_reader :attributes
|
|
8
10
|
|
|
9
11
|
def initialize(args = {})
|
|
@@ -13,71 +15,68 @@ module ActiveadminSettingsCached
|
|
|
13
15
|
assign_attributes(merge_attributes(args))
|
|
14
16
|
end
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
+
# Editable fields grouped by rails-settings-cached scope
|
|
19
|
+
def fields_by_scope
|
|
20
|
+
fields.group_by { |field| field[:scope] }
|
|
18
21
|
end
|
|
19
22
|
|
|
20
|
-
def
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
{
|
|
26
|
-
collection: default_value,
|
|
27
|
-
selected: value,
|
|
28
|
-
}
|
|
29
|
-
elsif (default_value.is_a?(TrueClass) || default_value.is_a?(FalseClass)) &&
|
|
30
|
-
display[settings_name].to_s == 'boolean'
|
|
31
|
-
{
|
|
32
|
-
input_html: { checked: value }, label: '', checked_value: 'true', unchecked_value: 'false'
|
|
33
|
-
}
|
|
34
|
-
else
|
|
35
|
-
{
|
|
36
|
-
input_html: { value: value, placeholder: default_value },
|
|
37
|
-
}
|
|
38
|
-
end
|
|
23
|
+
def fields
|
|
24
|
+
settings_model.editable_keys.map { |key| settings_model.get_field(key) }.select do |field|
|
|
25
|
+
scopes.nil? || scopes.include?(field[:scope])
|
|
26
|
+
end
|
|
27
|
+
end
|
|
39
28
|
|
|
40
|
-
|
|
41
|
-
|
|
29
|
+
def keys
|
|
30
|
+
fields.map { |field| field[:key] }
|
|
42
31
|
end
|
|
43
32
|
|
|
44
|
-
def
|
|
45
|
-
|
|
46
|
-
|
|
33
|
+
def field_options(key)
|
|
34
|
+
field = settings_model.get_field(key)
|
|
35
|
+
options = field[:options] || {}
|
|
36
|
+
input_html = { value: form_value(key), placeholder: format_value(field[:type], default(field)) }
|
|
47
37
|
|
|
48
|
-
|
|
49
|
-
|
|
38
|
+
input_opts = if options[:option_values]
|
|
39
|
+
{ as: :select, collection: options[:option_values], selected: value(key), include_blank: false }
|
|
40
|
+
else
|
|
41
|
+
case field[:type]
|
|
42
|
+
when :boolean
|
|
43
|
+
# Formtastic nests the checkbox into its label, so blank it
|
|
44
|
+
{ as: :boolean, label: '', input_html: { checked: value(key) },
|
|
45
|
+
checked_value: 'true', unchecked_value: 'false' }
|
|
46
|
+
when :array, :hash
|
|
47
|
+
{ as: :text, input_html: input_html.merge(rows: 5) }
|
|
48
|
+
when *NUMERIC_TYPES
|
|
49
|
+
{ as: :number, input_html: input_html }
|
|
50
|
+
else
|
|
51
|
+
{ as: :string, input_html: input_html }
|
|
52
|
+
end
|
|
53
|
+
end
|
|
50
54
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
settings_model.defaults :
|
|
54
|
-
::RailsSettings::Default
|
|
55
|
-
end
|
|
55
|
+
input_opts[:hint] = options[:help_text] if options[:help_text]
|
|
56
|
+
input_opts[:as] = display[key] if display[key]
|
|
56
57
|
|
|
57
|
-
|
|
58
|
-
settings_model.respond_to?(:defaults) ?
|
|
59
|
-
settings_model.defaults.keys :
|
|
60
|
-
::RailsSettings::Default.instance.keys
|
|
58
|
+
{ label: false }.merge(input_opts)
|
|
61
59
|
end
|
|
62
60
|
|
|
63
|
-
def
|
|
64
|
-
|
|
61
|
+
def value(key)
|
|
62
|
+
settings_model.public_send(key)
|
|
65
63
|
end
|
|
66
64
|
|
|
67
|
-
|
|
68
|
-
|
|
65
|
+
# Value as rendered in the form, used to detect changes on save
|
|
66
|
+
def form_value(key)
|
|
67
|
+
format_value(settings_model.get_field(key)[:type], value(key))
|
|
69
68
|
end
|
|
70
69
|
|
|
71
|
-
def
|
|
72
|
-
|
|
70
|
+
def changed?(key, input)
|
|
71
|
+
normalize(input) != normalize(form_value(key))
|
|
73
72
|
end
|
|
74
73
|
|
|
75
74
|
def save(key, value)
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
75
|
+
settings_model.public_send("#{key}=", value)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def display
|
|
79
|
+
attributes[:display]
|
|
81
80
|
end
|
|
82
81
|
|
|
83
82
|
def persisted?
|
|
@@ -86,22 +85,29 @@ module ActiveadminSettingsCached
|
|
|
86
85
|
|
|
87
86
|
alias_method :to_hash, :attributes
|
|
88
87
|
|
|
89
|
-
|
|
88
|
+
private
|
|
90
89
|
|
|
91
|
-
def
|
|
92
|
-
|
|
90
|
+
def scopes
|
|
91
|
+
Array(attributes[:scope]).map(&:to_sym).presence
|
|
93
92
|
end
|
|
94
93
|
|
|
95
|
-
def
|
|
96
|
-
|
|
94
|
+
def default(field)
|
|
95
|
+
field[:default].is_a?(Proc) ? field[:default].call : field[:default]
|
|
97
96
|
end
|
|
98
97
|
|
|
99
|
-
def
|
|
100
|
-
|
|
98
|
+
def format_value(type, value)
|
|
99
|
+
case type
|
|
100
|
+
when :array
|
|
101
|
+
Array(value).join("\n")
|
|
102
|
+
when :hash
|
|
103
|
+
value.blank? ? '' : value.to_hash.deep_stringify_keys.to_yaml.sub(/\A---\n/, '')
|
|
104
|
+
else
|
|
105
|
+
value.to_s
|
|
106
|
+
end
|
|
101
107
|
end
|
|
102
108
|
|
|
103
|
-
def
|
|
104
|
-
|
|
109
|
+
def normalize(value)
|
|
110
|
+
value.to_s.gsub("\r\n", "\n").strip
|
|
105
111
|
end
|
|
106
112
|
|
|
107
113
|
def assign_attributes(args = {})
|
|
@@ -110,8 +116,7 @@ module ActiveadminSettingsCached
|
|
|
110
116
|
|
|
111
117
|
def default_attributes
|
|
112
118
|
{
|
|
113
|
-
|
|
114
|
-
key: nil,
|
|
119
|
+
scope: nil,
|
|
115
120
|
model_name: ::ActiveadminSettingsCached.config.model_name,
|
|
116
121
|
display: ::ActiveadminSettingsCached.config.display
|
|
117
122
|
}
|
|
@@ -126,13 +131,5 @@ module ActiveadminSettingsCached
|
|
|
126
131
|
def settings_model
|
|
127
132
|
attributes[:model_name]
|
|
128
133
|
end
|
|
129
|
-
|
|
130
|
-
def meth
|
|
131
|
-
if Rails.version >= '4.1.0'
|
|
132
|
-
:get_all
|
|
133
|
-
else
|
|
134
|
-
:all
|
|
135
|
-
end
|
|
136
|
-
end
|
|
137
134
|
end
|
|
138
135
|
end
|
data/spec/model_spec.rb
CHANGED
|
@@ -9,165 +9,120 @@ RSpec.describe ActiveadminSettingsCached::Model do
|
|
|
9
9
|
end
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
before
|
|
13
|
-
|
|
14
|
-
'first_setting' => 'CCC',
|
|
15
|
-
'second_setting' => true
|
|
16
|
-
})
|
|
12
|
+
before do
|
|
13
|
+
ActiveadminSettingsCached.config.display = {}
|
|
17
14
|
end
|
|
18
15
|
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
model_name: 'Setting',
|
|
22
|
-
starting_with: 'base.',
|
|
23
|
-
key: nil,
|
|
24
|
-
display: {'base.first_setting' => 'string', 'base.second_setting' => 'boolean'}
|
|
25
|
-
}
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
let(:key_options) do
|
|
29
|
-
{
|
|
30
|
-
model_name: 'Setting',
|
|
31
|
-
starting_with: nil,
|
|
32
|
-
key: 'some',
|
|
33
|
-
display: {'some.first_setting' => 'string', 'base.second_setting' => 'boolean'}
|
|
34
|
-
}
|
|
35
|
-
end
|
|
16
|
+
subject(:object) { described_class.new(options) }
|
|
36
17
|
|
|
37
|
-
let(:
|
|
38
|
-
{}
|
|
39
|
-
end
|
|
18
|
+
let(:options) { { model_name: 'Setting', scope: :base, display: { 'title' => 'text' } } }
|
|
40
19
|
|
|
41
20
|
context '#attributes' do
|
|
42
|
-
before do
|
|
43
|
-
ActiveadminSettingsCached.config.display = {}
|
|
44
|
-
end
|
|
45
|
-
|
|
46
21
|
it 'set options' do
|
|
47
|
-
object = described_class.new(all_options)
|
|
48
22
|
expect(object.attributes).to eq({
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
})
|
|
23
|
+
scope: :base,
|
|
24
|
+
model_name: Setting,
|
|
25
|
+
display: { 'title' => 'text' }
|
|
26
|
+
})
|
|
54
27
|
end
|
|
55
28
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
expect(object.attributes).to eq({
|
|
59
|
-
starting_with: nil,
|
|
60
|
-
key: nil,
|
|
61
|
-
model_name: Setting,
|
|
62
|
-
display: {}
|
|
63
|
-
})
|
|
64
|
-
end
|
|
29
|
+
context 'without options' do
|
|
30
|
+
let(:options) { {} }
|
|
65
31
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
})
|
|
32
|
+
it 'set default options' do
|
|
33
|
+
expect(object.attributes).to eq({
|
|
34
|
+
scope: nil,
|
|
35
|
+
model_name: Setting,
|
|
36
|
+
display: {}
|
|
37
|
+
})
|
|
38
|
+
end
|
|
74
39
|
end
|
|
75
40
|
end
|
|
76
41
|
|
|
77
|
-
context '#
|
|
78
|
-
it '
|
|
79
|
-
object
|
|
80
|
-
expect(object.field_name('first_setting')).to eq('some.first_setting')
|
|
42
|
+
context '#keys' do
|
|
43
|
+
it 'returns editable keys of scope' do
|
|
44
|
+
expect(object.keys).to eq %w[title captcha_enabled user_limit tax_rate default_locale]
|
|
81
45
|
end
|
|
82
46
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
47
|
+
context 'with several scopes' do
|
|
48
|
+
let(:options) { { scope: %i[base second] } }
|
|
49
|
+
|
|
50
|
+
it { expect(object.keys).to include('title', 'admin_emails') }
|
|
51
|
+
it { expect(object.keys).not_to include('app_name', 'secret') }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
context 'without scope' do
|
|
55
|
+
let(:options) { {} }
|
|
56
|
+
|
|
57
|
+
it { expect(object.keys).to include('app_name', 'title', 'admin_emails') }
|
|
58
|
+
it { expect(object.keys).not_to include('secret') }
|
|
86
59
|
end
|
|
87
60
|
end
|
|
88
61
|
|
|
89
|
-
context '#
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
input_html: {value: 'AAA', placeholder: 'AAA'}
|
|
95
|
-
})
|
|
62
|
+
context '#fields_by_scope' do
|
|
63
|
+
let(:options) { {} }
|
|
64
|
+
|
|
65
|
+
it 'groups fields' do
|
|
66
|
+
expect(object.fields_by_scope.keys).to eq [nil, :base, :second]
|
|
96
67
|
end
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
context '#field_options' do
|
|
71
|
+
let(:options) { {} }
|
|
97
72
|
|
|
98
|
-
it 'with
|
|
99
|
-
object
|
|
100
|
-
|
|
101
|
-
label: false,
|
|
102
|
-
input_html: {value: 'CCC', placeholder: 'AAA'}
|
|
103
|
-
})
|
|
73
|
+
it 'with string element' do
|
|
74
|
+
expect(object.field_options('app_name')).to eq(as: :string, label: false,
|
|
75
|
+
input_html: { value: 'AAA', placeholder: 'AAA' })
|
|
104
76
|
end
|
|
105
77
|
|
|
106
|
-
it 'with
|
|
107
|
-
object
|
|
108
|
-
|
|
109
|
-
'base.six_setting' => 'array'}}))
|
|
110
|
-
expect(object.field_options('base.six_setting', 'base.six_setting')).to eq({as: 'array',
|
|
111
|
-
label: false,
|
|
112
|
-
collection: %w(a b),
|
|
113
|
-
selected: %w(a b)
|
|
114
|
-
})
|
|
78
|
+
it 'with number element' do
|
|
79
|
+
expect(object.field_options('user_limit')).to eq(as: :number, label: false,
|
|
80
|
+
input_html: { value: '5', placeholder: '5' })
|
|
115
81
|
end
|
|
116
82
|
|
|
117
83
|
it 'with boolean element' do
|
|
118
|
-
object
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
input_html: {checked: true},
|
|
122
|
-
checked_value: 'true',
|
|
123
|
-
unchecked_value: 'false'
|
|
124
|
-
})
|
|
84
|
+
expect(object.field_options('captcha_enabled')).to eq(as: :boolean, label: '',
|
|
85
|
+
input_html: { checked: true },
|
|
86
|
+
checked_value: 'true', unchecked_value: 'false')
|
|
125
87
|
end
|
|
126
|
-
end
|
|
127
88
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
89
|
+
it 'with select element' do
|
|
90
|
+
expect(object.field_options('default_locale')).to eq(as: :select, label: false, collection: %w[en de ru],
|
|
91
|
+
selected: 'en', include_blank: false,
|
|
92
|
+
hint: 'Interface language')
|
|
132
93
|
end
|
|
133
94
|
|
|
134
|
-
it '
|
|
135
|
-
object
|
|
136
|
-
|
|
95
|
+
it 'with array element' do
|
|
96
|
+
expect(object.field_options('admin_emails')).to eq(as: :text, label: false,
|
|
97
|
+
input_html: { value: "a@example.com\nb@example.com",
|
|
98
|
+
placeholder: "a@example.com\nb@example.com",
|
|
99
|
+
rows: 5 })
|
|
137
100
|
end
|
|
138
|
-
end
|
|
139
101
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
object = described_class.new(all_options)
|
|
143
|
-
object.save('base.first_setting', 'DDD')
|
|
144
|
-
expect(Setting['base.first_setting']).to eq('DDD')
|
|
102
|
+
it 'with hash element' do
|
|
103
|
+
expect(object.field_options('notification_options')[:input_html][:value]).to eq("send_all: true\n")
|
|
145
104
|
end
|
|
146
105
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
expect(
|
|
106
|
+
context 'with display option' do
|
|
107
|
+
let(:options) { { display: { title: :text } } }
|
|
108
|
+
|
|
109
|
+
it { expect(object.field_options('title')[:as]).to eq :text }
|
|
151
110
|
end
|
|
152
111
|
end
|
|
153
112
|
|
|
154
|
-
context '#
|
|
155
|
-
|
|
156
|
-
object = described_class.new(all_options)
|
|
157
|
-
expect(object.defaults).to eq(RailsSettings::Default)
|
|
158
|
-
end
|
|
113
|
+
context '#changed?' do
|
|
114
|
+
let(:options) { {} }
|
|
159
115
|
|
|
160
|
-
it '
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
end
|
|
116
|
+
it { expect(object.changed?('user_limit', '5')).to eq false }
|
|
117
|
+
it { expect(object.changed?('user_limit', '6')).to eq true }
|
|
118
|
+
it { expect(object.changed?('captcha_enabled', 'true')).to eq false }
|
|
119
|
+
it { expect(object.changed?('admin_emails', "a@example.com\r\nb@example.com\r\n")).to eq false }
|
|
165
120
|
end
|
|
166
121
|
|
|
167
|
-
context '#
|
|
168
|
-
it '
|
|
169
|
-
object
|
|
170
|
-
expect(
|
|
122
|
+
context '#save' do
|
|
123
|
+
it 'saves value' do
|
|
124
|
+
object.save('user_limit', '10')
|
|
125
|
+
expect(Setting.user_limit).to eq 10
|
|
171
126
|
end
|
|
172
127
|
end
|
|
173
128
|
|