11# 🐍 SnakyHash
22
3- [ ![ Version] [ 👽versioni ]] [ 👽version ] [ ![ License: MIT] [ 📄license-img ]] [ 📄license-ref ] [ ![ Downloads Rank] [ 👽dl-ranki ]] [ 👽dl-rank ] [ ![ Open Source Helpers] [ 👽oss-helpi ]] [ 👽oss-help ] [ ![ Depfu] [ 🔑depfui♻️ ]] [ 🔑depfu ] [ ![ Coveralls Test Coverage] [ 🔑coveralls-img ]] [ 🔑coveralls ] [ ![ QLTY Test Coverage] [ 🔑qlty-covi♻️ ]] [ 🔑qlty-cov ] [ ![ CI Heads] [ 🚎3-hd-wfi ]] [ 🚎3-hd-wf ] [ ![ CI Runtime Dependencies @ HEAD] [ 🚎12-crh-wfi ]] [ 🚎12-crh-wf ] [ ![ CI Current] [ 🚎11-c-wfi ]] [ 🚎11-c-wf ] [ ![ CI Truffle Ruby] [ 🚎9-t-wfi ]] [ 🚎9-t-wf ] [ ![ CI JRuby] [ 🚎10-j-wfi ]] [ 🚎10-j-wf ] [ ![ CI Supported] [ 🚎6-s-wfi ]] [ 🚎6-s-wf ] [ ![ CI Legacy] [ 🚎4-lg-wfi ]] [ 🚎4-lg-wf ] [ ![ CI Unsupported] [ 🚎7-us-wfi ]] [ 🚎7-us-wf ] [ ![ CI Ancient] [ 🚎1-an-wfi ]] [ 🚎1-an-wf ] [ ![ CI Test Coverage] [ 🚎2-cov-wfi ]] [ 🚎2-cov-wf ] [ ![ CI Style] [ 🚎5-st-wfi ]] [ 🚎5-st-wf ] [ ![ CodeQL] [ 🖐codeQL-img ]] [ 🖐codeQL ]
3+ [ ![ Version] [ 👽versioni ]] [ 👽version ] [ ![ License: MIT] [ 📄license-img ]] [ 📄license-ref ] [ ![ Downloads Rank] [ 👽dl-ranki ]] [ 👽dl-rank ] [ ![ Open Source Helpers] [ 👽oss-helpi ]] [ 👽oss-help ] [ ![ Depfu] [ 🔑depfui♻️ ]] [ 🔑depfu ] [ ![ Coveralls Test Coverage] [ 🔑coveralls-img ]] [ 🔑coveralls ] [ ![ QLTY Test Coverage] [ 🔑qlty-covi♻️ ]] [ 🔑qlty-cov ] [ ![ QLTY Maintainability ] [ 🔑qlty-mnti♻️ ]] [ 🔑qlty-mnt ] [ ![ CI Heads] [ 🚎3-hd-wfi ]] [ 🚎3-hd-wf ] [ ![ CI Runtime Dependencies @ HEAD] [ 🚎12-crh-wfi ]] [ 🚎12-crh-wf ] [ ![ CI Current] [ 🚎11-c-wfi ]] [ 🚎11-c-wf ] [ ![ CI Truffle Ruby] [ 🚎9-t-wfi ]] [ 🚎9-t-wf ] [ ![ CI JRuby] [ 🚎10-j-wfi ]] [ 🚎10-j-wf ] [ ![ CI Supported] [ 🚎6-s-wfi ]] [ 🚎6-s-wf ] [ ![ CI Legacy] [ 🚎4-lg-wfi ]] [ 🚎4-lg-wf ] [ ![ CI Unsupported] [ 🚎7-us-wfi ]] [ 🚎7-us-wf ] [ ![ CI Ancient] [ 🚎1-an-wfi ]] [ 🚎1-an-wf ] [ ![ CI Test Coverage] [ 🚎2-cov-wfi ]] [ 🚎2-cov-wf ] [ ![ CI Style] [ 🚎5-st-wfi ]] [ 🚎5-st-wf ] [ ![ CodeQL] [ 🖐codeQL-img ]] [ 🖐codeQL ]
44
55---
66
@@ -14,7 +14,7 @@ and provide a nice psuedo-object interface.
1414It can be thought of as a mashup of:
1515
1616* ` Rash ` (specifically the [ ` rash_alt ` ] ( https://github.com/shishi/rash_alt ) flavor), which is a special ` Mash ` , made popular by the ` hashie ` gem, and
17- * ` serialized_hashie ` [ gem by krystal] ( https://github.com/krystal/serialized-hashie )
17+ * ` serialized_hashie ` [ gem by krystal] ( https://github.com/krystal/serialized-hashie ) , rewritten, with some behavior changes
1818
1919Classes that ` include SnakyHash::Snake.new ` should inherit from ` Hashie::Mash ` .
2020
@@ -46,6 +46,17 @@ SnakyHash::StringKeyed.class_eval do
4646end
4747```
4848
49+ or you can create a custom class
50+
51+ ``` ruby
52+ class MyHash < Hashie ::Mash
53+ include SnakyHash ::Snake .new (key_type: :string , serializer: true )
54+ # Which is the same as:
55+ # include SnakyHash::Snake.new(key_type: :string)
56+ # extend SnakyHash::Serializer
57+ end
58+ ```
59+
4960You can then add serialization extensions as needed. See [ serialization] ( #serialization ) and [ extensions] ( #extensions ) for more.
5061
5162| Federated [ DVCS] [ 💎d-in-dvcs ] Repository | Status | Issues | PRs | Wiki | CI | Discussions |
@@ -212,71 +223,95 @@ This is also not a bug, though if you need different behavior, there is a soluti
212223
213224You can write your own arbitrary extensions:
214225
215- * "Hash Load" extensions operate on the hash, and nested hashes
226+ * "Hash Load" extensions operate on the hash and nested hashes
216227 * use ` ::load_hash_extensions.add(:extension_name) { |hash| } `
217- * "Load" extensions operate on the values, and nested hash's values, if any
218- * use ` ::load_extensions.add(:extension_name) { |value| } `
219- * "Dump" extensions operate on the values, and nested hash's values, if any
220- * use ` ::dump_extensions.add(:extension_name) { |value| } `
228+ * since v2.0.2, bugs fixed in v2.0.3
229+ * "Value Load" extensions operate on the values, and nested hashes' values, if any
230+ * use ` ::load_value_extensions.add(:extension_name) { |value| } `
231+ * since v2.0.2, bugs fixed in v2.0.3
232+ * "Hash Dump" extensions operate on the hash and nested hashes
233+ * use ` ::dump_hash_extensions.add(:extension_name) { |value| } `
234+ * since v2.0.3
235+ * "Value Dump" extensions operate on the values, and nested hashes' values, if any
236+ * use ` ::dump_value_extensions.add(:extension_name) { |value| } `
237+ * since v2.0.2, bugs fixed in v2.0.3
221238
222239#### Example
223240
224- Let's say I want all integer-like keys, except 0, to be integer keys,
225- while 0 converts to, and stays, a string forever.
241+ Let's say I want to really smash up my hash and make it more food-like.
226242
227243``` ruby
228244class MyExtSnakedHash < Hashie ::Mash
229245 include SnakyHash ::Snake .new (
230246 key_type: :symbol , # default :string
231- serializer: true , # default: false
247+ serializer: true , # default: false
232248 )
233249end
234250
235- MyExtSnakedHash .load_hash_extensions.add(:non_zero_keys_to_int ) do |value |
236- if value.is_a?(Hash )
237- value.transform_keys do |key |
238- key_int = key.to_s.to_i
239- if key_int > 0
240- key_int
241- else
242- key
243- end
244- end
245- else
246- value
251+ # We could swap all values with indexed apples (obliteraating nested data!)
252+ MyExtSnakedHash .dump_hash_extensions.add(:to_apple ) do |value |
253+ num = 0
254+ value.transform_values do |_key |
255+ key = " apple-#{ num } "
256+ num += 1
257+ key
247258 end
248259end
249260
250- snake = MyExtSnakedHash .new (1 => " a" , 0 => 4 , " VeryFineHat" => {3 => " v" , 5 => 7 , :very_fine_hat => " feathers" }) # => {1 => "a", 0 => 4, very_fine_hat: {3 => "v", 5 => 7, very_fine_hat: "feathers"}}
251- dump = MyExtSnakedHash .dump(snake) # => "{\"1\":\"a\",\"0\":4,\"very_fine_hat\":{\"3\":\"v\",\"5\":7,\"very_fine_hat\":\"feathers\"}}"
252- hydrated = MyExtSnakedHash .load (dump) # => {1 => "a", "0": 4, very_fine_hat: {3 => "v", 5 => 7, very_fine_hat: "feathers"}}
253- hydrated.class # => MyExtSnakedHash
254- hydrated[" 1" ] # => nil
255- hydrated[1 ] # => "a"
256- hydrated[" 0" ] # => 4
257- hydrated[0 ] # => nil
258- hydrated.very_fine_hat # => {3 => "v", 5 => 7, very_fine_hat: "feathers"}
259- hydrated.very_fine_hat.very_fine_hat # => "feathers"
260- hydrated.very_fine_hat[:very_fine_hat ] # => 'feathers'
261- hydrated.very_fine_hat[" very_fine_hat" ] # => 'feathers'
261+ # And then when loading the dump we could convert the yum to pear
262+ MyExtSnakedHash .load_hash_extensions.add(:apple_to_pear ) do |value |
263+ value.transform_keys do |key |
264+ key.to_s.sub (" yum" , " pear" )
265+ end
266+ end
267+
268+ # We could swap all index numbers "beet-<number>"
269+ MyExtSnakedHash .dump_value_extensions.add(:to_beet ) do |value |
270+ value.to_s.sub (/(\d +) / ) { |match | " beet-#{ match[0 ] } " }
271+ end
272+
273+ # And then when loading the dump we could convert beet to corn
274+ MyExtSnakedHash .load_value_extensions.add(:beet_to_corn ) do |value |
275+ value.to_s.sub (" beet" , " corn" )
276+ end
277+
278+ snake = MyExtSnakedHash .new ({" YumBread" => " b" , " YumCake" => {" b" => " b" }, " YumBoba" => [1 , 2 , 3 ]})
279+ snake # => {yum_bread: "b", yum_cake: {b: "b"}, yum_boba: [1, 2, 3]}
280+ snake.yum_bread # => "b"
281+ snake.yum_cake # => {b: "b"}
282+ snake.yum_boba # => [1, 2, 3]
283+ dump = snake.dump
284+ dump # => "{\"yum_bread\":\"apple-beet-0\",\"yum_cake\":\"apple-beet-1\",\"yum_boba\":\"apple-beet-2\"}"
285+ hydrated = MyExtSnakedHash .load (dump)
286+ hydrated # => {pear_bread: "apple-corn-0", pear_cake: "apple-corn-1", pear_boba: "apple-corn-2"}
262287```
263288
264289See the specs for more examples.
265290
266- ### Stranger Things
291+ ### Bad Ideas
267292
268293I don't recommend using these features... but they exist (for now).
294+
295+ <details >
296+ <summary >Show me what I should *not* do!</summary >
297+
269298You can still access the original un-snaked camel keys.
270299And through them you can even use un-snaked camel methods.
271300But don't.
272301
273302``` ruby
303+ snake = SnakyHash ::StringKeyed [" VeryFineHat" => " Feathers" ]
274304snake.key?(" VeryFineHat" ) # => true
275305snake[" VeryFineHat" ] # => 'Feathers'
276306snake.VeryFineHat # => 'Feathers', PLEASE don't do this!!!
277307snake[" VeryFineHat" ] = " pop" # Please don't do this... you'll get a warning, and it works (for now), but no guarantees.
278308# WARN -- : You are setting a key that conflicts with a built-in method MySnakedHash#VeryFineHat defined in MySnakedHash. This can cause unexpected behavior when accessing the key as a property. You can still access the key via the #[] method.
279309# => "pop"
310+ ```
311+
312+ Since you are reading this, here's what to do instead.
313+
314+ ``` ruby
280315snake.very_fine_hat = " pop" # => 'pop', do this instead!!!
281316snake.very_fine_hat # => 'pop'
282317snake[:very_fine_hat ] = " moose" # => 'moose', or do this instead!!!
@@ -285,6 +320,8 @@ snake["very_fine_hat"] = "cheese" # => 'cheese', or do this instead!!!
285320snake.very_fine_hat # => 'cheese'
286321```
287322
323+ </details >
324+
288325### 🚀 Release Instructions
289326
290327See [ CONTRIBUTING.md] [ 🤝contributing ] .
@@ -553,7 +590,7 @@ or one of the others at the head of this README.
553590[ 📌gitmoji ] :https://gitmoji.dev
554591[ 📌gitmoji-img ] :https://img.shields.io/badge/gitmoji_commits-%20😜%20😍-34495e.svg?style=flat-square
555592[ 🧮kloc ] : https://www.youtube.com/watch?v=dQw4w9WgXcQ
556- [ 🧮kloc-img ] : https://img.shields.io/badge/KLOC-0.119 -FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
593+ [ 🧮kloc-img ] : https://img.shields.io/badge/KLOC-0.132 -FFDD67.svg?style=for-the-badge&logo=YouTube&logoColor=blue
557594[ 🔐security ] : SECURITY.md
558595[ 🔐security-img ] : https://img.shields.io/badge/security-policy-259D6C.svg?style=flat
559596[ 📄copyright-notice-explainer ] : https://opensource.stackexchange.com/questions/5778/why-do-licenses-such-as-the-mit-license-specify-a-single-year
0 commit comments