setti 0.0.1

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.
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZTg5YzdkZjAyZDkxMzRmNmM4YjE0MTQxODhhNTk3OGM2MmExMzBiNg==
5
+ data.tar.gz: !binary |-
6
+ ODFmNzAxN2JhYTAwNjcyYTI3MjY3MzNlNTAzOWFlYzgyNTExZjk0Mw==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ NWQ2ZWY2NmM3MGQ5ZGYzNTk0YzA4MTE0ZWFhODdjYTE2Y2UwNjBlNmZiNDRl
10
+ ZDM0ZDBkMDI2MGNkYTlhZjBlYzQ4Zjk5NzExYjQ1NWYyMTc0ZjZlYWU3MTVh
11
+ Y2U1ZDhkMDE5ZTg5MWRkMTMxODI3ZjNhYTRkYmMzYzM1NTllMDQ=
12
+ data.tar.gz: !binary |-
13
+ YWE2NTNjZjgwMDI5YmExMGE0ZjQ2ODI1NWI3MzBlZTljOWI3YjYxNGM2OWU4
14
+ NGVlMGEwNDQxYjQzYmM2YjI1NWM4ODJiYWEyYmYwMTRjZGZiOTA2MjJlOTlj
15
+ ZGY5ODIyNDAyOTZkMThhNWVlZDZiZDNiYTc4OWFmZDZhMDE3ZTM=
@@ -0,0 +1,15 @@
1
+ require 'rspec/core/rake_task'
2
+
3
+ RSpec::Core::RakeTask.new(:spec)
4
+
5
+ begin
6
+ require 'rubocop/rake_task'
7
+ Rubocop::RakeTask.new
8
+ rescue LoadError
9
+ desc 'Run RuboCop'
10
+ task :rubocop do
11
+ $stderr.puts 'Rubocop is disabled'
12
+ end
13
+ end
14
+
15
+ task default: [:spec, :rubocop]
@@ -0,0 +1,4 @@
1
+ module Setti
2
+ autoload :Settings, 'setti/settings'
3
+ autoload :IndifferentHash, 'setti/indifferent_hash'
4
+ end
@@ -0,0 +1,12 @@
1
+ module Setti
2
+ class IndifferentHash < Hash
3
+ def [](name)
4
+ value = super(name.to_s)
5
+ if value.is_a?(Hash)
6
+ IndifferentHash[value]
7
+ else
8
+ value
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,71 @@
1
+ require 'oj'
2
+
3
+ module Setti
4
+ class Settings
5
+ def initialize(path)
6
+ assert File.exist?(path), error: "No such file or directory: #{path}"
7
+ @settings = Oj.load(IO.read(path), mode: :compat)
8
+ end
9
+
10
+ def validate(name, *args, &block)
11
+ value = lookup_property(name)
12
+ case args.first
13
+ when nil then nil_check!(name, value, block)
14
+ when :number then number_check!(name, value)
15
+ when :float then float_check!(name, value)
16
+ when :integer then int_check!(name, value)
17
+ when :regex then regex_check!(name, value, args.last)
18
+ end
19
+ end
20
+
21
+ def [](name)
22
+ with_indifferent_hash lookup_property(name)
23
+ end
24
+
25
+ private
26
+
27
+ def nil_check!(name, value, block)
28
+ fail "#{name}=#{value} does not comply with the validation" unless block.call(value)
29
+ end
30
+
31
+ def number_check!(name, value)
32
+ fail "#{name}=#{value} is not a number" unless [Integer, Fixnum, Float].include? value.class
33
+ end
34
+
35
+ def float_check!(name, value)
36
+ fail "#{name}=#{value} is not a float" unless value.is_a? Float
37
+ end
38
+
39
+ def int_check!(name, value)
40
+ fail "#{name}=#{value} is not an integer" unless [Integer, Fixnum].include? value.class
41
+ end
42
+
43
+ def regex_check!(name, value, regex)
44
+ fail "#{name}=#{value} does not match #{regex}" unless value =~ regex
45
+ end
46
+
47
+ def lookup_property(name)
48
+ if name.is_a?(String) && name.include?('.')
49
+ lookup_value_dot_path(name)
50
+ else
51
+ IndifferentHash[@settings][name]
52
+ end
53
+ end
54
+
55
+ def lookup_value_dot_path(name)
56
+ names = name.split('.')
57
+ names.inject(@settings) do |walker, cur_name|
58
+ fail "Not found: #{name}" unless walker[cur_name]
59
+ walker[cur_name]
60
+ end
61
+ end
62
+
63
+ def assert(condition, options = {})
64
+ fail options[:error] unless condition
65
+ end
66
+
67
+ def with_indifferent_hash(value)
68
+ value.is_a?(Hash) ? IndifferentHash[value] : value
69
+ end
70
+ end
71
+ end
@@ -0,0 +1,3 @@
1
+ module Setti
2
+ VERSION = '0.0.1'
3
+ end
@@ -0,0 +1,19 @@
1
+ {
2
+ "numbers": {
3
+ "integers": {
4
+ "bad": "80",
5
+ "good": 80
6
+ },
7
+ "floats": {
8
+ "bad": "5.5",
9
+ "good": 5.5
10
+ }
11
+ },
12
+ "regexes": {
13
+ "good": "5abc",
14
+ "bad": "abcd"
15
+ },
16
+ "procs": {
17
+ "true": true
18
+ }
19
+ }
@@ -0,0 +1,49 @@
1
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'setti')
2
+ require 'spec_helper'
3
+
4
+ describe Setti::Settings do
5
+ subject { Setti::Settings.new(File.join(File.dirname(__FILE__), 'sample.json')) }
6
+
7
+ it 'does load sample config file' do
8
+ expect { subject }.to_not raise_error
9
+ end
10
+
11
+ it 'does provide dot accessors' do
12
+ expect(subject['numbers.integers.bad']).to eql('80')
13
+ expect(subject['numbers.integers.good']).to eql(80)
14
+ end
15
+
16
+ it 'does provide hash accessors' do
17
+ expect(subject['numbers']['integers']['bad']).to eql('80')
18
+ expect(subject['numbers']['integers']['good']).to eql(80)
19
+
20
+ # Symbols and also recursive
21
+ expect(subject[:numbers][:integers][:bad]).to eql('80')
22
+ expect(subject[:numbers][:integers][:good]).to eql(80)
23
+ end
24
+
25
+ it 'does validate numbers' do
26
+ expect { subject.validate 'numbers.integers.bad', :number }.to raise_error
27
+ expect { subject.validate 'numbers.integers.good', :number }.to_not raise_error
28
+ expect { subject.validate 'numbers.floats.bad', :float }.to raise_error
29
+ expect { subject.validate 'numbers.floats.good', :float }.to_not raise_error
30
+ end
31
+
32
+ it 'does validate regexes' do
33
+ expect { subject.validate 'regexes.good', :regex, /^\d[a-zA-Z]{3}$/ }.to_not raise_error
34
+ expect { subject.validate 'regexes.bad', :regex, /^\d[a-zA-Z]{3}$/ }.to raise_error
35
+ end
36
+
37
+ it 'does validate procs' do
38
+ expect { subject.validate('procs.true') { |val| val } }.to_not raise_error
39
+ expect { subject.validate('procs.true') { |val| !val } }.to raise_error
40
+ end
41
+
42
+ context 'Config. file missing' do
43
+ subject { Setti::Settings.new('foo.json') }
44
+
45
+ it 'does raise a ENOENT error' do
46
+ expect { subject }.to raise_error
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,2 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
metadata ADDED
@@ -0,0 +1,97 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: setti
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - André Dieb Martins
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-06-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: oj
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '2.9'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '2.9'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '10.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '10.3'
55
+ description: Fast indifferent-access JSON settings framework, validation included.
56
+ email:
57
+ - andre.dieb@gmail.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - Rakefile
63
+ - lib/setti.rb
64
+ - lib/setti/indifferent_hash.rb
65
+ - lib/setti/settings.rb
66
+ - lib/setti/version.rb
67
+ - spec/sample.json
68
+ - spec/settings_spec.rb
69
+ - spec/spec_helper.rb
70
+ homepage: https://github.com/dieb/setti
71
+ licenses:
72
+ - MIT
73
+ metadata: {}
74
+ post_install_message:
75
+ rdoc_options: []
76
+ require_paths:
77
+ - lib
78
+ required_ruby_version: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ required_rubygems_version: !ruby/object:Gem::Requirement
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: '0'
88
+ requirements: []
89
+ rubyforge_project:
90
+ rubygems_version: 2.2.2
91
+ signing_key:
92
+ specification_version: 4
93
+ summary: Settings microframework for ruby applications.
94
+ test_files:
95
+ - spec/sample.json
96
+ - spec/settings_spec.rb
97
+ - spec/spec_helper.rb