key_value_coding 0.1.0 → 0.2.0
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 +4 -4
- data/CHANGELOG.md +3 -1
- data/README.md +12 -12
- data/lib/key_value_coding/hash.rb +0 -2
- data/lib/key_value_coding/object.rb +16 -7
- data/lib/key_value_coding/version.rb +1 -1
- data/lib/key_value_coding.rb +1 -0
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 24584f6b8d22bd6093300ce6b4d69ee97265d21127c4bc939e696979cb951d4f
|
|
4
|
+
data.tar.gz: 0bfdff95bc24f469ea8805d87cd147ce1f6c9a6f0761630cd077daf655bab786
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: c5fa4a4c31d0fe521a08baca2abd5ad188e5112b4db3980e6ad3d078bc1797c5e639d7fe0d57804d9017ba9f787e74349de0a4d7aae5f065f718ccf503b405b5
|
|
7
|
+
data.tar.gz: a3272ffe2dea7c57108c78002bcf84bc3cb06114dc6e2f69b19f7c6332f0ca627d76a492b436057f1dd6bd7d794b1cac55fd53890e47074079f9a638d84f2f94
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
|
@@ -37,37 +37,35 @@ object.value_for_key(:company) # Works with both!
|
|
|
37
37
|
```ruby
|
|
38
38
|
company.address[:street] # Meh
|
|
39
39
|
data.dig(:company, :address).street # Ugh
|
|
40
|
-
data.value_for_key_path(
|
|
40
|
+
data.value_for_key_path(:company, :address :street) # Also nice!
|
|
41
41
|
```
|
|
42
42
|
|
|
43
43
|
### Operating on multiple collection items at once
|
|
44
44
|
|
|
45
45
|
```ruby
|
|
46
46
|
company.managers.map { it[:name] }.map(&:upcase) # Meh
|
|
47
|
-
company.value_for_key_path(
|
|
47
|
+
company.value_for_key_path(:name, :upcase) # Nice!
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
### Set a value on a mixed hierarchy of PORO and hashes
|
|
51
51
|
|
|
52
52
|
```ruby
|
|
53
|
-
record.company
|
|
54
|
-
record.set_value("Ash Tree Lane 12" for_key_path:
|
|
53
|
+
record.company.address[:street] = "Ash Tree Lane 12" # Meh
|
|
54
|
+
record.set_value("Ash Tree Lane 12" for_key_path: [:company, :address, :street]) # Nice!
|
|
55
55
|
```
|
|
56
56
|
|
|
57
57
|
## Installation
|
|
58
58
|
|
|
59
|
-
TODO: Replace `UPDATE_WITH_YOUR_GEM_NAME_IMMEDIATELY_AFTER_RELEASE_TO_RUBYGEMS_ORG` with your gem name right after releasing it to RubyGems.org. Please do not do it earlier due to security reasons. Alternatively, replace this section with instructions to install your gem from git if you don't plan to release to RubyGems.org.
|
|
60
|
-
|
|
61
59
|
Install the gem and add to the application's Gemfile by executing:
|
|
62
60
|
|
|
63
61
|
```bash
|
|
64
|
-
bundle add
|
|
62
|
+
bundle add key_value_coding
|
|
65
63
|
```
|
|
66
64
|
|
|
67
65
|
If bundler is not being used to manage dependencies, install the gem by executing:
|
|
68
66
|
|
|
69
67
|
```bash
|
|
70
|
-
gem install
|
|
68
|
+
gem install key_value_coding
|
|
71
69
|
```
|
|
72
70
|
|
|
73
71
|
## Usage
|
|
@@ -111,12 +109,13 @@ If one of the keys doesn't exist, `value_for_undefined_key` is called (which usu
|
|
|
111
109
|
### `Object#value_for_key_path`
|
|
112
110
|
|
|
113
111
|
```ruby
|
|
114
|
-
manager.value_for_key_path(
|
|
112
|
+
manager.value_for_key_path(:name, :length) # 10
|
|
113
|
+
manager.value_for_key_path("name.length") # Also works with dot-separated components
|
|
115
114
|
```
|
|
116
115
|
|
|
117
116
|
Get the value of a chain of keys (like object traversal, but works also on hashes).
|
|
118
117
|
|
|
119
|
-
For each dot-separated component of the key-path, `value_for_key` is used to retrieve the value.
|
|
118
|
+
For each symbol or dot-separated component of the key-path, `value_for_key` is used to retrieve the value.
|
|
120
119
|
|
|
121
120
|
If one of the keys doesn't exist, `value_for_undefined_key` is called (which usually results in a `KeyValueCoding::UndefinedKey` exception).
|
|
122
121
|
|
|
@@ -133,12 +132,13 @@ If the key doesn't exist, `value_for_undefined_key` is called (which usually res
|
|
|
133
132
|
### `Object#set_value(value, for_key_path:)`
|
|
134
133
|
|
|
135
134
|
```ruby
|
|
136
|
-
record.set_value("Richard Whitman", for_key_path:
|
|
135
|
+
record.set_value("Richard Whitman", for_key_path: [:manager, :name])
|
|
136
|
+
record.set_value("Richard Whitman", for_key_path: "manager.name") # Also works with dot-separated components
|
|
137
137
|
```
|
|
138
138
|
|
|
139
139
|
Set the value of a key-path (like object assignement, but also work on hashes).
|
|
140
140
|
|
|
141
|
-
For each dot-separated component of the key-path, `value_for_key` is invoked to retrieve the value. On the last component, `set_value(value, for_key:)` is invoked to set the value.
|
|
141
|
+
For each symbol or dot-separated component of the key-path, `value_for_key` is invoked to retrieve the value. On the last component, `set_value(value, for_key:)` is invoked to set the value.
|
|
142
142
|
|
|
143
143
|
If one of the keys doesn't exist, `value_for_undefined_key` is called (which usually results in a `KeyValueCoding::UndefinedKey` exception).
|
|
144
144
|
|
|
@@ -17,17 +17,15 @@ class Object
|
|
|
17
17
|
keys.map { |k| [k, value_for_key(k)] }.to_h
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
def value_for_key_path(key_path)
|
|
21
|
-
key_path
|
|
22
|
-
.split(".")
|
|
23
|
-
.reduce(self) { |object, key| object.value_for_key(key) }
|
|
20
|
+
def value_for_key_path(*key_path, **nil)
|
|
21
|
+
normalized_key_path(*key_path).reduce(self) { |object, key| object.value_for_key(key) }
|
|
24
22
|
end
|
|
25
23
|
|
|
26
24
|
def set_value(value, for_key: nil, for_key_path: nil)
|
|
27
25
|
if for_key
|
|
28
26
|
set_value_for_key(value, for_key)
|
|
29
27
|
elsif for_key_path
|
|
30
|
-
set_value_for_key_path(value, for_key_path)
|
|
28
|
+
set_value_for_key_path(value, *for_key_path)
|
|
31
29
|
else
|
|
32
30
|
raise ArgumentError("Either `for_key` or `for_key_path` must be provided")
|
|
33
31
|
end
|
|
@@ -43,8 +41,8 @@ class Object
|
|
|
43
41
|
end
|
|
44
42
|
end
|
|
45
43
|
|
|
46
|
-
def set_value_for_key_path(value, key_path)
|
|
47
|
-
*path, key = key_path
|
|
44
|
+
def set_value_for_key_path(value, *key_path)
|
|
45
|
+
*path, key = normalized_key_path(*key_path)
|
|
48
46
|
target = value_for_key_path(path.join('.'))
|
|
49
47
|
target.set_value(value, for_key: key)
|
|
50
48
|
end
|
|
@@ -56,4 +54,15 @@ class Object
|
|
|
56
54
|
def set_value_for_undefined_key(value, key)
|
|
57
55
|
raise KeyValueCoding::UndefinedKey.new("Undefined key '#{key}' for object #{self}")
|
|
58
56
|
end
|
|
57
|
+
|
|
58
|
+
private
|
|
59
|
+
|
|
60
|
+
def normalized_key_path(*key_path)
|
|
61
|
+
case key_path
|
|
62
|
+
in [String] then key_path.first.split(".")
|
|
63
|
+
in [Symbol] then key_path
|
|
64
|
+
in [Symbol, *] if key_path.all? { |k| k.is_a?(Symbol)} then key_path
|
|
65
|
+
else raise KeyValueCoding::InvalidPath.new("Expected a string or an array of symbols, but got '#{key_path}'")
|
|
66
|
+
end
|
|
67
|
+
end
|
|
59
68
|
end
|
data/lib/key_value_coding.rb
CHANGED