Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: rubinius/rubinius
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 135145ad95e3
Choose a base ref
...
head repository: rubinius/rubinius
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 97da6c2ab173
Choose a head ref
  • 3 commits
  • 6 files changed
  • 2 contributors

Commits on Jan 10, 2016

  1. Copy the full SHA
    75b5565 View commit details
  2. Copy the full SHA
    8d71754 View commit details

Commits on Jan 11, 2016

  1. Merge pull request #3562 from ahmadsherif/feature/dig-method

    Implement #dig method
    brixen committed Jan 11, 2016
    Copy the full SHA
    97da6c2 View commit details
Showing with 144 additions and 0 deletions.
  1. +9 −0 kernel/common/array.rb
  2. +9 −0 kernel/common/hash.rb
  3. +13 −0 kernel/common/struct.rb
  4. +38 −0 spec/ruby/core/array/dig_spec.rb
  5. +38 −0 spec/ruby/core/hash/dig_spec.rb
  6. +37 −0 spec/ruby/core/struct/dig_spec.rb
9 changes: 9 additions & 0 deletions kernel/common/array.rb
Original file line number Diff line number Diff line change
@@ -583,6 +583,15 @@ def delete_if
self
end

def dig(*sequence)
item = self[sequence.shift]
return item if sequence.empty? || item.nil?

raise TypeError, "#{item.class} does not have #dig method" unless item.respond_to?(:dig)

item.dig(*sequence)
end

def each_index
return to_enum(:each_index) { size } unless block_given?

9 changes: 9 additions & 0 deletions kernel/common/hash.rb
Original file line number Diff line number Diff line change
@@ -322,6 +322,15 @@ def delete(key)
return yield(key) if block_given?
end

def dig(*sequence)
item = self[sequence.shift]
return item if sequence.empty? || item.nil?

raise TypeError, "#{item.class} does not have #dig method" unless item.respond_to?(:dig)

item.dig(*sequence)
end

def each_item
return unless @state

13 changes: 13 additions & 0 deletions kernel/common/struct.rb
Original file line number Diff line number Diff line change
@@ -181,6 +181,19 @@ def []=(var, obj)
return instance_variable_set(:"@#{var}", obj)
end

def dig(*sequence)
item = begin
self[sequence.shift]
rescue NameError
nil
end
return item if sequence.empty? || item.nil?

raise TypeError, "#{item.class} does not have #dig method" unless item.respond_to?(:dig)

item.dig(*sequence)
end

def eql?(other)
return true if equal? other
return false if self.class != other.class
38 changes: 38 additions & 0 deletions spec/ruby/core/array/dig_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Array#dig" do
it "returns the nested value specified by the sequence of indexes" do
a = [[1, [2, 3]]]

a.dig(0, 1, 1).should == 3
end

it "returns the nested value specified if the sequence includes a key" do
a = [42, new_hash(foo: :bar)]

a.dig(1, :foo).should == :bar
end

it "raises a TypeError if any intermediate step does not respond to #dig" do
a = [1, 2]

lambda { a.dig(0, 1) }.should raise_error(TypeError)
end

it "returns nil if any intermediate step is nil" do
a = [[1, [2, 3]]]

a.dig(1, 2, 3).should == nil
end

it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
o = Object.new
a = [1, [2, o]]

def o.dig(*args)
{dug: args}
end

a.dig(1, 1, :bar, :baz).should == {dug: [:bar, :baz]}
end
end
38 changes: 38 additions & 0 deletions spec/ruby/core/hash/dig_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Hash#dig" do
it "returns the nested value specified by the sequence of keys" do
h = new_hash(foo: new_hash(bar: new_hash(baz: 1)))

h.dig(:foo, :bar, :baz).should == 1
end

it "returns the nested value specified if the sequence includes an index" do
h = new_hash(foo: [1, 2, 3])

h.dig(:foo, 2).should == 3
end

it "returns nil if any intermediate step is nil" do
h = new_hash(foo: new_hash(bar: new_hash(baz: 1)))

h.dig(:foo, :zot, :xyz).should == nil
end

it "raises a TypeError if any intermediate step does not respond to #dig" do
h = new_hash(foo: 1)

lambda { h.dig(:foo, 3) }.should raise_error(TypeError)
end

it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
o = Object.new
h = new_hash(foo: o)

def o.dig(*args)
{dug: args}
end

h.dig(:foo, :bar, :baz).should == {dug: [:bar, :baz]}
end
end
37 changes: 37 additions & 0 deletions spec/ruby/core/struct/dig_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
require File.expand_path('../../../spec_helper', __FILE__)

describe "Struct#dig" do
before(:each) do
@klass = Struct.new(:a)
@instance = @klass.new(@klass.new(b: [1, 2, 3]))
end

it "returns the nested value specified by the sequence of keys" do
@instance.dig(:a, :a).should == {b: [1, 2, 3]}
end

it "returns the nested value specified if the sequence includes an index" do
@instance.dig(:a, :a, :b, 0).should == 1
end

it "returns nil if any intermediate step is nil" do
@instance.dig(:b, 0).should == nil
end

it "raises a TypeError if any intermediate step does not respond to #dig" do
instance = @klass.new(1)

lambda { instance.dig(:a, 3) }.should raise_error(TypeError)
end

it "calls #dig on any intermediate step with the rest of the sequence as arguments" do
obj = Object.new
instance = @klass.new(obj)

def obj.dig(*args)
{dug: args}
end

instance.dig(:a, :bar, :baz).should == {dug: [:bar, :baz]}
end
end