class method
Data.define
[KLASS < ::Data::_DataClass] (*::Symbol) ?{ (KLASS) [self: KLASS] -> void } -> KLASS
define(*symbols) → class
struct.c
View on GitHub ↗
static VALUE
rb_data_s_def(int argc, VALUE *argv, VALUE klass)
{
VALUE rest;
long i;
VALUE data_class;
rest = rb_ident_hash_new();
RBASIC_CLEAR_CLASS(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 data member: %"PRIsVALUE, mem);
}
if (RTEST(rb_hash_has_key(rest, mem))) {
rb_raise(rb_eArgError, "duplicate member: %"PRIsVALUE, mem);
}
rb_hash_aset(rest, mem, Qtrue);
}
rest = rb_hash_keys(rest);
RBASIC_CLEAR_CLASS(rest);
OBJ_FREEZE(rest);
data_class = anonymous_struct(klass);
setup_data(data_class, rest);
if (rb_block_given_p()) {
rb_mod_module_eval(0, 0, data_class);
}
return data_class;
}
Defines a new Data class.
Example
measure = Data.define(:amount, :unit) #=> #<Class:0x00007f70c6868498> measure.new(1, 'km') #=> #<data amount=1, unit="km"> # It you store the new class in the constant, it will # affect #inspect and will be more natural to use: Measure = Data.define(:amount, :unit) #=> Measure Measure.new(1, 'km') #=> #<data Measure amount=1, unit="km">
Note that member-less Data is acceptable and might be a useful technique for defining several homogeneous data classes, like
Example
class HTTPFetcher Response = Data.define(:body) NotFound = Data.define # ... implementation end
Now, different kinds of responses from HTTPFetcher would have consistent representation:
Example
#<data HTTPFetcher::Response body="<html..."> #<data HTTPFetcher::NotFound>
And are convenient to use in pattern matching:
Example
case fetcher.get(url) in HTTPFetcher::Response(body) # process body variable in HTTPFetcher::NotFound # handle not found case end