settingson 1.6.0 → 1.6.1

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml CHANGED
@@ -11,3 +11,6 @@ rvm:
11
11
  gemfile:
12
12
  - gemfiles/4.2.gemfile
13
13
  - gemfiles/5.0.gemfile
14
+
15
+ env:
16
+ - CODECLIMATE_REPO_TOKEN=620b22e287791de2c9f8a522182ddf57098302ff8958768f8192eaaa7d8a685d
data/Gemfile CHANGED
@@ -2,3 +2,5 @@ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in settingson.gemspec
4
4
  gemspec
5
+
6
+ gem "codeclimate-test-reporter", group: :test, require: nil
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  [![Gem Version](https://badge.fury.io/rb/settingson.svg)](http://badge.fury.io/rb/settingson)
2
2
  [![Build Status](https://travis-ci.org/daanforever/settingson.svg?branch=master)](https://travis-ci.org/daanforever/settingson)
3
3
  [![Code Climate](https://codeclimate.com/github/daanforever/settingson/badges/gpa.svg)](https://codeclimate.com/github/daanforever/settingson)
4
+ [![Test Coverage](https://codeclimate.com/github/daanforever/settingson/badges/coverage.svg)](https://codeclimate.com/github/daanforever/settingson/coverage)
4
5
 
5
6
  # Settingson
6
7
 
@@ -111,23 +112,15 @@ end
111
112
  New way:
112
113
  in config/initializers/settingson.rb
113
114
  ```ruby
114
- Settings.defaults do
115
- Settings.server.smtp.host? || Settings.server.smtp.host = 'host'
116
- Settings.server.smtp.port? || Settings.server.smtp.port = 25
115
+ Settings.defaults do |conf|
116
+ conf.server.smtp.host = 'host'
117
+ conf.server.smtp.port = 25
117
118
  end
118
119
  ```
119
120
 
120
- Old way:
121
- in config/initializers/settingson.rb
122
121
  ```ruby
123
- Rails.application.config.after_initialize do
124
- begin
125
- Settings.server.smtp.host? || Settings.server.smtp.host = 'host'
126
- Settings.server.smtp.port? || Settings.server.smtp.port = '25'
127
- rescue
128
- Rails.logger.warn('Something goes wrong')
129
- end
130
- end
122
+ conf.server.smtp.host # => 'host'
123
+ conf.server.smtp.port # => 25
131
124
  ```
132
125
 
133
126
  ## Contributing
@@ -11,9 +11,8 @@ module Settingson::Base
11
11
  #
12
12
  # # or
13
13
  #
14
- # Settings.configure.expires = 600
15
- # Settings.configure.enabled = true
16
-
14
+ # Settings.configure.cache.expires = 600
15
+ # Settings.configure.cache.enabled = true
17
16
  def configure
18
17
  @_settings ||= ::Settingson::Config.new
19
18
  yield @_settings if block_given?
@@ -24,32 +23,15 @@ module Settingson::Base
24
23
  # settings.server.host = 'host'
25
24
  # settings.server.port = 80
26
25
  # end
27
- # FIXME: not ready yet
28
26
  def defaults
27
+ return unless block_given?
29
28
  Rails.application.config.after_initialize do
30
- begin
31
- yield new(settingson: 'defaults') if block_given?
32
- rescue
33
- Rails.logger.warn('Settingson::defaults failed')
34
- end
29
+ yield Settingson::Store.new( klass: self, path: '__defaults' )
35
30
  end
36
- true
37
- end
38
-
39
- # Settings.delete_all
40
- # Delete cached items before super
41
- def delete_all
42
- Rails.cache.delete_matched(/#{self.configure.cache.namespace}/)
43
- super
44
31
  end
45
32
 
46
33
  # Settings.from_hash('smtp.host' => 'host')
47
-
48
- def cached(*args)
49
- ActiveSupport::Deprecation.warn('Now caching is enabled by default')
50
- self.new
51
- end
52
-
34
+ # Settings.smtp.host
53
35
  def from_hash(attributes)
54
36
  case attributes
55
37
  when Hash
@@ -61,102 +43,29 @@ module Settingson::Base
61
43
  end
62
44
  end
63
45
 
64
- def method_missing(symbol, *args)
46
+ # Custom hook for clear cache before delete_all
47
+ #
48
+ def delete_all
65
49
  super
66
- rescue NameError
67
- self.new.send(symbol, *args)
68
- rescue NoMethodError
69
- self.new.send(symbol, *args)
50
+ Rails.cache.delete_matched(/#{self.configure.cache.namespace}/)
70
51
  end
71
52
 
53
+ def method_missing(symbol, *args)
54
+ super
55
+ rescue NameError, NoMethodError
56
+ Settingson::Store.new(klass: self).send(symbol, args.first)
57
+ end
72
58
 
73
59
  end # module ClassMethods
74
60
 
75
61
  included do
76
- attr_accessor :settingson
77
62
  serialize :value
78
63
  before_destroy :__delete_cached
79
64
  end
80
65
 
81
- def __debug(message)
82
- Rails.logger.debug(message) if self.class.configure.debug
83
- end
84
-
85
66
  def __delete_cached
86
67
  cache_key = "#{self.class.configure.cache.namespace}/#{self.key}"
87
68
  Rails.cache.delete(cache_key)
88
- __debug("#{self.class.name}: delete '#{self.key}' '#{cache_key}'")
89
- end
90
-
91
- def to_s
92
- self.new_record? ? '' : super
93
- end
94
-
95
- def inspect
96
- self.new_record? ? '""' : super
97
- end
98
-
99
- def to_i
100
- self.new_record? ? 0 : super
101
- end
102
-
103
- def nil?
104
- self.new_record? ? true : super
105
- end
106
-
107
- alias empty? nil?
108
-
109
- def method_missing(symbol, *args)
110
- super
111
- rescue NameError
112
- __rescue_action(symbol.to_s, args.first)
113
- rescue NoMethodError
114
- __rescue_action(symbol.to_s, args.first)
115
- end # method_missing
116
-
117
- protected
118
-
119
- def __cached_key
120
- [ self.class.configure.cache.namespace, @settingson ].join('/')
121
- end
122
-
123
- def __rescue_action(key, value)
124
- case key
125
- when /(.+)=/ # setter
126
- @settingson = [@settingson, $1].compact.join('.')
127
- record = self.class.find_or_create_by!(key: @settingson)
128
- record.update!(value: value)
129
- Rails.cache.write(__cached_key, value)
130
- __debug("#{self.class.name}##{__method__} setter '#{__cached_key}'")
131
- record.value
132
- else # returns values or self
133
- @settingson = [@settingson, key].compact.join('.')
134
- __debug("#{self.class.name}##{__method__} getter '#{@settingson}'")
135
- __cached_value_or_self
136
- end
137
- end
138
-
139
- def __cached_value_or_self
140
- result = __cached_value
141
- result.is_a?(ActiveRecord::RecordNotFound) ? self : result
142
- end
143
-
144
- def __cached_value
145
- __debug("#{self.class.name}##{__method__} '#{@settingson}'")
146
- Rails.cache.fetch(
147
- __cached_key,
148
- expires_in: self.class.configure.cache.expires,
149
- race_condition_ttl: self.class.configure.cache.race_condition_ttl
150
- ) do
151
- __debug("#{self.class.name}: fresh '#{@settingson}'")
152
- __fresh_value
153
- end
154
- end
155
-
156
- def __fresh_value
157
- self.class.find_by!(key: @settingson).value
158
- rescue ActiveRecord::RecordNotFound
159
- ActiveRecord::RecordNotFound.new
160
69
  end
161
70
 
162
71
  end # Settingson::Base
data/gemfiles/4.2.gemfile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "codeclimate-test-reporter", :group => :test, :require => nil
5
6
  gem "rails", "~> 4.2.0"
6
7
 
7
8
  gemspec :path => "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- settingson (1.5.14)
4
+ settingson (1.6.0)
5
5
  rails (>= 4.0)
6
6
 
7
7
  GEM
@@ -48,9 +48,12 @@ GEM
48
48
  thor (>= 0.14.0)
49
49
  arel (6.0.3)
50
50
  builder (3.2.2)
51
+ codeclimate-test-reporter (0.6.0)
52
+ simplecov (>= 0.7.1, < 1.0.0)
51
53
  concurrent-ruby (1.0.2)
52
54
  database_cleaner (1.5.3)
53
55
  diff-lcs (1.2.5)
56
+ docile (1.1.5)
54
57
  erubis (2.7.0)
55
58
  faker (1.6.6)
56
59
  i18n (~> 0.5)
@@ -122,6 +125,11 @@ GEM
122
125
  rspec-mocks (~> 3.5.0)
123
126
  rspec-support (~> 3.5.0)
124
127
  rspec-support (3.5.0)
128
+ simplecov (0.12.0)
129
+ docile (~> 1.1.0)
130
+ json (>= 1.8, < 3)
131
+ simplecov-html (~> 0.10.0)
132
+ simplecov-html (0.10.0)
125
133
  spring (1.7.2)
126
134
  spring-commands-rspec (1.0.4)
127
135
  spring (>= 0.9.1)
@@ -144,6 +152,7 @@ PLATFORMS
144
152
  DEPENDENCIES
145
153
  appraisal
146
154
  bundler (>= 1.6)
155
+ codeclimate-test-reporter
147
156
  database_cleaner
148
157
  faker
149
158
  rails (~> 4.2.0)
data/gemfiles/5.0.gemfile CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "codeclimate-test-reporter", :group => :test, :require => nil
5
6
  gem "rails", "~> 5.0.0"
6
7
 
7
8
  gemspec :path => "../"
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- settingson (1.5.14)
4
+ settingson (1.6.0)
5
5
  rails (>= 4.0)
6
6
 
7
7
  GEM
@@ -50,15 +50,19 @@ GEM
50
50
  thor (>= 0.14.0)
51
51
  arel (7.1.2)
52
52
  builder (3.2.2)
53
+ codeclimate-test-reporter (0.6.0)
54
+ simplecov (>= 0.7.1, < 1.0.0)
53
55
  concurrent-ruby (1.0.2)
54
56
  database_cleaner (1.5.3)
55
57
  diff-lcs (1.2.5)
58
+ docile (1.1.5)
56
59
  erubis (2.7.0)
57
60
  faker (1.6.6)
58
61
  i18n (~> 0.5)
59
62
  globalid (0.3.7)
60
63
  activesupport (>= 4.1.0)
61
64
  i18n (0.7.0)
65
+ json (2.0.2)
62
66
  loofah (2.0.3)
63
67
  nokogiri (>= 1.5.9)
64
68
  mail (2.6.4)
@@ -124,6 +128,11 @@ GEM
124
128
  rspec-mocks (~> 3.5.0)
125
129
  rspec-support (~> 3.5.0)
126
130
  rspec-support (3.5.0)
131
+ simplecov (0.12.0)
132
+ docile (~> 1.1.0)
133
+ json (>= 1.8, < 3)
134
+ simplecov-html (~> 0.10.0)
135
+ simplecov-html (0.10.0)
127
136
  spring (1.7.2)
128
137
  spring-commands-rspec (1.0.4)
129
138
  spring (>= 0.9.1)
@@ -149,6 +158,7 @@ PLATFORMS
149
158
  DEPENDENCIES
150
159
  appraisal
151
160
  bundler (>= 1.6)
161
+ codeclimate-test-reporter
152
162
  database_cleaner
153
163
  faker
154
164
  rails (~> 5.0.0)
@@ -1,4 +1,108 @@
1
- module Settingson::Store
1
+ class Settingson::Store
2
2
 
3
+ def initialize(klass:, path: nil)
4
+ @__klass = klass
5
+ @__path = path
6
+ end
7
+
8
+ def to_s
9
+ self.new_record? ? '' : super
10
+ end
11
+
12
+ def to_i
13
+ self.new_record? ? 0 : super
14
+ end
15
+
16
+ def nil?
17
+ self.new_record? ? true : super
18
+ end
19
+
20
+ alias empty? nil?
21
+
22
+ def method_missing(symbol, *args)
23
+ __rescue_action(symbol.to_s, args.first)
24
+ end # method_missing
25
+
26
+ protected
27
+
28
+ def __debug(message)
29
+ message = sprintf("%s#%-32s: %s",
30
+ self.class.name,
31
+ caller_locations.first.label,
32
+ message)
33
+ Rails.logger.debug(message) if @__klass.configure.debug
34
+ end
35
+
36
+ def __rescue_action(key, value)
37
+ case key
38
+ when /(.+)=/ # setter
39
+ __debug("set '#{$1}' value '#{value}' path '#{@__path}'")
40
+ __set($1, value)
41
+ else # returns values or self
42
+ __debug("get '#{key}' value '#{value}' path '#{@__path}'")
43
+ __get(key)
44
+ end
45
+ end
46
+
47
+ def __set(key, value)
48
+ __update_search_path(key)
49
+ if record = @__klass.find_by(key: @__path)
50
+ record.update!(value: value)
51
+ else
52
+ @__klass.create!(key: @__path, value: value)
53
+ end
54
+ Rails.cache.write(__cache_key(@__path), value)
55
+ value
56
+ end
57
+
58
+ def __get(key)
59
+ __update_search_path(key)
60
+ result = __cached_or_default_value(@__path)
61
+
62
+ if result.is_a?(ActiveRecord::RecordNotFound)
63
+ __debug("return self with path: #{@__path}")
64
+ self
65
+ else
66
+ __debug("return result")
67
+ result
68
+ end
69
+ end
70
+
71
+ def __update_search_path(key)
72
+ @__path = [@__path, key].compact.join('.')
73
+ end
74
+
75
+ def __cached_or_default_value(key)
76
+ result = __cached_value(key)
77
+
78
+ if result.is_a?(ActiveRecord::RecordNotFound) # Try defaults
79
+ __cached_value('__defaults.' + key)
80
+ else
81
+ result
82
+ end
83
+ end
84
+
85
+ def __cache_key(key)
86
+ [ @__klass.configure.cache.namespace, key ].join('/')
87
+ end
88
+
89
+ def __cached_value(key)
90
+ __debug("looking in cache '#{__cache_key(key)}'")
91
+ Rails.cache.fetch(
92
+ __cache_key(key),
93
+ expires_in: @__klass.configure.cache.expires,
94
+ race_condition_ttl: @__klass.configure.cache.race_condition_ttl
95
+ ) do
96
+ __debug("ask DB '#{key}'")
97
+ __get_from_db(key)
98
+ end
99
+ end
100
+
101
+ def __get_from_db(key)
102
+ @__klass.find_by!(key: key).value
103
+ rescue ActiveRecord::RecordNotFound
104
+ __debug("not found")
105
+ ActiveRecord::RecordNotFound.new
106
+ end
3
107
 
4
108
  end
@@ -1,3 +1,3 @@
1
1
  module Settingson
2
- VERSION = "1.6.0"
2
+ VERSION = "1.6.1"
3
3
  end
@@ -0,0 +1 @@
1
+ Settings.configure.debug = true
@@ -2,9 +2,32 @@ require 'spec_helper'
2
2
 
3
3
  describe Settings do
4
4
 
5
- describe 'Settings.defaults' do
6
- it 'not raises errors' do
7
- expect{ Settings.default {} }.to_not raise_error
5
+ describe '::defaults' do
6
+ it 'not raises errors without parameters' do
7
+ expect{ Settings.defaults {} }.to_not raise_error
8
+ end
9
+
10
+ it 'returns default value for simple value' do
11
+ word = Faker::Lorem.word
12
+ Settings.defaults{|s| s.cached_key = word}
13
+ expect( Settings.cached_key ).to eq(word)
14
+ end
15
+
16
+ it 'returns default value for complex value' do
17
+ word = Faker::Lorem.word
18
+ Settings.defaults{|s| s.some.key = word}
19
+ expect( Settings.some.key ).to eq(word)
20
+ end
21
+ end
22
+
23
+ describe '::from_hash' do
24
+ it 'accessable by hash key' do
25
+ Settings.from_hash(hello: :world)
26
+ expect( Settings.hello ).to eq(:world)
27
+ end
28
+
29
+ it 'raises error when not Hash' do
30
+ expect{Settings.from_hash([:hello, :world])}.to raise_error(ArgumentError)
8
31
  end
9
32
  end
10
33
 
@@ -15,11 +38,13 @@ describe Settings do
15
38
  it 'not raises error on create new element' do
16
39
  expect{ Settings.hello = Faker::Lorem.word }.to_not raise_error
17
40
  end
18
- it 'returns same Fixnum' do
19
- word = Faker::Lorem.word
41
+ it 'returns same Fixnum #1' do
20
42
  Settings.number = 100
21
43
  expect( Settings.number ).to eq(100)
22
44
  end
45
+ it 'returns 0 when key not found' do
46
+ expect( Settings.not_found.to_i ).to eq(0)
47
+ end
23
48
  it 'returns same String' do
24
49
  word = Faker::Lorem.word
25
50
  Settings.hello = word
@@ -27,13 +52,18 @@ describe Settings do
27
52
  end
28
53
  it 'returns same value for complex key #1' do
29
54
  word = Faker::Lorem.word
30
- Settings.hello.hello = word
31
- expect( Settings.hello.hello ).to eq(word)
55
+ Settings.hello1.hello2 = word
56
+ expect( Settings.hello1.hello2 ).to eq(word)
32
57
  end
33
58
  it 'returns same value for complex key #2' do
34
59
  word = Faker::Lorem.word
35
- Settings.i.hello = word
36
- expect( Settings.i.hello ).to eq(word)
60
+ Settings.hello.key = word
61
+ expect( Settings.hello.key ).to eq(word)
62
+ end
63
+ it 'returns same value for complex key #3' do
64
+ word = Faker::Lorem.word
65
+ Settings.hello.hello = word
66
+ expect( Settings.hello.hello ).to eq(word)
37
67
  end
38
68
  it 'not destroys record with nil value #1' do
39
69
  word = Faker::Lorem.word
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,8 @@
1
1
  ENV["RAILS_ENV"] ||= 'test'
2
2
 
3
+ require "codeclimate-test-reporter"
4
+ CodeClimate::TestReporter.start
5
+
3
6
  require ::File.expand_path('../dummy/config/environment', __FILE__)
4
7
  require 'rspec/rails'
5
8
  require 'database_cleaner'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: settingson
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.6.0
4
+ version: 1.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - dan
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-09-16 00:00:00.000000000 Z
11
+ date: 2016-09-19 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -157,8 +157,10 @@ executables: []
157
157
  extensions: []
158
158
  extra_rdoc_files: []
159
159
  files:
160
+ - ".codeclimate.yml"
160
161
  - ".gitignore"
161
162
  - ".rspec"
163
+ - ".rubocop.yml"
162
164
  - ".travis.yml"
163
165
  - Appraisals
164
166
  - Gemfile
@@ -212,6 +214,7 @@ files:
212
214
  - spec/dummy/config/initializers/inflections.rb
213
215
  - spec/dummy/config/initializers/mime_types.rb
214
216
  - spec/dummy/config/initializers/session_store.rb
217
+ - spec/dummy/config/initializers/settingson.rb
215
218
  - spec/dummy/config/initializers/wrap_parameters.rb
216
219
  - spec/dummy/config/locales/en.yml
217
220
  - spec/dummy/config/routes.rb
@@ -286,6 +289,7 @@ test_files:
286
289
  - spec/dummy/config/initializers/inflections.rb
287
290
  - spec/dummy/config/initializers/mime_types.rb
288
291
  - spec/dummy/config/initializers/session_store.rb
292
+ - spec/dummy/config/initializers/settingson.rb
289
293
  - spec/dummy/config/initializers/wrap_parameters.rb
290
294
  - spec/dummy/config/locales/en.yml
291
295
  - spec/dummy/config/routes.rb