rails-settings-cached 0.7.2 → 2.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 +4 -4
- data/MIT-LICENSE +21 -0
- data/README.md +121 -172
- data/Rakefile +30 -0
- data/lib/generators/settings/install_generator.rb +2 -1
- data/lib/generators/settings/templates/migration.rb +1 -3
- data/lib/generators/settings/templates/model.rb +6 -3
- data/lib/rails-settings/base.rb +100 -23
- data/lib/rails-settings/railtie.rb +3 -2
- data/lib/rails-settings/version.rb +3 -1
- data/lib/rails-settings-cached.rb +2 -4
- metadata +11 -18
- data/lib/generators/settings/templates/app.yml +0 -13
- data/lib/rails-settings/default.rb +0 -40
- data/lib/rails-settings/extend.rb +0 -34
- data/lib/rails-settings/scoped_settings.rb +0 -12
- data/lib/rails-settings/settings.rb +0 -120
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e89d0b87824703140e5d9182ade7936b22045bde791ba86d805dfbde9614f7b7
|
4
|
+
data.tar.gz: 2a3643dd2c6b3b837c3a4b1361651ca0a5b468336e038a38d1aaaa3bc659e151
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e6b9209c170d1b5d34b62496533936c4e8598bc963fb5bd1fbb3a8c5b86424e6c7986fb300eb4aebc89ce7e13f86d083588bef06e93c5c6927b18ccf2465e5e6
|
7
|
+
data.tar.gz: 7b7b05d0794663008292b3630c99c160f8fc54cc0b9e8b958d46052cb63ce94f9eff4d012d06b2676551cfc805502d890e5313a887d3611bfb6fdbd0ffb2d3d9
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
Copyright (c) 2006 Alex Wayne
|
2
|
+
Some additional features added 2009 by Georg Ledermann
|
3
|
+
|
4
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
5
|
+
a copy of this software and associated documentation files (the
|
6
|
+
"Software"), to deal in the Software without restriction, including
|
7
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
8
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
9
|
+
permit persons to whom the Software is furnished to do so, subject to
|
10
|
+
the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be
|
13
|
+
included in all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
16
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
17
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOa AND
|
18
|
+
NONINFRINGEMENT. IN NO EVENT SaALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
19
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
20
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
21
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
# Rails Settings Cached
|
2
2
|
|
3
|
-
This
|
4
|
-
added caching for all settings. Settings is a plugin that makes managing a table of
|
3
|
+
This a plugin that makes managing a table of
|
5
4
|
global key, value pairs easy. Think of it like a global Hash stored in your database,
|
6
5
|
that uses simple ActiveRecord like methods for manipulation. Keep track of any global
|
7
6
|
setting that you dont want to hard code into your rails app. You can store any kind
|
8
7
|
of object. Strings, numbers, arrays, or any object.
|
9
8
|
|
9
|
+
> 🚨 BREAK CHANGES WARNING:
|
10
|
+
> rails-settings-cached 2.x has redesign the API, the new version will compatible with the stored setting values by older version.
|
11
|
+
> When you wants to upgrade 2.x, you must read the README again, and follow guides to change your Setting model.
|
12
|
+
|
10
13
|
## Status
|
11
14
|
|
12
15
|
[](https://rubygems.org/gems/rails-settings-cached) [](http://travis-ci.org/huacnlee/rails-settings-cached) [](https://codeclimate.com/github/huacnlee/rails-settings-cached) [](https://codecov.io/github/huacnlee/rails-settings-cached?branch=master)
|
@@ -41,11 +44,23 @@ You will get `app/models/setting.rb`
|
|
41
44
|
|
42
45
|
```rb
|
43
46
|
class Setting < RailsSettings::Base
|
44
|
-
source Rails.root.join("config/app.yml")
|
45
47
|
# cache_prefix { "v1" }
|
48
|
+
|
49
|
+
field :host, default: "http://example.com"
|
50
|
+
field :readonly_item, type: :integer, default: 100, readonly: true
|
51
|
+
field :user_limits, type: :integer, default: 20
|
52
|
+
field :admin_emails, type: :array, default: %w[admin@rubyonrails.org]
|
53
|
+
field :captcha_enable, type: :boolean, default: 1
|
54
|
+
field :notification_options, type: :hash, default: {
|
55
|
+
send_all: true,
|
56
|
+
logging: true,
|
57
|
+
sender_email: "foo@bar.com"
|
58
|
+
}
|
46
59
|
end
|
47
60
|
```
|
48
61
|
|
62
|
+
You must use `field` method to statement the setting keys, otherwice you can't use it.
|
63
|
+
|
49
64
|
Now just put that migration in the database with:
|
50
65
|
|
51
66
|
```bash
|
@@ -57,154 +72,92 @@ rake db:migrate
|
|
57
72
|
The syntax is easy. First, lets create some settings to keep track of:
|
58
73
|
|
59
74
|
```ruby
|
60
|
-
Setting.
|
61
|
-
|
62
|
-
Setting.
|
63
|
-
Setting.
|
64
|
-
|
75
|
+
irb > Setting.host
|
76
|
+
"http://example.com"
|
77
|
+
irb > Setting.host = "https://your-host.com"
|
78
|
+
irb > Setting.host
|
79
|
+
"https://your-host.com"
|
80
|
+
|
81
|
+
irb > Setting.user_limits
|
82
|
+
20
|
83
|
+
irb > Setting.user_limits = "30"
|
84
|
+
irb > Setting.user_limits
|
85
|
+
30
|
86
|
+
irb > Setting.user_limits = 45
|
87
|
+
irb > Setting.user_limits
|
88
|
+
45
|
89
|
+
|
90
|
+
irb > Setting.captcha_enable
|
91
|
+
1
|
92
|
+
irb > Setting.captcha_enable?
|
93
|
+
true
|
94
|
+
irb > Setting.captcha_enable = "0"
|
95
|
+
irb > Setting.captcha_enable
|
96
|
+
false
|
97
|
+
irb > Setting.captcha_enable = "1"
|
98
|
+
irb > Setting.captcha_enable
|
99
|
+
true
|
100
|
+
irb > Setting.captcha_enable = "false"
|
101
|
+
irb > Setting.captcha_enable
|
102
|
+
false
|
103
|
+
irb > Setting.captcha_enable = "true"
|
104
|
+
irb > Setting.captcha_enable
|
105
|
+
true
|
106
|
+
irb > Setting.captcha_enable?
|
107
|
+
true
|
108
|
+
|
109
|
+
irb > Setting.admin_emails
|
110
|
+
["admin@rubyonrails.org"]
|
111
|
+
irb > Setting.admin_emails = %w[foo@bar.com bar@dar.com]
|
112
|
+
irb > Setting.admin_emails
|
113
|
+
["foo@bar.com", "bar@dar.com"]
|
114
|
+
irb > Setting.admin_emails = "huacnlee@gmail.com,admin@admin.com\nadmin@rubyonrails.org"
|
115
|
+
irb > Setting.admin_emails
|
116
|
+
["huacnlee@gmail.com", "admin@admin.com", "admin@rubyonrails.org"]
|
117
|
+
|
118
|
+
irb > Setting.notification_options
|
119
|
+
{
|
120
|
+
send_all: true,
|
121
|
+
logging: true,
|
122
|
+
sender_email: "foo@bar.com"
|
123
|
+
}
|
124
|
+
irb > Setting.notification_options = {
|
125
|
+
sender_email: "notice@rubyonrails.org"
|
126
|
+
}
|
127
|
+
irb > Setting.notification_options
|
128
|
+
{
|
129
|
+
sender_email: "notice@rubyonrails.org"
|
130
|
+
}
|
65
131
|
```
|
66
132
|
|
67
|
-
Now lets read them back:
|
68
|
-
|
69
|
-
```ruby
|
70
|
-
Setting.foo # returns 123
|
71
|
-
```
|
72
|
-
|
73
|
-
Changing an existing setting is the same as creating a new setting:
|
74
|
-
|
75
|
-
```ruby
|
76
|
-
Setting.foo = 'super duper bar'
|
77
|
-
```
|
78
|
-
|
79
|
-
Decide you dont want to track a particular setting anymore?
|
80
|
-
|
81
|
-
```ruby
|
82
|
-
Setting.destroy :foo
|
83
|
-
Setting.foo # returns nil
|
84
|
-
```
|
85
|
-
|
86
|
-
Want a list of all the settings?
|
87
|
-
```ruby
|
88
|
-
Setting.get_all
|
89
|
-
```
|
90
|
-
|
91
|
-
You need name spaces and want a list of settings for a give name space? Just choose your prefered named space delimiter and use `Setting.get_all` (`Settings.all` for # Rails 3.x and 4.0.x) like this:
|
92
|
-
|
93
|
-
```ruby
|
94
|
-
Setting['preferences.color'] = :blue
|
95
|
-
Setting['preferences.size'] = :large
|
96
|
-
Setting['license.key'] = 'ABC-DEF'
|
97
|
-
# Rails 4.1.x
|
98
|
-
Setting.get_all('preferences.')
|
99
|
-
# Rails 3.x and 4.0.x
|
100
|
-
Setting.all('preferences.')
|
101
|
-
# returns { 'preferences.color' => :blue, 'preferences.size' => :large }
|
102
|
-
```
|
103
|
-
|
104
|
-
## Extend a model
|
105
|
-
|
106
|
-
Settings may be bound to any existing ActiveRecord object. Define this association like this:
|
107
|
-
Notice! is not do caching in this version.
|
108
|
-
|
109
|
-
```ruby
|
110
|
-
class User < ActiveRecord::Base
|
111
|
-
include RailsSettings::Extend
|
112
|
-
end
|
113
|
-
```
|
114
|
-
|
115
|
-
Then you can set/get a setting for a given user instance just by doing this:
|
116
|
-
|
117
|
-
```ruby
|
118
|
-
user = User.find(123)
|
119
|
-
user.settings.color = :red
|
120
|
-
user.settings.color # returns :red
|
121
|
-
user.settings.get_all
|
122
|
-
# { "color" => :red }
|
123
|
-
```
|
124
|
-
|
125
|
-
If you want to find users having or not having some settings, there are named scopes for this:
|
126
|
-
|
127
|
-
```ruby
|
128
|
-
User.with_settings
|
129
|
-
# => returns a scope of users having any setting
|
130
|
-
|
131
|
-
User.with_settings_for('color')
|
132
|
-
# => returns a scope of users having a 'color' setting
|
133
|
-
|
134
|
-
User.without_settings
|
135
|
-
# returns a scope of users having no setting at all (means user.settings.get_all == {})
|
136
|
-
|
137
|
-
User.without_settings('color')
|
138
|
-
# returns a scope of users having no 'color' setting (means user.settings.color == nil)
|
139
|
-
```
|
140
|
-
|
141
|
-
## Default settings
|
142
|
-
|
143
|
-
Sometimes you may want define default settings.
|
144
|
-
|
145
|
-
RailsSettings has generate a config YAML file in:
|
146
|
-
|
147
|
-
```yml
|
148
|
-
# config/app.yml
|
149
|
-
defaults: &defaults
|
150
|
-
github_token: "123456"
|
151
|
-
twitter_token: "<%= ENV["TWITTER_TOKEN"] %>"
|
152
|
-
foo:
|
153
|
-
bar: "Foo bar"
|
154
|
-
|
155
|
-
development:
|
156
|
-
<<: *defaults
|
157
|
-
|
158
|
-
test:
|
159
|
-
<<: *defaults
|
160
|
-
|
161
|
-
production:
|
162
|
-
<<: *defaults
|
163
|
-
```
|
164
|
-
|
165
|
-
And you can use by `Setting` model:
|
166
|
-
|
167
|
-
```
|
168
|
-
Setting.github_token
|
169
|
-
=> "123456"
|
170
|
-
Setting.github_token = "654321"
|
171
|
-
# Save into database.
|
172
|
-
Setting.github_token
|
173
|
-
# Read from databae / caching.
|
174
|
-
=> "654321"
|
175
|
-
Setting['foo.bar']
|
176
|
-
=> 'Foo bar'
|
177
|
-
```
|
178
|
-
|
179
|
-
NOTE: YAML setting it also under the cache scope, when you restart Rails application, cache will expire,
|
180
|
-
so when you want change default config, you need restart Rails application server.
|
181
|
-
|
182
133
|
### Caching flow:
|
183
134
|
|
184
135
|
```
|
185
|
-
Setting.
|
186
|
-
|
|
187
|
-
Check DB -> Exist -> Write Cache -> Return
|
136
|
+
Setting.host -> Check Cache -> Exist - Get value of key for cache -> Return
|
188
137
|
|
|
189
|
-
|
138
|
+
Fetch all key and values from DB -> Write Cache -> Get value of key for cache -> return
|
190
139
|
|
|
191
|
-
|
140
|
+
Return default value or nil
|
192
141
|
```
|
193
142
|
|
143
|
+
In each Setting keys call, we will load the cache/db and save in Thread.current for avoid hit cache/db.
|
144
|
+
|
145
|
+
Each key update will expires the cache, so do not add some frequent update key.
|
146
|
+
|
194
147
|
## Change cache key
|
195
148
|
|
196
|
-
|
149
|
+
Some times you may need to force update cache, now you can use `cache_prefix`
|
197
150
|
|
198
151
|
```ruby
|
199
152
|
class Setting < RailsSettings::Base
|
200
|
-
cache_prefix {
|
153
|
+
cache_prefix { "you-prefix" }
|
201
154
|
...
|
202
155
|
end
|
203
156
|
```
|
204
157
|
|
205
158
|
-----
|
206
159
|
|
207
|
-
## How to
|
160
|
+
## How to manage Settings in admin interface?
|
208
161
|
|
209
162
|
If you want create an admin interface to editing the Settings, you can try methods in follow:
|
210
163
|
|
@@ -224,61 +177,57 @@ module Admin
|
|
224
177
|
class SettingsController < ApplicationController
|
225
178
|
before_action :get_setting, only: [:edit, :update]
|
226
179
|
|
227
|
-
def
|
228
|
-
@settings = Setting.get_all
|
229
|
-
end
|
230
|
-
|
231
|
-
def edit
|
180
|
+
def show
|
232
181
|
end
|
233
182
|
|
234
|
-
def
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
redirect_to admin_settings_path, notice: 'Setting has updated.'
|
239
|
-
else
|
240
|
-
redirect_to admin_settings_path
|
183
|
+
def create
|
184
|
+
setting_params.keys.each do |key|
|
185
|
+
next if key.to_s == "site_logo"
|
186
|
+
Setting.send("#{key}=", setting_params[key].strip) unless setting_params[key].nil?
|
241
187
|
end
|
188
|
+
redirect_to admin_settings_path(notice: "Setting was successfully updated.")
|
242
189
|
end
|
243
190
|
|
244
|
-
|
245
|
-
|
246
|
-
|
191
|
+
|
192
|
+
private
|
193
|
+
def setting_params
|
194
|
+
params.require(:setting).permit(:host, :user_limits, :admin_emails,
|
195
|
+
:captcha_enable, :notification_options)
|
196
|
+
end
|
247
197
|
end
|
248
198
|
end
|
249
199
|
```
|
250
200
|
|
251
|
-
app/views/admin/settings/
|
252
|
-
|
253
|
-
```erb
|
254
|
-
<table>
|
255
|
-
<tr>
|
256
|
-
<th>Key</th>
|
257
|
-
<th></th>
|
258
|
-
</tr>
|
259
|
-
<% @settings.each_key do |key| %>
|
260
|
-
<tr>
|
261
|
-
<td><%= key %></td>
|
262
|
-
<td><%= link_to 'edit', edit_admin_setting_path(key) %></td>
|
263
|
-
</tr>
|
264
|
-
<% end %>
|
265
|
-
</table>
|
266
|
-
```
|
267
|
-
|
268
|
-
app/views/admin/settings/edit.html.erb
|
201
|
+
app/views/admin/settings/show.html.erb
|
269
202
|
|
270
203
|
```erb
|
271
|
-
<%= form_for(
|
272
|
-
<
|
273
|
-
|
274
|
-
|
204
|
+
<%= form_for(Setting.new, url: admin_settings_path) do |f| %>
|
205
|
+
<div class="form-group">
|
206
|
+
<label class="control-label">Host</label>
|
207
|
+
<%= f.text_field :host, value: Setting.host, class: "form-control", placeholder: "http://localhost" %>
|
208
|
+
</div>
|
209
|
+
|
210
|
+
<div class="form-group form-checkbox">
|
211
|
+
<label>
|
212
|
+
<%= f.check_box :captcha_enable, checked: Setting.captcha_enable? %>
|
213
|
+
Enable/Disable Captcha
|
214
|
+
</label>
|
215
|
+
</div>
|
216
|
+
|
217
|
+
<div class="form-group">
|
218
|
+
<label class="control-label">Admin Emails</label>
|
219
|
+
<%= f.text_area :admin_emails, value: Setting.admin_emails.join("\n"), class: "form-control" %>
|
220
|
+
</div>
|
221
|
+
|
222
|
+
<div class="form-group">
|
223
|
+
<label class="control-label">Notification options</label>
|
224
|
+
<%= f.text_area :notification_options, value: YAML.dump(Setting.notification_options), class: "form-control", style: "height: 180px;" %>
|
225
|
+
<div class="form-text">
|
226
|
+
Use YAML format to config the SMTP_html
|
227
|
+
</details>
|
275
228
|
<% end %>
|
276
229
|
```
|
277
230
|
|
278
|
-
Also you may use [rails-settings-ui](https://github.com/accessd/rails-settings-ui) gem
|
279
|
-
for building ready to using interface with validations,
|
280
|
-
or [activeadmin_settings_cached](https://github.com/artofhuman/activeadmin_settings_cached) gem if you use [activeadmin](https://github.com/activeadmin/activeadmin).
|
281
|
-
|
282
231
|
## Use case:
|
283
232
|
|
284
233
|
- [ruby-china/ruby-china](https://github.com/ruby-china/ruby-china)
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "bundler/setup"
|
5
|
+
rescue LoadError
|
6
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
7
|
+
end
|
8
|
+
|
9
|
+
require "rdoc/task"
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = "rdoc"
|
13
|
+
rdoc.title = "Rails Settings Cached"
|
14
|
+
rdoc.options << "--line-numbers"
|
15
|
+
rdoc.rdoc_files.include("README.md")
|
16
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
17
|
+
end
|
18
|
+
|
19
|
+
require "bundler/gem_tasks"
|
20
|
+
|
21
|
+
require "rake/testtask"
|
22
|
+
|
23
|
+
Rake::TestTask.new(:test) do |t|
|
24
|
+
t.libs << "test"
|
25
|
+
t.pattern = "test/**/*_test.rb"
|
26
|
+
t.verbose = false
|
27
|
+
t.warning = false
|
28
|
+
end
|
29
|
+
|
30
|
+
task default: :test
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "rails/generators"
|
2
4
|
require "rails/generators/migration"
|
3
5
|
|
@@ -27,7 +29,6 @@ module Settings
|
|
27
29
|
|
28
30
|
def install_setting
|
29
31
|
template "model.rb", File.join("app/models", class_path, "#{file_name}.rb")
|
30
|
-
template "app.yml", File.join("config", "app.yml")
|
31
32
|
migration_template "migration.rb", "db/migrate/create_settings.rb", migration_version: migration_version
|
32
33
|
end
|
33
34
|
|
@@ -3,12 +3,10 @@ class CreateSettings < ActiveRecord::Migration<%= migration_version %>
|
|
3
3
|
create_table :settings do |t|
|
4
4
|
t.string :var, null: false
|
5
5
|
t.text :value, null: true
|
6
|
-
t.integer :thing_id, null: true
|
7
|
-
t.string :thing_type, null: true, limit: 30
|
8
6
|
t.timestamps
|
9
7
|
end
|
10
8
|
|
11
|
-
add_index :settings, %i(
|
9
|
+
add_index :settings, %i(var), unique: true
|
12
10
|
end
|
13
11
|
|
14
12
|
def self.down
|
@@ -1,7 +1,10 @@
|
|
1
1
|
# RailsSettings Model
|
2
2
|
class <%= class_name %> < RailsSettings::Base
|
3
|
-
|
3
|
+
cache_prefix { "v1" }
|
4
4
|
|
5
|
-
#
|
6
|
-
#
|
5
|
+
# Define your fields
|
6
|
+
# field :host, type: :string, default: "http://localhost:3000"
|
7
|
+
# field :default_locale, default: "en", type: :string
|
8
|
+
# field :confirmable_enable, default: "0", type: :boolean
|
9
|
+
# field :admin_emails, default: "admin@rubyonrails.org", type: :array
|
7
10
|
end
|
data/lib/rails-settings/base.rb
CHANGED
@@ -1,44 +1,121 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RailsSettings
|
2
|
-
class Base <
|
3
|
-
|
4
|
-
|
4
|
+
class Base < ActiveRecord::Base
|
5
|
+
class SettingNotFound < RuntimeError; end
|
6
|
+
|
7
|
+
SEPARATOR_REGEXP = /[\s,]/
|
8
|
+
self.table_name = table_name_prefix + "settings"
|
9
|
+
|
10
|
+
# get the value field, YAML decoded
|
11
|
+
def value
|
12
|
+
YAML.load(self[:value]) if self[:value].present?
|
5
13
|
end
|
6
14
|
|
7
|
-
|
8
|
-
|
15
|
+
# set the value field, YAML encoded
|
16
|
+
def value=(new_value)
|
17
|
+
self[:value] = new_value.to_yaml
|
9
18
|
end
|
10
19
|
|
11
|
-
def
|
12
|
-
|
20
|
+
def expire_cache
|
21
|
+
Thread.current[:rails_settings_all_settings] = nil
|
22
|
+
Rails.cache.delete(self.class.cache_key)
|
13
23
|
end
|
14
24
|
|
15
25
|
class << self
|
26
|
+
def field(key, **opts)
|
27
|
+
_define_field(key, default: opts[:default], type: opts[:type], readonly: opts[:readonly])
|
28
|
+
end
|
29
|
+
|
16
30
|
def cache_prefix(&block)
|
17
31
|
@cache_prefix = block
|
18
32
|
end
|
19
33
|
|
20
|
-
def cache_key
|
21
|
-
scope = ["
|
34
|
+
def cache_key
|
35
|
+
scope = ["rails-settings-cached"]
|
22
36
|
scope << @cache_prefix.call if @cache_prefix
|
23
|
-
scope << "#{scope_object.class.name}-#{scope_object.id}" if scope_object
|
24
|
-
scope << var_name.to_s
|
25
37
|
scope.join("/")
|
26
38
|
end
|
27
39
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
40
|
+
private
|
41
|
+
def _define_field(key, default: nil, type: :string, readonly: false)
|
42
|
+
self.class.define_method(key) do
|
43
|
+
val = self.send(:_value_of, key)
|
44
|
+
result = nil
|
45
|
+
if !val.nil?
|
46
|
+
result = val
|
47
|
+
else
|
48
|
+
result = default
|
49
|
+
result = default.call if default.is_a?(Proc)
|
50
|
+
end
|
51
|
+
|
52
|
+
result = self.send(:_covert_string_to_typeof_value, type, result)
|
53
|
+
|
54
|
+
result
|
55
|
+
end
|
56
|
+
|
57
|
+
unless readonly
|
58
|
+
self.class.define_method("#{key}=") do |value|
|
59
|
+
var_name = key.to_s
|
60
|
+
|
61
|
+
record = find_by(var: var_name) || new(var: var_name)
|
62
|
+
value = self.send(:_covert_string_to_typeof_value, type, value)
|
63
|
+
|
64
|
+
record.value = value
|
65
|
+
record.save!
|
66
|
+
|
67
|
+
value
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
if type == :boolean
|
72
|
+
self.class.define_method("#{key}?") do
|
73
|
+
val = self.send(:_value_of, key)
|
74
|
+
val == "true" || val == "1"
|
75
|
+
end
|
76
|
+
end
|
32
77
|
end
|
33
|
-
val
|
34
|
-
end
|
35
78
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
79
|
+
def _covert_string_to_typeof_value(type, value)
|
80
|
+
return value unless value.is_a?(String) || value.is_a?(Integer)
|
81
|
+
|
82
|
+
case type
|
83
|
+
when :boolean
|
84
|
+
return value == "true" || value == "1" || value == 1 || value == true
|
85
|
+
when :array
|
86
|
+
return value.split(SEPARATOR_REGEXP).reject { |str| str.empty? }
|
87
|
+
when :hash
|
88
|
+
value = YAML.load(value).to_hash rescue {}
|
89
|
+
value.deep_stringify_keys!
|
90
|
+
return value
|
91
|
+
when :integer
|
92
|
+
return value.to_i
|
93
|
+
else
|
94
|
+
value
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
def _value_of(var_name)
|
99
|
+
raise "#{self.table_name} does not exist." unless table_exists?
|
100
|
+
|
101
|
+
_all_settings[var_name.to_s]
|
102
|
+
end
|
103
|
+
|
104
|
+
def rails_initialized?
|
105
|
+
Rails.application && Rails.application.initialized?
|
106
|
+
end
|
107
|
+
|
108
|
+
def _all_settings
|
109
|
+
raise "You can use settings before Rails initialize." unless rails_initialized?
|
110
|
+
Thread.current[:rails_settings_all_settings] ||= begin
|
111
|
+
Rails.cache.fetch(self.cache_key, expires_in: 1.week) do
|
112
|
+
vars = unscoped.select("var, value")
|
113
|
+
result = {}
|
114
|
+
vars.each { |record| result[record.var] = record.value }
|
115
|
+
result.with_indifferent_access
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
42
119
|
end
|
43
120
|
end
|
44
121
|
end
|
@@ -1,8 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module RailsSettings
|
2
4
|
class Railtie < Rails::Railtie
|
3
5
|
initializer "rails_settings.active_record.initialization" do
|
4
|
-
RailsSettings::Base.after_commit :
|
5
|
-
RailsSettings::Base.after_commit :expire_cache, on: %i(destroy)
|
6
|
+
RailsSettings::Base.after_commit :expire_cache, on: %i(create update destroy)
|
6
7
|
end
|
7
8
|
end
|
8
9
|
end
|
@@ -1,8 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require_relative "rails-settings/base"
|
3
|
-
require_relative "rails-settings/scoped_settings"
|
4
|
-
require_relative "rails-settings/default"
|
5
|
-
require_relative "rails-settings/extend"
|
6
4
|
require_relative "rails-settings/railtie"
|
7
5
|
require_relative "rails-settings/version"
|
8
6
|
|
metadata
CHANGED
@@ -1,17 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-settings-cached
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jason Lee
|
8
|
-
- Squeegy
|
9
|
-
- Georg Ledermann
|
10
|
-
- 100hz
|
11
8
|
autorequire:
|
12
9
|
bindir: bin
|
13
10
|
cert_chain: []
|
14
|
-
date:
|
11
|
+
date: 2019-04-26 00:00:00.000000000 Z
|
15
12
|
dependencies:
|
16
13
|
- !ruby/object:Gem::Dependency
|
17
14
|
name: rails
|
@@ -45,16 +42,16 @@ dependencies:
|
|
45
42
|
name: rubocop
|
46
43
|
requirement: !ruby/object:Gem::Requirement
|
47
44
|
requirements:
|
48
|
-
- -
|
45
|
+
- - ">="
|
49
46
|
- !ruby/object:Gem::Version
|
50
|
-
version: 0
|
47
|
+
version: '0'
|
51
48
|
type: :development
|
52
49
|
prerelease: false
|
53
50
|
version_requirements: !ruby/object:Gem::Requirement
|
54
51
|
requirements:
|
55
|
-
- -
|
52
|
+
- - ">="
|
56
53
|
- !ruby/object:Gem::Version
|
57
|
-
version: 0
|
54
|
+
version: '0'
|
58
55
|
- !ruby/object:Gem::Dependency
|
59
56
|
name: simplecov
|
60
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -70,7 +67,7 @@ dependencies:
|
|
70
67
|
- !ruby/object:Gem::Version
|
71
68
|
version: '0'
|
72
69
|
- !ruby/object:Gem::Dependency
|
73
|
-
name:
|
70
|
+
name: minitest
|
74
71
|
requirement: !ruby/object:Gem::Requirement
|
75
72
|
requirements:
|
76
73
|
- - ">="
|
@@ -108,18 +105,15 @@ executables: []
|
|
108
105
|
extensions: []
|
109
106
|
extra_rdoc_files: []
|
110
107
|
files:
|
108
|
+
- MIT-LICENSE
|
111
109
|
- README.md
|
110
|
+
- Rakefile
|
112
111
|
- lib/generators/settings/install_generator.rb
|
113
|
-
- lib/generators/settings/templates/app.yml
|
114
112
|
- lib/generators/settings/templates/migration.rb
|
115
113
|
- lib/generators/settings/templates/model.rb
|
116
114
|
- lib/rails-settings-cached.rb
|
117
115
|
- lib/rails-settings/base.rb
|
118
|
-
- lib/rails-settings/default.rb
|
119
|
-
- lib/rails-settings/extend.rb
|
120
116
|
- lib/rails-settings/railtie.rb
|
121
|
-
- lib/rails-settings/scoped_settings.rb
|
122
|
-
- lib/rails-settings/settings.rb
|
123
117
|
- lib/rails-settings/version.rb
|
124
118
|
homepage: https://github.com/huacnlee/rails-settings-cached
|
125
119
|
licenses: []
|
@@ -132,15 +126,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
132
126
|
requirements:
|
133
127
|
- - ">="
|
134
128
|
- !ruby/object:Gem::Version
|
135
|
-
version: '2.
|
129
|
+
version: '2.5'
|
136
130
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
137
131
|
requirements:
|
138
132
|
- - ">="
|
139
133
|
- !ruby/object:Gem::Version
|
140
134
|
version: '0'
|
141
135
|
requirements: []
|
142
|
-
|
143
|
-
rubygems_version: 2.7.6
|
136
|
+
rubygems_version: 3.0.1
|
144
137
|
signing_key:
|
145
138
|
specification_version: 4
|
146
139
|
summary: Settings plugin for Rails that makes managing a table of global keys.
|
@@ -1,40 +0,0 @@
|
|
1
|
-
require "digest/md5"
|
2
|
-
|
3
|
-
module RailsSettings
|
4
|
-
class Default < ::Hash
|
5
|
-
class MissingKey < StandardError; end
|
6
|
-
|
7
|
-
class << self
|
8
|
-
def enabled?
|
9
|
-
source_path && File.exist?(source_path)
|
10
|
-
end
|
11
|
-
|
12
|
-
def source(value = nil)
|
13
|
-
@source ||= value
|
14
|
-
end
|
15
|
-
|
16
|
-
def source_path
|
17
|
-
@source || Rails.root.join("config/app.yml")
|
18
|
-
end
|
19
|
-
|
20
|
-
def [](key)
|
21
|
-
# foo.bar.dar Nested fetch value
|
22
|
-
return instance[key] if instance.key?(key)
|
23
|
-
keys = key.to_s.split(".")
|
24
|
-
instance.dig(*keys)
|
25
|
-
end
|
26
|
-
|
27
|
-
def instance
|
28
|
-
return @instance if defined? @instance
|
29
|
-
@instance = new
|
30
|
-
end
|
31
|
-
end
|
32
|
-
|
33
|
-
def initialize
|
34
|
-
content = open(self.class.source_path).read
|
35
|
-
hash = content.empty? ? {} : YAML.load(ERB.new(content).result).to_hash
|
36
|
-
hash = hash[Rails.env] || {}
|
37
|
-
replace hash
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,34 +0,0 @@
|
|
1
|
-
module RailsSettings
|
2
|
-
module Extend
|
3
|
-
extend ActiveSupport::Concern
|
4
|
-
|
5
|
-
included do
|
6
|
-
scope :with_settings, lambda {
|
7
|
-
joins("JOIN settings ON (settings.thing_id = #{table_name}.#{primary_key} AND
|
8
|
-
settings.thing_type = '#{base_class.name}')")
|
9
|
-
.select("DISTINCT #{table_name}.*")
|
10
|
-
}
|
11
|
-
|
12
|
-
scope :with_settings_for, lambda { |var|
|
13
|
-
joins("JOIN settings ON (settings.thing_id = #{table_name}.#{primary_key} AND
|
14
|
-
settings.thing_type = '#{base_class.name}') AND settings.var = '#{var}'")
|
15
|
-
}
|
16
|
-
|
17
|
-
scope :without_settings, lambda {
|
18
|
-
joins("LEFT JOIN settings ON (settings.thing_id = #{table_name}.#{primary_key} AND
|
19
|
-
settings.thing_type = '#{base_class.name}')")
|
20
|
-
.where("settings.id IS NULL")
|
21
|
-
}
|
22
|
-
|
23
|
-
scope :without_settings_for, lambda { |var|
|
24
|
-
where("settings.id IS NULL")
|
25
|
-
.joins("LEFT JOIN settings ON (settings.thing_id = #{table_name}.#{primary_key} AND
|
26
|
-
settings.thing_type = '#{base_class.name}') AND settings.var = '#{var}'")
|
27
|
-
}
|
28
|
-
end
|
29
|
-
|
30
|
-
def settings
|
31
|
-
ScopedSettings.for_thing(self)
|
32
|
-
end
|
33
|
-
end
|
34
|
-
end
|
@@ -1,120 +0,0 @@
|
|
1
|
-
module RailsSettings
|
2
|
-
class Settings < ActiveRecord::Base
|
3
|
-
self.table_name = table_name_prefix + "settings"
|
4
|
-
|
5
|
-
class SettingNotFound < RuntimeError; end
|
6
|
-
|
7
|
-
belongs_to :thing, polymorphic: true
|
8
|
-
|
9
|
-
# get the value field, YAML decoded
|
10
|
-
def value
|
11
|
-
YAML.load(self[:value]) if self[:value].present?
|
12
|
-
end
|
13
|
-
|
14
|
-
# set the value field, YAML encoded
|
15
|
-
def value=(new_value)
|
16
|
-
self[:value] = new_value.to_yaml
|
17
|
-
end
|
18
|
-
|
19
|
-
class << self
|
20
|
-
# get or set a variable with the variable as the called method
|
21
|
-
# rubocop:disable Style/MethodMissing
|
22
|
-
def method_missing(method, *args)
|
23
|
-
method_name = method.to_s
|
24
|
-
super(method, *args)
|
25
|
-
rescue NoMethodError
|
26
|
-
# set a value for a variable
|
27
|
-
if method_name[-1] == "="
|
28
|
-
var_name = method_name.sub("=", "")
|
29
|
-
value = args.first
|
30
|
-
self[var_name] = value
|
31
|
-
else
|
32
|
-
# retrieve a value
|
33
|
-
self[method_name]
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
# destroy the specified settings record
|
38
|
-
def destroy(var_name)
|
39
|
-
var_name = var_name.to_s
|
40
|
-
obj = object(var_name)
|
41
|
-
raise SettingNotFound, "Setting variable \"#{var_name}\" not found" if obj.nil?
|
42
|
-
|
43
|
-
obj.destroy
|
44
|
-
true
|
45
|
-
end
|
46
|
-
|
47
|
-
# retrieve all settings as a hash (optionally starting with a given namespace)
|
48
|
-
def get_all(starting_with = nil)
|
49
|
-
vars = thing_scoped.select("var, value")
|
50
|
-
vars = vars.where("var LIKE '#{starting_with}%'") if starting_with
|
51
|
-
result = {}
|
52
|
-
vars.each { |record| result[record.var] = record.value }
|
53
|
-
result.reverse_merge!(default_settings(starting_with))
|
54
|
-
result.with_indifferent_access
|
55
|
-
end
|
56
|
-
|
57
|
-
def where(sql = nil)
|
58
|
-
vars = thing_scoped.where(sql) if sql
|
59
|
-
vars
|
60
|
-
end
|
61
|
-
|
62
|
-
# get a setting value by [] notation
|
63
|
-
def [](var_name)
|
64
|
-
return Default[var_name] unless rails_initialized?
|
65
|
-
|
66
|
-
val = object(var_name)
|
67
|
-
return val.value if val
|
68
|
-
return Default[var_name] if Default.enabled?
|
69
|
-
end
|
70
|
-
|
71
|
-
# set a setting value by [] notation
|
72
|
-
def []=(var_name, value)
|
73
|
-
var_name = var_name.to_s
|
74
|
-
|
75
|
-
record = object(var_name) || thing_scoped.new(var: var_name)
|
76
|
-
record.value = value
|
77
|
-
record.save!
|
78
|
-
|
79
|
-
value
|
80
|
-
end
|
81
|
-
|
82
|
-
def merge!(var_name, hash_value)
|
83
|
-
raise ArgumentError unless hash_value.is_a?(Hash)
|
84
|
-
|
85
|
-
old_value = self[var_name] || {}
|
86
|
-
raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
|
87
|
-
|
88
|
-
new_value = old_value.merge(hash_value)
|
89
|
-
self[var_name] = new_value if new_value != old_value
|
90
|
-
|
91
|
-
new_value
|
92
|
-
end
|
93
|
-
|
94
|
-
def object(var_name)
|
95
|
-
return nil unless table_exists?
|
96
|
-
thing_scoped.where(var: var_name.to_s).first
|
97
|
-
end
|
98
|
-
|
99
|
-
def thing_scoped
|
100
|
-
unscoped.where("thing_type is NULL and thing_id is NULL")
|
101
|
-
end
|
102
|
-
|
103
|
-
def source(filename)
|
104
|
-
Default.source(filename)
|
105
|
-
end
|
106
|
-
|
107
|
-
def rails_initialized?
|
108
|
-
Rails.application && Rails.application.initialized?
|
109
|
-
end
|
110
|
-
|
111
|
-
private
|
112
|
-
|
113
|
-
def default_settings(starting_with = nil)
|
114
|
-
return {} unless Default.enabled?
|
115
|
-
return Default.instance if starting_with.nil?
|
116
|
-
Default.instance.select { |key, _| key.to_s.start_with?(starting_with) }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
end
|
120
|
-
end
|