rails-settings-cached 0.5.6 → 0.6.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
  SHA1:
3
- metadata.gz: b57a0a5ecf132300eb30437cecef1d72ac4a6850
4
- data.tar.gz: 0819f21de6cb043141b20ff39ddd4c212aabd758
3
+ metadata.gz: fa6d7bd1e608d80ee9995d8f1393e9fce6a19d2f
4
+ data.tar.gz: d47dd443d8e1afe1ea8dde4e7e10acbff1aafd3c
5
5
  SHA512:
6
- metadata.gz: b26625a6a49cc7413f18201e454374a6de07523705efd6eedd7d889aa464f2f07a057a541a277eba1fcfc1ad6cc791c4221ce6e84b35c2004cb37d86fdb661ad
7
- data.tar.gz: d2c7146010da954ef4b8010b5a3fe7bd92a9c6c100c389a8db3c834fd90429c64a648387f6d5885c414f13b407f4cde974b382d13c6a089cc5dc0373780ef7d2
6
+ metadata.gz: 0101c4f85fec7b475e5306bc94882c39ce7711f66b3cdc5c5175aedc333a138503388ba56d4dee0d956bb8ce2af396c030e04fcee89ef8d75749fc932e8259dd
7
+ data.tar.gz: 892a9665b231016b4c2ea079afdd94a01895169795ca1637cc23e7a2bf007823b5400d37fef0d400a2ca40204618d5dbe2c2a6b391fa7f4b53dee59db91b7373
data/README.md CHANGED
@@ -1,202 +1,263 @@
1
- # Settings Gem
2
-
3
- This is improved from [rails-settings](https://github.com/ledermann/rails-settings),
4
- added caching for all settings. Settings is a plugin that makes managing a table of
5
- global key, value pairs easy. Think of it like a global Hash stored in your database,
6
- that uses simple ActiveRecord like methods for manipulation. Keep track of any global
7
- setting that you dont want to hard code into your rails app. You can store any kind
8
- of object. Strings, numbers, arrays, or any object.
9
-
10
- ## Status
11
-
12
- [![Gem Version](https://badge.fury.io/rb/rails-settings-cached.svg)](https://rubygems.org/gems/rails-settings-cached) [![CI Status](https://api.travis-ci.org/huacnlee/rails-settings-cached.svg)](http://travis-ci.org/huacnlee/rails-settings-cached) [![Code Climate](https://codeclimate.com/github/huacnlee/rails-settings-cached/badges/gpa.svg)](https://codeclimate.com/github/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)
13
-
14
- ## Setup
15
-
16
- Edit your Gemfile:
17
-
18
- ```ruby
19
- gem 'rails-settings-cached', "~> 0.5.6"
20
- ```
21
-
22
- Older Rails versions:
23
-
24
- ```rb
25
- # 4.1.x
26
- gem "rails-settings-cached", "~> 0.4.0"
27
- # 4.0.x
28
- gem "rails-settings-cached", "0.3.1"
29
- # 3.x
30
- gem "rails-settings-cached", "0.2.4"
31
- ```
32
-
33
- Generate your settings:
34
-
35
- ```bash
36
- $ rails g settings:install
37
- ```
38
-
39
- If you want custom model name:
40
-
41
- ```bash
42
- $ rails g settings:install MySetting
43
- ```
44
-
45
- Now just put that migration in the database with:
46
-
47
- ```bash
48
- rake db:migrate
49
- ```
50
-
51
- ## Usage
52
-
53
- The syntax is easy. First, lets create some settings to keep track of:
54
-
55
- ```ruby
56
- Setting.admin_password = 'supersecret'
57
- Setting.date_format = '%m %d, %Y'
58
- Setting.cocktails = ['Martini', 'Screwdriver', 'White Russian']
59
- Setting.foo = 123
60
- Setting.credentials = { :username => 'tom', :password => 'secret' }
61
- ```
62
-
63
- Now lets read them back:
64
-
65
- ```ruby
66
- Setting.foo # returns 123
67
- ```
68
-
69
- Changing an existing setting is the same as creating a new setting:
70
-
71
- ```ruby
72
- Setting.foo = 'super duper bar'
73
- ```
74
-
75
- For changing an existing setting which is a Hash, you can merge new values with existing ones:
76
-
77
- ```ruby
78
- Setting.merge!(:credentials, :password => 'topsecret')
79
- Setting.credentials # returns { :username => 'tom', :password => 'topsecret' }
80
- ```
81
-
82
- Decide you dont want to track a particular setting anymore?
83
-
84
- ```ruby
85
- Setting.destroy :foo
86
- Setting.foo # returns nil
87
- ```
88
-
89
- Want a list of all the settings?
90
- ```ruby
91
- # Rails 4.1.x
92
- Setting.get_all
93
- # Rails 3.x and 4.0.x
94
- Setting.all
95
- # returns {'admin_password' => 'super_secret', 'date_format' => '%m %d, %Y'}
96
- ```
97
-
98
- 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:
99
-
100
- ```ruby
101
- Setting['preferences.color'] = :blue
102
- Setting['preferences.size'] = :large
103
- Setting['license.key'] = 'ABC-DEF'
104
- # Rails 4.1.x
105
- Setting.get_all('preferences.')
106
- # Rails 3.x and 4.0.x
107
- Setting.all('preferences.')
108
- # returns { 'preferences.color' => :blue, 'preferences.size' => :large }
109
- ```
110
-
111
- Set defaults for certain settings of your app. This will cause the defined settings to return with the
112
- Specified value even if they are **not in the database**. Make a new file in `config/initializers/default_settings.rb`
113
- with the following:
114
-
115
- ```ruby
116
- Setting.defaults[:some_setting] = 'footastic'
117
- Setting.where(:var => "some_setting").count
118
- => 0
119
- Setting.some_setting
120
- => "footastic"
121
- ```
122
-
123
- Init default value in database, this has indifferent with `Setting.defaults[:some_setting]`, this will **save the value into database**:
124
-
125
- ```ruby
126
- Setting.save_default(:some_key, "123")
127
- Setting.where(:var => "some_key").count
128
- => 1
129
- Setting.some_key
130
- => "123"
131
- ```
132
-
133
- Settings may be bound to any existing ActiveRecord object. Define this association like this:
134
- Notice! is not do caching in this version.
135
-
136
- ```ruby
137
- class User < ActiveRecord::Base
138
- include RailsSettings::Extend
139
- end
140
- ```
141
-
142
- Then you can set/get a setting for a given user instance just by doing this:
143
-
144
- ```ruby
145
- user = User.find(123)
146
- user.settings.color = :red
147
- user.settings.color # returns :red
148
- # Rails 4.1.x
149
- user.settings.get_all
150
- # Rails 3.x and 4.0.x
151
- user.settings.all
152
- # { "color" => :red }
153
- ```
154
-
155
- If you want to find users having or not having some settings, there are named scopes for this:
156
-
157
- ```ruby
158
- User.with_settings
159
- # => returns a scope of users having any setting
160
-
161
- User.with_settings_for('color')
162
- # => returns a scope of users having a 'color' setting
163
-
164
- User.without_settings
165
- # returns a scope of users having no setting at all (means user.settings.get_all == {})
166
-
167
- User.without_settings('color')
168
- # returns a scope of users having no 'color' setting (means user.settings.color == nil)
169
- ```
170
-
171
- Settings maybe dynamically scoped. For example, if you're using [apartment gem](https://github.com/influitive/apartment) for multitenancy, you may not want tenants to share settings:
172
-
173
- ```ruby
174
- class Settings < RailsSettings::CachedSettings
175
- cache_prefix { Apartment::Tenant.current }
176
- ...
177
- end
178
- ```
179
-
180
- -----
181
-
182
- ## How to create a list, form to manage Settings?
183
-
184
- If you want create an admin interface to editing the Settings, you can try methods in follow:
185
-
186
- ```ruby
187
- class SettingsController < ApplicationController
188
- def index
189
- # to get all items for render list
190
- @settings = Setting.unscoped
191
- end
192
-
193
- def edit
194
- @setting = Setting.unscoped.find(params[:id])
195
- end
196
- end
197
- ```
198
-
199
-
200
- Also you may use [rails-settings-ui](https://github.com/accessd/rails-settings-ui) gem
201
- for building ready to using interface with validations.
202
-
1
+ # Rails Settings Cached
2
+
3
+ This is improved from [rails-settings](https://github.com/ledermann/rails-settings),
4
+ added caching for all settings. Settings is a plugin that makes managing a table of
5
+ global key, value pairs easy. Think of it like a global Hash stored in your database,
6
+ that uses simple ActiveRecord like methods for manipulation. Keep track of any global
7
+ setting that you dont want to hard code into your rails app. You can store any kind
8
+ of object. Strings, numbers, arrays, or any object.
9
+
10
+ ## Status
11
+
12
+ [![Gem Version](https://badge.fury.io/rb/rails-settings-cached.svg)](https://rubygems.org/gems/rails-settings-cached) [![CI Status](https://api.travis-ci.org/huacnlee/rails-settings-cached.svg)](http://travis-ci.org/huacnlee/rails-settings-cached) [![Code Climate](https://codeclimate.com/github/huacnlee/rails-settings-cached/badges/gpa.svg)](https://codeclimate.com/github/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)
13
+
14
+ ## Setup
15
+
16
+ Edit your Gemfile:
17
+
18
+ ```ruby
19
+ gem "rails-settings-cached"
20
+ ```
21
+
22
+ Generate your settings:
23
+
24
+ ```bash
25
+ $ rails g settings:install
26
+ ```
27
+
28
+ If you want custom model name:
29
+
30
+ ```bash
31
+ $ rails g settings:install SiteConfig
32
+ ```
33
+
34
+ Now just put that migration in the database with:
35
+
36
+ ```bash
37
+ rake db:migrate
38
+ ```
39
+
40
+ ## Usage
41
+
42
+ The syntax is easy. First, lets create some settings to keep track of:
43
+
44
+ ```ruby
45
+ Setting.admin_password = 'supersecret'
46
+ Setting.date_format = '%m %d, %Y'
47
+ Setting.cocktails = ['Martini', 'Screwdriver', 'White Russian']
48
+ Setting.foo = 123
49
+ Setting.credentials = { :username => 'tom', :password => 'secret' }
50
+ ```
51
+
52
+ Now lets read them back:
53
+
54
+ ```ruby
55
+ Setting.foo # returns 123
56
+ ```
57
+
58
+ Changing an existing setting is the same as creating a new setting:
59
+
60
+ ```ruby
61
+ Setting.foo = 'super duper bar'
62
+ ```
63
+
64
+ Decide you dont want to track a particular setting anymore?
65
+
66
+ ```ruby
67
+ Setting.destroy :foo
68
+ Setting.foo # returns nil
69
+ ```
70
+
71
+ Want a list of all the settings?
72
+ ```ruby
73
+ Setting.get_all
74
+ ```
75
+
76
+ 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:
77
+
78
+ ```ruby
79
+ Setting['preferences.color'] = :blue
80
+ Setting['preferences.size'] = :large
81
+ Setting['license.key'] = 'ABC-DEF'
82
+ # Rails 4.1.x
83
+ Setting.get_all('preferences.')
84
+ # Rails 3.x and 4.0.x
85
+ Setting.all('preferences.')
86
+ # returns { 'preferences.color' => :blue, 'preferences.size' => :large }
87
+ ```
88
+
89
+ ## Extend a model
90
+
91
+ Settings may be bound to any existing ActiveRecord object. Define this association like this:
92
+ Notice! is not do caching in this version.
93
+
94
+ ```ruby
95
+ class User < ActiveRecord::Base
96
+ include RailsSettings::Extend
97
+ end
98
+ ```
99
+
100
+ Then you can set/get a setting for a given user instance just by doing this:
101
+
102
+ ```ruby
103
+ user = User.find(123)
104
+ user.settings.color = :red
105
+ user.settings.color # returns :red
106
+ user.settings.get_all
107
+ # { "color" => :red }
108
+ ```
109
+
110
+ If you want to find users having or not having some settings, there are named scopes for this:
111
+
112
+ ```ruby
113
+ User.with_settings
114
+ # => returns a scope of users having any setting
115
+
116
+ User.with_settings_for('color')
117
+ # => returns a scope of users having a 'color' setting
118
+
119
+ User.without_settings
120
+ # returns a scope of users having no setting at all (means user.settings.get_all == {})
121
+
122
+ User.without_settings('color')
123
+ # returns a scope of users having no 'color' setting (means user.settings.color == nil)
124
+ ```
125
+
126
+ ## Default settings
127
+
128
+ Sometimes you may want define default settings.
129
+
130
+ RailsSettings has generate a config YAML file in:
131
+
132
+ ```yml
133
+ # config/app.yml
134
+ defaults: &defaults
135
+ github_token: "123456"
136
+ twitter_token: "<%= ENV["TWITTER_TOKEN"] %>"
137
+ foo:
138
+ bar: "Foo bar"
139
+
140
+ development:
141
+ <<: *defaults
142
+
143
+ test:
144
+ <<: *defaults
145
+
146
+ production:
147
+ <<: *defaults
148
+ ```
149
+
150
+ And you can use by `Setting` model:
151
+
152
+ ```
153
+ Setting.github_token
154
+ => "123456"
155
+ Setting.github_token = "654321"
156
+ # Save into database.
157
+ Setting.github_token
158
+ # Read from databae / caching.
159
+ => "654321"
160
+ Setting['foo.bar']
161
+ => 'Foo bar'
162
+ ```
163
+
164
+ NOTE: YAML setting it also under the cache scope, when you restart Rails application, cache will expire,
165
+ so when you want change default config, you need restart Rails application server.
166
+
167
+ ### Caching flow:
168
+
169
+ ```
170
+ Setting.foo -> Check Cache -> Exist - Write Cache -> Return
171
+ |
172
+ Check DB -> Exist -> Write Cache -> Return
173
+ |
174
+ Check Default -> Exist -> Write Cache -> Return
175
+ |
176
+ Return nil
177
+ ```
178
+
179
+ ## Change cache key
180
+
181
+ ```ruby
182
+ class Setting < RailsSettings::Base
183
+ cache_prefix { 'you-prefix' }
184
+ ...
185
+ end
186
+ ```
187
+
188
+ -----
189
+
190
+ ## How to create a list, form to manage Settings?
191
+
192
+ If you want create an admin interface to editing the Settings, you can try methods in follow:
193
+
194
+ config/routes.rb
195
+
196
+ ```rb
197
+ namespace :admin do
198
+ resources :settings
199
+ end
200
+ ```
201
+
202
+
203
+ app/controllers/admin/settings_controller.rb
204
+
205
+ ```rb
206
+ module Admin
207
+ class SettingsController < ApplicationController
208
+ before_action :get_setting, only: [:edit, :update]
209
+
210
+ def index
211
+ @settings = Setting.get_all
212
+ end
213
+
214
+ def edit
215
+ end
216
+
217
+ def update
218
+ if @setting.value != params[:setting][:value]
219
+ @setting.value = YAML.load(params[:setting][:value])
220
+ @setting.save
221
+ redirect_to admin_settings_path, notice: 'Setting has updated.'
222
+ else
223
+ redirect_to admin_settings_path
224
+ end
225
+ end
226
+
227
+ def get_setting
228
+ @setting = Setting.find_by(var: params[:id]) || Setting.new(var: params[:id])
229
+ @setting[:value] = Setting[params[:id]]
230
+ end
231
+ end
232
+ end
233
+ ```
234
+
235
+ app/views/admin/settings/index.html.erb
236
+
237
+ ```erb
238
+ <table>
239
+ <tr>
240
+ <th>Key</th>
241
+ <th></th>
242
+ </tr>
243
+ <% @settings.each_key do |key| %>
244
+ <tr>
245
+ <td><%= key %></td>
246
+ <td><%= link_to 'edit', edit_admin_setting_path(key) %></td>
247
+ </tr>
248
+ <% end %>
249
+ </table>
250
+ ```
251
+
252
+ app/views/admin/settings/edit.html.erb
253
+
254
+ ```erb
255
+ <%= form_for(@setting, url: admin_setting_path(@setting.var), method: 'patch') do |f| %>
256
+ <label><%= @setting.var %></label>
257
+ <%= f.textarea :value, rows: 10 %>
258
+ <%= f.submit %>
259
+ <% end %>
260
+ ```
261
+
262
+ Also you may use [rails-settings-ui](https://github.com/accessd/rails-settings-ui) gem
263
+ for building ready to using interface with validations.
@@ -26,7 +26,8 @@ module Settings
26
26
  end
27
27
 
28
28
  def install_setting
29
- template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb"), force: true
29
+ template 'model.rb', File.join('app/models', class_path, "#{file_name}.rb")
30
+ template 'app.yml', File.join('config', "app.yml")
30
31
  migration_template 'migration.rb', 'db/migrate/create_settings.rb'
31
32
  end
32
33
  end
@@ -0,0 +1,13 @@
1
+ # config/app.yml for rails-settings-cached
2
+ defaults: &defaults
3
+ foo: "Foo"
4
+ bar: 123
5
+
6
+ development:
7
+ <<: *defaults
8
+
9
+ test:
10
+ <<: *defaults
11
+
12
+ production:
13
+ <<: *defaults
@@ -1,3 +1,5 @@
1
1
  # RailsSettings Model
2
2
  class <%= class_name %> < RailsSettings::CachedSettings
3
+ source Rails.root.join("config/app.yml")
4
+ namespace Rails.env
3
5
  end
@@ -1,15 +1,16 @@
1
- require_relative 'rails-settings/base'
2
1
  require_relative 'rails-settings/settings'
2
+ require_relative 'rails-settings/base'
3
3
  require_relative 'rails-settings/cached_settings'
4
4
  require_relative 'rails-settings/scoped_settings'
5
+ require_relative 'rails-settings/default'
5
6
  require_relative 'rails-settings/extend'
6
7
  require_relative 'rails-settings/version'
7
8
 
8
9
  module RailsSettings
9
10
  class Railtie < Rails::Railtie
10
11
  initializer "rails_settings.active_record.initialization" do
11
- RailsSettings::CachedSettings.after_commit :rewrite_cache, on: %i(create update)
12
- RailsSettings::CachedSettings.after_commit :expire_cache, on: %i(destroy)
12
+ RailsSettings::Base.after_commit :rewrite_cache, on: %i(create update)
13
+ RailsSettings::Base.after_commit :expire_cache, on: %i(destroy)
13
14
  end
14
15
  end
15
16
  end
@@ -1,111 +1,55 @@
1
1
  module RailsSettings
2
- class Base < ActiveRecord::Base
3
- self.table_name = table_name_prefix + 'settings'
4
-
5
- class SettingNotFound < RuntimeError; end
6
-
7
- cattr_accessor :defaults
8
- @@defaults = {}.with_indifferent_access
9
-
10
- belongs_to :thing, polymorphic: true
11
-
12
- # Support old plugin
13
- if defined?(SettingsDefaults::DEFAULTS)
14
- @@defaults = SettingsDefaults::DEFAULTS.with_indifferent_access
2
+ class Base < Settings
3
+ def rewrite_cache
4
+ Rails.cache.write(cache_key, value)
15
5
  end
16
6
 
17
- # get the value field, YAML decoded
18
- def value
19
- YAML.load(self[:value]) if self[:value].present?
7
+ def expire_cache
8
+ Rails.cache.delete(cache_key)
20
9
  end
21
10
 
22
- # set the value field, YAML encoded
23
- def value=(new_value)
24
- self[:value] = new_value.to_yaml
11
+ def cache_key
12
+ self.class.cache_key(var, thing)
25
13
  end
26
14
 
27
15
  class << self
28
- # get or set a variable with the variable as the called method
29
- def method_missing(method, *args)
30
- method_name = method.to_s
31
- super(method, *args)
32
- rescue NoMethodError
33
- # set a value for a variable
34
- if method_name[-1] == '='
35
- var_name = method_name.sub('=', '')
36
- value = args.first
37
- self[var_name] = value
38
- else
39
- # retrieve a value
40
- self[method_name]
41
- end
16
+ def cache_prefix_by_startup
17
+ @cache_prefix_by_startup ||= Time.now.to_f.to_s
42
18
  end
43
19
 
44
- # destroy the specified settings record
45
- def destroy(var_name)
46
- var_name = var_name.to_s
47
- obj = object(var_name)
48
- raise SettingNotFound, "Setting variable \"#{var_name}\" not found" if obj.nil?
49
-
50
- obj.destroy
51
- true
20
+ def cache_prefix(&block)
21
+ @cache_prefix = block
52
22
  end
53
23
 
54
- # retrieve all settings as a hash (optionally starting with a given namespace)
55
- def get_all(starting_with = nil)
56
- vars = thing_scoped.select('var, value')
57
- vars = vars.where("var LIKE '#{starting_with}%'") if starting_with
58
-
59
- result = {}
60
- vars.each do |record|
61
- result[record.var] = record.value
62
- end
63
- default_keys = @@defaults.keys
64
- default_keys = default_keys.select {|k| k.start_with? starting_with } if starting_with
65
- result.merge! @@defaults.slice(*(default_keys - result.keys))
66
-
67
- result.with_indifferent_access
24
+ def cache_key(var_name, scope_object)
25
+ scope = ["rails_settings_cached", cache_prefix_by_startup]
26
+ scope << @cache_prefix.call if @cache_prefix
27
+ scope << "#{scope_object.class.name}-#{scope_object.id}" if scope_object
28
+ scope << var_name.to_s
29
+ scope.join('/')
68
30
  end
69
31
 
70
- def where(sql = nil)
71
- vars = thing_scoped.where(sql) if sql
72
- vars
73
- end
74
-
75
- # get a setting value by [] notation
76
- def [](var_name)
77
- object(var_name).try(:value) || @@defaults[var_name.to_s]
32
+ def [](key)
33
+ val = Rails.cache.fetch(cache_key(key, @object)) do
34
+ super(key)
35
+ end
36
+ val
78
37
  end
79
38
 
80
39
  # set a setting value by [] notation
81
40
  def []=(var_name, value)
82
- var_name = var_name.to_s
41
+ super
83
42
 
84
- record = object(var_name) || thing_scoped.new(var: var_name)
85
- record.value = value
86
- record.save!
43
+ Rails.cache.write(cache_key(var_name, @object),value)
87
44
 
88
45
  value
89
46
  end
90
47
 
91
- def merge!(var_name, hash_value)
92
- raise ArgumentError unless hash_value.is_a?(Hash)
93
-
94
- old_value = self[var_name] || {}
95
- raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
96
-
97
- new_value = old_value.merge(hash_value)
98
- self[var_name] = new_value if new_value != old_value
99
-
100
- new_value
101
- end
102
-
103
- def object(var_name)
104
- thing_scoped.where(var: var_name.to_s).first
105
- end
106
-
107
- def thing_scoped
108
- unscoped.where('thing_type is NULL and thing_id is NULL')
48
+ def save_default(key, value)
49
+ Kernel.warn 'DEPRECATION WARNING: RailsSettings save_default is deprecated and it will removed in 0.7.0. ' <<
50
+ 'Please use YAML file for default setting.'
51
+ return false unless self[key].nil?
52
+ self[key] = value
109
53
  end
110
54
  end
111
55
  end
@@ -1,54 +1,9 @@
1
1
  module RailsSettings
2
2
  class CachedSettings < Base
3
- def rewrite_cache
4
- Rails.cache.write(cache_key, value)
5
- end
6
-
7
- def expire_cache
8
- Rails.cache.delete(cache_key)
9
- end
10
-
11
- def cache_key
12
- self.class.cache_key(var, thing)
13
- end
14
-
15
- class << self
16
- def cache_prefix(&block)
17
- @cache_prefix = block
18
- end
19
-
20
- def cache_key(var_name, scope_object)
21
- scope = "rails_settings_cached:"
22
- scope << "#{@cache_prefix.call}:" if @cache_prefix
23
- scope << "#{scope_object.class.name}-#{scope_object.id}:" if scope_object
24
- scope << "#{var_name}"
25
- end
26
-
27
- def [](var_name)
28
- value = Rails.cache.fetch(cache_key(var_name, @object)) do
29
- super(var_name)
30
- end
31
-
32
- if value.nil?
33
- @@defaults[var_name.to_s] if value.nil?
34
- else
35
- value
36
- end
37
- end
38
-
39
- # set a setting value by [] notation
40
- def []=(var_name, value)
41
- super
42
-
43
- Rails.cache.write(cache_key(var_name, @object),value)
44
-
45
- value
46
- end
47
-
48
- def save_default(key, value)
49
- return false unless self[key].nil?
50
- self[key] = value
51
- end
3
+ def self.inherited(subclass)
4
+ Kernel.warn 'DEPRECATION WARNING: RailsSettings::CachedSettings is deprecated and it will removed in 0.7.0. ' <<
5
+ 'Please use RailsSettings::Base instead.'
6
+ super(subclass)
52
7
  end
53
8
  end
54
9
  end
@@ -0,0 +1,43 @@
1
+ module RailsSettings
2
+ class Default < ::Hash
3
+ class MissingKey < StandardError; end
4
+
5
+ class << self
6
+ def enabled?
7
+ source_path && File.exists?(source_path)
8
+ end
9
+
10
+ def source(value = nil)
11
+ @source ||= value
12
+ end
13
+
14
+ def source_path
15
+ @source || Rails.root.join('config/app.yml')
16
+ end
17
+
18
+ def [](key)
19
+ # foo.bar.dar Nested fetch value
20
+ keys = key.to_s.split('.')
21
+ val = instance
22
+ keys.each do |k|
23
+ val = val.fetch(k.to_s, nil)
24
+ break if val.nil?
25
+ end
26
+ val
27
+ end
28
+
29
+ def instance
30
+ return @instance if defined? @instance
31
+ @instance = new
32
+ @instance
33
+ end
34
+ end
35
+
36
+ def initialize
37
+ content = open(self.class.source_path).read
38
+ hash = content.empty? ? {} : YAML.load(ERB.new(content).result).to_hash
39
+ hash = hash[Rails.env] || {}
40
+ self.replace hash
41
+ end
42
+ end
43
+ end
@@ -1,5 +1,5 @@
1
1
  module RailsSettings
2
- class ScopedSettings < CachedSettings
2
+ class ScopedSettings < Base
3
3
  def self.for_thing(object)
4
4
  @object = object
5
5
  self
@@ -1,9 +1,119 @@
1
1
  module RailsSettings
2
- class Settings < Base
3
- def self.inherited(subclass)
4
- Kernel.warn 'DEPRECATION WARNING: RailsSettings::Settings is deprecated and it will removed in 0.6.0. ' <<
5
- 'Please use RailsSettings::Base instead.'
6
- super(subclass)
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
+ def method_missing(method, *args)
22
+ method_name = method.to_s
23
+ super(method, *args)
24
+ rescue NoMethodError
25
+ # set a value for a variable
26
+ if method_name[-1] == '='
27
+ var_name = method_name.sub('=', '')
28
+ value = args.first
29
+ self[var_name] = value
30
+ else
31
+ # retrieve a value
32
+ self[method_name]
33
+ end
34
+ end
35
+
36
+ # destroy the specified settings record
37
+ def destroy(var_name)
38
+ var_name = var_name.to_s
39
+ obj = object(var_name)
40
+ raise SettingNotFound, "Setting variable \"#{var_name}\" not found" if obj.nil?
41
+
42
+ obj.destroy
43
+ true
44
+ end
45
+
46
+ # retrieve all settings as a hash (optionally starting with a given namespace)
47
+ def get_all(starting_with = nil)
48
+ vars = thing_scoped.select('var, value')
49
+ vars = vars.where("var LIKE '#{starting_with}%'") if starting_with
50
+
51
+ result = {}
52
+ vars.each do |record|
53
+ result[record.var] = record.value
54
+ end
55
+
56
+ defaults = {}
57
+ if Default.enabled?
58
+ defaults = starting_with.nil? ? Default.instance : Default.instance.fetch(starting_with, {})
59
+ end
60
+
61
+ result.merge! defaults
62
+
63
+ result.with_indifferent_access
64
+ end
65
+
66
+ def where(sql = nil)
67
+ vars = thing_scoped.where(sql) if sql
68
+ vars
69
+ end
70
+
71
+ # get a setting value by [] notation
72
+ def [](var_name)
73
+ if var = object(var_name)
74
+ val = var.value
75
+ elsif Default.enabled?
76
+ val = Default[var_name]
77
+ else
78
+ val = nil
79
+ end
80
+ val
81
+ end
82
+
83
+ # set a setting value by [] notation
84
+ def []=(var_name, value)
85
+ var_name = var_name.to_s
86
+
87
+ record = object(var_name) || thing_scoped.new(var: var_name)
88
+ record.value = value
89
+ record.save!
90
+
91
+ value
92
+ end
93
+
94
+ def merge!(var_name, hash_value)
95
+ raise ArgumentError unless hash_value.is_a?(Hash)
96
+
97
+ old_value = self[var_name] || {}
98
+ raise TypeError, "Existing value is not a hash, can't merge!" unless old_value.is_a?(Hash)
99
+
100
+ new_value = old_value.merge(hash_value)
101
+ self[var_name] = new_value if new_value != old_value
102
+
103
+ new_value
104
+ end
105
+
106
+ def object(var_name)
107
+ thing_scoped.where(var: var_name.to_s).first
108
+ end
109
+
110
+ def thing_scoped
111
+ unscoped.where('thing_type is NULL and thing_id is NULL')
112
+ end
113
+
114
+ def source(filename)
115
+ Default.source(filename)
116
+ end
7
117
  end
8
118
  end
9
119
  end
@@ -1,7 +1,7 @@
1
1
  module RailsSettings
2
2
  class << self
3
3
  def version
4
- "0.5.6"
4
+ "0.6.0"
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rails-settings-cached
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jason Lee
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2016-04-11 00:00:00.000000000 Z
14
+ date: 2016-04-20 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: rails
@@ -40,11 +40,13 @@ extra_rdoc_files: []
40
40
  files:
41
41
  - README.md
42
42
  - lib/generators/settings/install_generator.rb
43
+ - lib/generators/settings/templates/app.yml
43
44
  - lib/generators/settings/templates/migration.rb
44
45
  - lib/generators/settings/templates/model.rb
45
46
  - lib/rails-settings-cached.rb
46
47
  - lib/rails-settings/base.rb
47
48
  - lib/rails-settings/cached_settings.rb
49
+ - lib/rails-settings/default.rb
48
50
  - lib/rails-settings/extend.rb
49
51
  - lib/rails-settings/scoped_settings.rb
50
52
  - lib/rails-settings/settings.rb