smart_kv 0.2.6 → 0.2.7

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
  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/