smart_kv 0.2.6 → 0.2.7

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
  SHA256:
3
- metadata.gz: 58e421790894c41c5608d79fcfb86c604b18e9f98f0a1591e76589358a5f31c9
4
- data.tar.gz: 7916f3b61f1d53cd56ee4db704ea5424dd9b5b764dfefd2946eadd8eea3c2452
3
+ metadata.gz: a40cd8eb22b67d869043b25fd77f73700f21c40dd0302cfc6d59d436fd89027f
4
+ data.tar.gz: faca0c5c75a0437de06f2e8a7eddd64097578b49187a46f0aecc4abfcf350c26
5
5
  SHA512:
6
- metadata.gz: 41edbc48494258f1c55db913009e6cb722f2f70bbcba721afbc6d0a86b17f507b919dd58086aecbf2f6b8a78a00b474e12786c1bfca1aaa29cf62bcfcff1f844
7
- data.tar.gz: 9a9b0280c67b828262442b27bebc28e70b77922facd2115e5dd19d5091c0959f705cb938cae5432d2888a1a4a3dbcb2ca37a0e653c0e902163c3266498e5abc2
6
+ metadata.gz: d4c7ee93525e01eb972ded20303bdb252897c009fbb6e0901d16e26481a7d859e8884b6f6cb44b51ea5569bb4ef8709cbfff05d1aaefbf2f188a1a898fd07bb2
7
+ data.tar.gz: 0fb4bce5f669b7afb31b5430e6aeb69b768b1e5acce875a9249976162c11a716490893aea011a669259344684a8730f06695474724877bc702681c52d0db545b
data/README.md CHANGED
@@ -4,10 +4,7 @@
4
4
  [![Coverage Status](https://coveralls.io/repos/github/styd/smart_kv/badge.svg?branch=master)](https://coveralls.io/github/styd/smart_kv?branch=master)
5
5
  [![Gem Version](https://badge.fury.io/rb/smart_kv.svg)](https://rubygems.org/gems/smart_kv)
6
6
 
7
- Best practice of writing options or configurations by strictly allowing and requiring keys.
8
-
9
- It doesn't have to be options or configurations.
10
- You can use it for strict request body or other use cases too.
7
+ Write options or configurations without worry of typos and the need to remember all the keys.
11
8
 
12
9
  ## Background
13
10
 
@@ -19,24 +16,12 @@ d = DateTime.now
19
16
  e = d.change(hour: 1, minute: 5)
20
17
  ```
21
18
 
22
- and then move on with your life.. until you realize that the code doesn't behave as you expected it to behave.
23
- But why? Everything looks fine, right? Yes, it does look fine.. but it's not fine.
24
-
25
- So, what's the problem?
26
- The problem was the option key `:minute` was not recognized.
27
- Eh? :confused:
28
- Why didn't it tell me if it was not recognized?
29
-
30
- I wish that too.
31
- But `Hash` has a default value of `nil` if key is not found (same thing applies to `OpenStruct`).
32
- So, it will fail gracefully even if an option is actually required, unless the developer uses `#fetch` instead of `#[]`.
33
- Even if the developer uses `#fetch` for required keys, it doesn't actually check if there are foreign keys input.
34
- Also, most developers won't bother checking each options' key made by the users of the library or method.
35
-
19
+ You think everything works fine, but it's not.
20
+ There is no key `:minute` in options used by `#change`.
36
21
  If only the source of the `DateTime#change` method starts like this:
37
22
 
38
23
  ```ruby
39
- # this class can be defined on its own file
24
+ # this class can be defined on its own file, just remember to require it
40
25
  class ChangeOptions < SmartKv
41
26
  optional :nsec, :usec, :year, :month, :day, :hour, :min, :sec, :offset, :start
42
27
  end
@@ -44,7 +29,7 @@ end
44
29
  class DateTime
45
30
  ...
46
31
  def change(options)
47
- options = ChangeOptions.new(options)
32
+ options = ChangeOptions.check(options)
48
33
  ...
49
34
  end
50
35
  end
@@ -53,14 +38,14 @@ end
53
38
  So, when you do this `d.change(hour: 1, minute: 5)`, it will yell:
54
39
 
55
40
  ```
56
- NotImplementedError: unrecognized key(s): `:minute' in ChangeOptions
41
+ KeyError: unrecognized key: :minute in ChangeOptions
57
42
  ```
58
43
 
59
44
  Well, this is better. But, how do you know all the right options?
60
- Type: `ChangeOptions.optional_keys` and `ChangeOptions.required_keys`.
45
+ Type: `ChangeOptions.keys`
61
46
 
62
47
 
63
- ## More Usage Example
48
+ ## More Usage Examples
64
49
 
65
50
  ```ruby
66
51
  class Config < SmartKv
@@ -68,7 +53,7 @@ class Config < SmartKv
68
53
  optional :an_option
69
54
  end
70
55
 
71
- Config.new({some_key: "val"})
56
+ Config.check({some_key: "val"})
72
57
  ```
73
58
 
74
59
  This will complain that you're not using the `:second key`.
@@ -83,7 +68,7 @@ class ChildConfig < Config
83
68
  required :first_key
84
69
  end
85
70
 
86
- ChildConfig.new({first_key: "val", second_key: "val 2"})
71
+ ChildConfig.check({first_key: "val", second_key: "val 2"})
87
72
  ```
88
73
 
89
74
  This will also complain that you're not using the `:some_key`.
@@ -94,10 +79,10 @@ This will also complain that you're not using the `:some_key`.
94
79
  Whatever given as input is callable directly.
95
80
 
96
81
  ```ruby
97
- c = Config.new({some_key: "val", second_key: "val 2"})
82
+ c = Config.check({some_key: "val", second_key: "val 2"})
98
83
  c[:some_key]
99
84
 
100
- c2 = Config.new(OpenStruct.new({some_key: "val", second_key: "val 2"}))
85
+ c2 = Config.check(OpenStruct.new({some_key: "val", second_key: "val 2"}))
101
86
  c2.second_key
102
87
  ```
103
88
 
@@ -112,7 +97,7 @@ class Convertable < SmartKv
112
97
  callable_as OpenStruct
113
98
  end
114
99
 
115
- c = Convertable.new({abcd: 123})
100
+ c = Convertable.check({abcd: 123})
116
101
  c.abcd #=> 123
117
102
  ```
118
103
 
@@ -127,7 +112,7 @@ class PostBody < SmartKv
127
112
  end
128
113
  .
129
114
  .
130
- request.set_form_data(PostBody.new({app_key: "abc", secret_key: "def"}))
115
+ request.set_form_data(PostBody.check({app_key: "abc", secret_key: "def"}))
131
116
  ```
132
117
 
133
118
 
@@ -139,20 +124,6 @@ Add this line to your application's Gemfile:
139
124
  gem 'smart_kv'
140
125
  ```
141
126
 
142
- And then execute:
143
-
144
- $ bundle
145
-
146
-
147
- ## Coming Soon
148
-
149
- - [X] Convertable from hash (as input) to OpenStruct (the resulting object) or another object and vice versa
150
- - [X] Suggests corrections for unrecognized keys using DidYouMean
151
- - [ ] Support nested/deep key value object as input
152
- - [ ] Make some nested keys from the same parent key required and some others optional
153
- - [ ] Accept config file (e.g. `json`, `yaml`, etc.) or file path as input
154
-
155
-
156
127
  ## Contributing
157
128
 
158
129
  Bug reports and pull requests are welcome on GitHub at https://github.com/styd/smart_kv. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
@@ -161,8 +132,3 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/styd/s
161
132
  ## License
162
133
 
163
134
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
164
-
165
-
166
- ## Code of Conduct
167
-
168
- Everyone interacting in the SmartKv project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/styd/smart_kv/blob/master/CODE_OF_CONDUCT.md).
@@ -1,6 +1,6 @@
1
1
  module SmartKv::Check
2
2
  def has_did_you_mean_key_error?
3
- !ENV['TRAVIS'] && defined?(DidYouMean::KeyErrorChecker)
3
+ defined?(DidYouMean::KeyErrorChecker)
4
4
  end
5
5
  module_function :has_did_you_mean_key_error?
6
6
 
@@ -1,5 +1,5 @@
1
1
  class SmartKv
2
- InitializationError = Class.new(StandardError)
2
+ CheckError = Class.new(StandardError)
3
3
 
4
4
  class KeyError < ::KeyError
5
5
  attr_reader :key, :receiver
data/lib/smart_kv/meat.rb CHANGED
@@ -7,27 +7,37 @@ module SmartKv::Meat
7
7
  include SmartKv::Convert
8
8
 
9
9
  def required(*args)
10
- @required ||= superclass == SmartKv ? Set.new : superclass.required_keys.dup
10
+ init_required
11
11
  @required += args
12
12
  @optional -= @required if @optional
13
13
  @required
14
14
  end
15
15
 
16
16
  def required_keys
17
+ init_required
17
18
  @required.to_a
18
19
  end
19
20
 
21
+ def init_required
22
+ @required ||= superclass == SmartKv ? Set.new : superclass.required.dup
23
+ end
24
+
20
25
  def optional(*args)
21
- @optional ||= superclass == SmartKv ? Set.new : superclass.optional_keys.dup
26
+ init_optional
22
27
  @optional += args
23
28
  @required -= @optional if @required
24
29
  @optional
25
30
  end
26
31
 
27
32
  def optional_keys
33
+ init_optional
28
34
  @optional.to_a
29
35
  end
30
36
 
37
+ def init_optional
38
+ @optional ||= superclass == SmartKv ? Set.new : superclass.optional.dup
39
+ end
40
+
31
41
  def keys
32
42
  Array(@required) + Array(@optional)
33
43
  end
@@ -51,7 +61,7 @@ module SmartKv::Meat
51
61
  unrecognized_keys = hash.keys - required_keys - optional_keys
52
62
  unless unrecognized_keys.empty?
53
63
  key = unrecognized_keys.first
54
- raise SmartKv::KeyError.new("key not found: #{key.inspect}.", key: key, receiver: (keys - hash.keys).map {|k| [k, nil] }.to_h)
64
+ raise SmartKv::KeyError.new("unrecognized key: #{key.inspect} for #{self}.", key: key, receiver: (keys - hash.keys).map {|k| [k, nil] }.to_h)
55
65
  end
56
66
  end
57
67
 
@@ -71,7 +81,7 @@ private
71
81
 
72
82
  def prevent_direct_instantiation
73
83
  if self == SmartKv
74
- raise SmartKv::InitializationError, "only subclass of SmartConfig can be instantiated".freeze
84
+ raise SmartKv::CheckError, "only subclass of SmartKv is meant to be used".freeze
75
85
  end
76
86
  end
77
87
  end
@@ -1,3 +1,3 @@
1
1
  class SmartKv
2
- VERSION = "0.2.6"
2
+ VERSION = "0.2.7"
3
3
  end
data/smart_kv.gemspec CHANGED
@@ -9,8 +9,8 @@ Gem::Specification.new do |spec|
9
9
  spec.authors = ["Adrian Setyadi"]
10
10
  spec.email = ["a.styd@yahoo.com"]
11
11
 
12
- spec.summary = %q{Smart checks for your key value objects.}
13
- spec.description = %q{Best practice of writing options or configurations by strictly allowing and requiring keys.}
12
+ spec.summary = %q{Smart checks for your options or configurations.}
13
+ spec.description = %q{Write options or configurations without worry of typos and the need to remember all the keys.}
14
14
  spec.homepage = "https://github.com/styd/smart_kv"
15
15
  spec.license = "MIT"
16
16
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smart_kv
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.6
4
+ version: 0.2.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - Adrian Setyadi
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-03-08 00:00:00.000000000 Z
11
+ date: 2019-03-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -108,8 +108,8 @@ dependencies:
108
108
  - - ">="
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
- description: Best practice of writing options or configurations by strictly allowing
112
- and requiring keys.
111
+ description: Write options or configurations without worry of typos and the need to
112
+ remember all the keys.
113
113
  email:
114
114
  - a.styd@yahoo.com
115
115
  executables: []
@@ -120,7 +120,6 @@ files:
120
120
  - ".gitignore"
121
121
  - ".rspec"
122
122
  - ".travis.yml"
123
- - CODE_OF_CONDUCT.md
124
123
  - Gemfile
125
124
  - LICENSE.txt
126
125
  - README.md
@@ -158,5 +157,5 @@ rubyforge_project:
158
157
  rubygems_version: 2.7.6
159
158
  signing_key:
160
159
  specification_version: 4
161
- summary: Smart checks for your key value objects.
160
+ summary: Smart checks for your options or configurations.
162
161
  test_files: []
data/CODE_OF_CONDUCT.md DELETED
@@ -1,74 +0,0 @@
1
- # Contributor Covenant Code of Conduct
2
-
3
- ## Our Pledge
4
-
5
- In the interest of fostering an open and welcoming environment, we as
6
- contributors and maintainers pledge to making participation in our project and
7
- our community a harassment-free experience for everyone, regardless of age, body
8
- size, disability, ethnicity, gender identity and expression, level of experience,
9
- nationality, personal appearance, race, religion, or sexual identity and
10
- orientation.
11
-
12
- ## Our Standards
13
-
14
- Examples of behavior that contributes to creating a positive environment
15
- include:
16
-
17
- * Using welcoming and inclusive language
18
- * Being respectful of differing viewpoints and experiences
19
- * Gracefully accepting constructive criticism
20
- * Focusing on what is best for the community
21
- * Showing empathy towards other community members
22
-
23
- Examples of unacceptable behavior by participants include:
24
-
25
- * The use of sexualized language or imagery and unwelcome sexual attention or
26
- advances
27
- * Trolling, insulting/derogatory comments, and personal or political attacks
28
- * Public or private harassment
29
- * Publishing others' private information, such as a physical or electronic
30
- address, without explicit permission
31
- * Other conduct which could reasonably be considered inappropriate in a
32
- professional setting
33
-
34
- ## Our Responsibilities
35
-
36
- Project maintainers are responsible for clarifying the standards of acceptable
37
- behavior and are expected to take appropriate and fair corrective action in
38
- response to any instances of unacceptable behavior.
39
-
40
- Project maintainers have the right and responsibility to remove, edit, or
41
- reject comments, commits, code, wiki edits, issues, and other contributions
42
- that are not aligned to this Code of Conduct, or to ban temporarily or
43
- permanently any contributor for other behaviors that they deem inappropriate,
44
- threatening, offensive, or harmful.
45
-
46
- ## Scope
47
-
48
- This Code of Conduct applies both within project spaces and in public spaces
49
- when an individual is representing the project or its community. Examples of
50
- representing a project or community include using an official project e-mail
51
- address, posting via an official social media account, or acting as an appointed
52
- representative at an online or offline event. Representation of a project may be
53
- further defined and clarified by project maintainers.
54
-
55
- ## Enforcement
56
-
57
- Instances of abusive, harassing, or otherwise unacceptable behavior may be
58
- reported by contacting the project team at a.styd@yahoo.com. All
59
- complaints will be reviewed and investigated and will result in a response that
60
- is deemed necessary and appropriate to the circumstances. The project team is
61
- obligated to maintain confidentiality with regard to the reporter of an incident.
62
- Further details of specific enforcement policies may be posted separately.
63
-
64
- Project maintainers who do not follow or enforce the Code of Conduct in good
65
- faith may face temporary or permanent repercussions as determined by other
66
- members of the project's leadership.
67
-
68
- ## Attribution
69
-
70
- This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
71
- available at [http://contributor-covenant.org/version/1/4][version]
72
-
73
- [homepage]: http://contributor-covenant.org
74
- [version]: http://contributor-covenant.org/version/1/4/