rails-settings-cached 0.5.6 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
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