Feature #12719 ยป struct_merge.patch
| ChangeLog | ||
|---|---|---|
|
Fri Sep 2 17:27:31 2016 Matthew Mongeau <halogenandtoast@gmail.com>
|
||
|
* struct.c (rb_struct_update): Add Struct#merge and Struct#merge!
|
||
|
for updating structs
|
||
|
Fri Sep 2 16:06:59 2016 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||
|
* internal.h (MEMO_V1_SET, MEMO_V2_SET): fix typos. use the macro
|
||
| struct.c | ||
|---|---|---|
|
return RSTRUCT_GET(s, i);
|
||
|
}
|
||
|
static int
|
||
|
value_update(VALUE key, VALUE value, VALUE s)
|
||
|
{
|
||
|
rb_struct_aset(s, key, value);
|
||
|
return ST_CONTINUE;
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* struct.merge!(hash) -> struct
|
||
|
*
|
||
|
* Updates the values of the struct using the keys and values of the hash
|
||
|
*
|
||
|
* Point = Struct.new(:x, :y)
|
||
|
* hash = { "x" => 5 }
|
||
|
* point = Point.new(1, 2)
|
||
|
* point.merge!(hash)
|
||
|
*
|
||
|
* point.x #=> 5
|
||
|
*/
|
||
|
VALUE
|
||
|
rb_struct_update(VALUE self, VALUE hash)
|
||
|
{
|
||
|
VALUE converted_hash = rb_convert_type(hash, T_HASH, "Hash", "to_hash");
|
||
|
rb_hash_foreach(converted_hash, value_update, self);
|
||
|
return self;
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* struct.merge(hash) -> new_struct
|
||
|
*
|
||
|
* Returns a new struct with updated values using the keys and values of
|
||
|
* the hash
|
||
|
*
|
||
|
* Point = Struct.new(:x, :y)
|
||
|
* p = Point.new(1, 2)
|
||
|
* p2 = p.merge(y: 20)
|
||
|
*
|
||
|
* p.y #=> 2
|
||
|
* p2.y #=> 20
|
||
|
*/
|
||
|
VALUE
|
||
|
rb_struct_merge(VALUE self, VALUE hash)
|
||
|
{
|
||
|
VALUE dup = rb_obj_dup(self);
|
||
|
return rb_struct_update(dup, hash);
|
||
|
}
|
||
|
/*
|
||
|
* call-seq:
|
||
|
* struct[member] = obj -> obj
|
||
| ... | ... | |
|
rb_define_method(rb_cStruct, "members", rb_struct_members_m, 0);
|
||
|
rb_define_method(rb_cStruct, "dig", rb_struct_dig, -1);
|
||
|
rb_define_method(rb_cStruct, "merge", rb_struct_merge, 1);
|
||
|
rb_define_method(rb_cStruct, "merge!", rb_struct_update, 1);
|
||
|
}
|
||
|
#undef rb_intern
|
||
| test/ruby/test_struct.rb | ||
|---|---|---|
|
assert_nil(o.dig(:b, 0))
|
||
|
end
|
||
|
def test_merge!
|
||
|
klass = @Struct.new(:a, :b)
|
||
|
o = klass.new(1, 2)
|
||
|
o.merge!(a: 10)
|
||
|
assert_equal(o.a, 10)
|
||
|
assert_equal(o.b, 2)
|
||
|
o.merge!("b" => 5)
|
||
|
assert_equal(o.b, 5)
|
||
|
assert_raise(TypeError) {
|
||
|
o.merge(0)
|
||
|
}
|
||
|
end
|
||
|
def test_merge
|
||
|
klass = @Struct.new(:a, :b)
|
||
|
o = klass.new(1, 2)
|
||
|
p = o.merge(a: 10)
|
||
|
assert_equal(p.a, 10)
|
||
|
assert_equal(p.b, 2)
|
||
|
assert_equal(o.a, 1)
|
||
|
assert_equal(o.b, 2)
|
||
|
assert_raise(TypeError) {
|
||
|
o.merge(0)
|
||
|
}
|
||
|
end
|
||
|
def test_new_dupilicate
|
||
|
bug12291 = '[ruby-core:74971] [Bug #12291]'
|
||
|
assert_raise_with_message(ArgumentError, /duplicate member/, bug12291) {
|
||