Socket
Book a DemoInstallSign in
Socket

lab42_open_map

Package Overview
Dependencies
Maintainers
1
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

lab42_open_map

0.1.2
bundlerRubygems
Version published
Maintainers
1
Created
Source

Gem Version

Lab42::OpenMap

OpenMap = OpenStruct with a rich Map API

N.B. All these code examples are verified with the speculate_about gem

Context Quick Starting Guide

Given an OpenMap

    require "lab42/open_map/include" # aliases Lab42::OpenMap as OpenMap
    let(:pet) { OpenMap.new }

Then we can see that it can be empty

    expect( pet ).to be_empty

And that we can add fields like to a hash

    pet[:name] = "Furfur"
    expect( pet[:name] ).to eq("Furfur")

However we are not a hash.

Example: Only Symbol Keys please

    expect{ pet["name"] = nil }.to raise_error(ArgumentError, %{"name" is not a symbol})

And that holds for construction too

    expect{ OpenMap.new("verbose" => false) }
      .to raise_error(ArgumentError, %{the following keys are not symbols: ["verbose"]})

But many Hash methods are applicable to OpenMap

Given that

    let (:dog) {OpenMap.new(name: "Rantanplan", breed: "You are kidding?")}

Then we can access it like a hash

    expect( dog.keys ).to eq(%i[name breed])
    expect( dog.values ).to eq(["Rantanplan", "You are kidding?"])
    expect( dog.size ).to eq(2)
    expect( dog.map.to_a ).to eq([[:name, "Rantanplan"], [:breed, "You are kidding?"]])

And we can use slice and get a nice counterpart without

    expect( dog.slice(:name) ).to eq(name: "Rantanplan")
    expect( dog.slice(:name, :breed) ).to eq(name: "Rantanplan", breed: "You are kidding?")
    expect( dog.without(:breed) ).to eq(name: "Rantanplan")
    expect( dog.without(:name, :breed) ).to eq({})

Example: each_pair

  expect( dog.each_pair.to_a ).to eq([[:name, "Rantanplan"],[ :breed, "You are kidding?"]])
    

each_pair is important for the following to work Given we have OpenStruct

    require "ostruct"

Then we can create one from an OpenMap

  struct_dog = OpenStruct.new(dog)
  expect( struct_dog.name ).to eq("Rantanplan")
    

And last, but certainly not least: Named Access

    expect(dog.name).to eq("Rantanplan") 
    dog.breed = "still unknown"
    expect( dog.values ).to eq(["Rantanplan", "still unknown"])

Context All About Named Access

Given the same dog again

    let (:dog) {OpenMap.new(name: "Rantanplan", breed: "You are kidding?")}

Then we cannot access a nonexistant field by name

    expect{ dog.age }.to raise_error(NoMethodError, %r{\Aundefined method `age' for})

And we cannot create a new one either

    expect{ dog.age = 10 }.to raise_error(NoMethodError, %r{\Aundefined method `age' for})

But we still can create new fields with []= or update

    dog.update( age: 10 ) 
    expect( dog.age ).to eq(10)

And of course the update method preserves our symbol keys only property

    expect{ dog.update("verbose" => true)  } 
      .to raise_error(ArgumentError, %{the following keys are not symbols: ["verbose"]})

Context Methods that create new OpenMap objects

Given a cat now, cannot risk losing half of the pet loving community ;)

  let(:garfield) {OpenMap.new(name: "Garfield", yob: 1976, creator: "Jim Davis")} # Yes under a differnt name, but still
  let!(:nermal) { garfield.merge(name: "Nermal", yob: 1979)}

Then exactly the following can be certified

    expect( nermal ).to be_kind_of(OpenMap)
    expect( garfield.values ).to eq(["Garfield", 1976, "Jim Davis"])
    expect( nermal.values ).to eq(["Nermal", 1979, "Jim Davis"])

We also have a counterpart to without, called sans And with sans we get this

    partial_garfield = garfield.sans(:yob, :creator) 
    expect( partial_garfield.to_h ).to eq(name: "Garfield")
    expect( garfield.values ).to eq(["Garfield", 1976, "Jim Davis"])

Context Hash like Protocol

We have already seen that [], slice, size and friends act like on hashes, let us document the other Hashlike methods here

Given a nice little OpenMap

    let(:my_map) { OpenMap.new(street: "Champs Elysée", city: "Paris", country: "France") }

fetch

Then we can fetch existing values

    expect( my_map.fetch(:city) ).to eq("Paris")

And we have to be a little bit more careful with non existing values

    expect( my_map.fetch(:zip, 75008) ).to eq(75008)
    expect( my_map.fetch(:number) { 42 } ).to eq(42)
    expect{ my_map.fetch(:continent) }.to raise_error(KeyError, "key not found: :continent" )

Pattern Matching with deconstruct_keys

And we can pattern match

    my_map in {city: city, street: street}
    expect( [street, city] ).to eq(["Champs Elysée", "Paris"])
    expect{ my_map in {city: "Bordeaux"} }.to raise_error(NoMatchingPatternError)

entries

And with not much to say about

    expect( my_map.entries ).to eq([[:street, "Champs Elysée"], [:city, "Paris"], [:country, "France"]])

LICENSE

Copyright 2020 Robert Dober robert.dober@gmail.com

Apache-2.0 c.f LICENSE

FAQs

Package last updated on 01 Dec 2020

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.