End of Life Ruby 3.1 has reached end of life and gets no more fixes. Switch to Ruby 4.0 →
Struct.new
static VALUE
rb_struct_s_def(int argc, VALUE *argv, VALUE klass)
{
VALUE name, rest, keyword_init = Qnil;
long i;
VALUE st;
st_table *tbl;
rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
name = argv[0];
if (SYMBOL_P(name)) {
name = Qnil;
}
else {
--argc;
++argv;
}
if (RB_TYPE_P(argv[argc-1], T_HASH)) {
static ID keyword_ids[1];
if (!keyword_ids[0]) {
keyword_ids[0] = rb_intern("keyword_init");
}
rb_get_kwargs(argv[argc-1], keyword_ids, 0, 1, &keyword_init);
if (keyword_init == Qundef) {
keyword_init = Qnil;
}
else if (RTEST(keyword_init)) {
keyword_init = Qtrue;
}
--argc;
}
rest = rb_ident_hash_new();
RBASIC_CLEAR_CLASS(rest);
OBJ_WB_UNPROTECT(rest);
tbl = RHASH_TBL_RAW(rest);
for (i=0; i<argc; i++) {
VALUE mem = rb_to_symbol(argv[i]);
if (rb_is_attrset_sym(mem)) {
rb_raise(rb_eArgError, "invalid struct member: %"PRIsVALUE, mem);
}
if (st_insert(tbl, mem, Qtrue)) {
rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
}
}
rest = rb_hash_keys(rest);
st_clear(tbl);
RBASIC_CLEAR_CLASS(rest);
OBJ_FREEZE_RAW(rest);
if (NIL_P(name)) {
st = anonymous_struct(klass);
}
else {
st = new_struct(name, klass);
}
setup_struct(st, rest);
rb_ivar_set(st, id_keyword_init, keyword_init);
if (rb_block_given_p()) {
rb_mod_module_eval(0, 0, st);
}
return st;
}
Struct.new returns a new subclass of Struct. The new subclass:
-
May be anonymous, or may have the name given by
class_name. -
May have members as given by
member_names. -
May have initialization via ordinary arguments (the default) or via keyword arguments (if
keyword_init: trueis given).
The new subclass has its own method ::new; thus:
Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo f = Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1>
Class Name
With string argument class_name, returns a new subclass of Struct named Struct::<em>class_name</em>:
Foo = Struct.new('Foo', :foo, :bar) # => Struct::Foo Foo.name # => "Struct::Foo" Foo.superclass # => Struct
Without string argument class_name, returns a new anonymous subclass of Struct:
Struct.new(:foo, :bar).name # => nil
Block
With a block given, the created subclass is yielded to the block:
Customer = Struct.new('Customer', :name, :address) do |new_class| p "The new subclass is #{new_class}" def greeting "Hello #{name} at #{address}" end end # => Struct::Customer dave = Customer.new('Dave', '123 Main') dave # => #<struct Struct::Customer name="Dave", address="123 Main"> dave.greeting # => "Hello Dave at 123 Main"
Output, from Struct.new:
"The new subclass is Struct::Customer"
Member Names
Symbol arguments member_names determines the members of the new subclass:
Struct.new(:foo, :bar).members # => [:foo, :bar] Struct.new('Foo', :foo, :bar).members # => [:foo, :bar]
The new subclass has instance methods corresponding to member_names:
Foo = Struct.new('Foo', :foo, :bar) Foo.instance_methods(false) # => [:foo, :bar, :foo=, :bar=] f = Foo.new # => #<struct Struct::Foo foo=nil, bar=nil> f.foo # => nil f.foo = 0 # => 0 f.bar # => nil f.bar = 1 # => 1 f # => #<struct Struct::Foo foo=0, bar=1>
Singleton Methods
A subclass returned by Struct.new has these singleton methods:
-
Method
::newcreates an instance of the subclass:ExampleFoo.new # => #<struct Struct::Foo foo=nil, bar=nil> Foo.new(0) # => #<struct Struct::Foo foo=0, bar=nil> Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1> Foo.new(0, 1, 2) # Raises ArgumentError: struct size differs
Method
::[]is an alias for method::new. -
Method
:inspectreturns a string representation of the subclass:ExampleFoo.inspect # => "Struct::Foo"
-
Method
::membersreturns an array of the member names:ExampleFoo.members # => [:foo, :bar]
Keyword Argument
By default, the arguments for initializing an instance of the new subclass are ordinary arguments (not keyword arguments). With optional keyword argument keyword_init: true, the new subclass is initialized with keyword arguments:
# Without keyword_init: true. Foo = Struct.new('Foo', :foo, :bar) Foo # => Struct::Foo Foo.new(0, 1) # => #<struct Struct::Foo foo=0, bar=1> # With keyword_init: true. Bar = Struct.new(:foo, :bar, keyword_init: true) Bar # => # => Bar(keyword_init: true) Bar.new(bar: 1, foo: 0) # => #<struct Bar foo=0, bar=1>