Class: Xf::Scope

Inherits:
Object
  • Object
show all
Defined in:
lib/xf/scope.rb

Overview

A play on Lenses in Ruby, though not quite as powerful they can be useful for getting and setting deep values on collections.

Author:

  • baweaver

Since:

  • 0.0.2

Instance Method Summary collapse

Constructor Details

#initialize(paths) ⇒ Xf::Scope

Creates a Scope

Parameters:

  • paths (Array[Any])

    Paths to follow to reach the desired value

Since:

  • 0.0.2



13
14
15
# File 'lib/xf/scope.rb', line 13

def initialize(paths)
  @paths = paths
end

Instance Method Details

#get(&fn) ⇒ type

Gets a value from a Hash

Returns:

  • (type)
    description

Since:

  • 0.0.2



20
21
22
# File 'lib/xf/scope.rb', line 20

def get(&fn)
  Proc.new { |hash| get_value(hash, &fn) }
end

#get_value(hash, &fn) ⇒ Any

Direct value getter, though it may be wiser to use Hash#dig here instead if you’re concerned about speed.

If the object does not respond to dig, Xf will attempt to use an array bracket accessor dive instead for compatability reasons.

Parameters:

  • hash (Hash)

    Hash to get value from

Returns:

  • (Any)

Since:

  • 0.0.2



60
61
62
63
64
65
66
67
68
69
70
# File 'lib/xf/scope.rb', line 60

def get_value(hash, &fn)
  value = if hash.respond_to?(:dig)
    hash.dig(*@paths)
  else
    new_hash = hash
    @paths.each { |s| new_hash = new_hash[s] }
    new_hash
  end

  block_given? ? fn[value] : value
end

#set(value = nil, &fn) ⇒ Proc[Hash] -

Sets a value in a Hash

Parameters:

  • value (defaults to: nil)

    nil [Any]

    Value to set at the target

  • &fn (Proc)

    Block to yield target value to. Returned value will be set as the new value at the target.

Returns:

  • (Proc[Hash] -)

    Hash] New Hash with transformation applied

Since:

  • 0.0.2



35
36
37
# File 'lib/xf/scope.rb', line 35

def set(value = nil, &fn)
  Proc.new { |hash| set_value(hash, value, &fn) }
end

#set!(value = nil, &fn) ⇒ Object

Note:

This method does the same thing as ‘#set`, except that it mutates the target value instead of creating a clone first.

Mutates a value in a Hash

See Also:

Since:

  • 0.0.2



47
48
49
# File 'lib/xf/scope.rb', line 47

def set!(value = nil, &fn)
  Proc.new { |hash| set_value!(hash, value, &fn) }
end

#set_value(hash, value = nil, &fn) ⇒ Hash

Sets a value at the bottom of a path without mutating the original.

Parameters:

  • hash (Hash)

    Hash to set value on

  • value (defaults to: nil)

    nil [Any]

    Value to set

  • &fn (Proc)

    If present, current value is yielded to it and the return value is the new set value

Returns:

  • (Hash)

    Clone of the original with the value set

Since:

  • 0.0.2



86
87
88
# File 'lib/xf/scope.rb', line 86

def set_value(hash, value = nil, &fn)
  set_value!(deep_clone(hash), value, &fn)
end

#set_value!(hash, value = nil, &fn) ⇒ Object

Mutating form of ‘#set_value`

See Also:

Since:

  • 0.0.2



93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
# File 'lib/xf/scope.rb', line 93

def set_value!(hash, value = nil, &fn)
  lead_in    = @paths[0..-2]
  target_key = @paths[-1]

  new_hash = hash
  lead_in.each { |s| new_hash = new_hash[s] }

  new_value = block_given? ?
    yield(new_hash[target_key]) :
    value

  new_hash[target_key] = new_value

  hash
end