AModule is a collection of methods andconstants. The methods in a module may be instance methods or modulemethods. Instance methods appear as methods in a class when the module isincluded, module methods do not. Conversely, module methods may be calledwithout creating an encapsulating object, while instance methods may not.(See#module_function.)
In the descriptions that follow, the parametersym refers to asymbol, which is either a quoted string or aSymbol (such as:name
).
moduleModincludeMathCONST =1defmeth# ...endendMod.class#=> ModuleMod.constants#=> [:CONST, :PI, :E]Mod.instance_methods#=> [:meth]
In the first form, returns an array of the names of all constantsaccessible from the point of call. This list includes the names of allmodules and classes defined in the global scope.
Module.constants.first(4)# => [:ARGF, :ARGV, :ArgumentError, :Array]Module.constants.include?(:SEEK_SET)# => falseclassIOModule.constants.include?(:SEEK_SET)# => trueend
The second form calls the instance methodconstants
.
static VALUErb_mod_s_constants(int argc, VALUE *argv, VALUE mod){ const rb_cref_t *cref = rb_vm_cref(); VALUE klass; VALUE cbase = 0; void *data = 0; if (argc > 0 || mod != rb_cModule) { return rb_mod_constants(argc, argv, mod); } while (cref) { klass = CREF_CLASS(cref); if (!CREF_PUSHED_BY_EVAL(cref) && !NIL_P(klass)) { data = rb_mod_const_at(CREF_CLASS(cref), data); if (!cbase) { cbase = klass; } } cref = CREF_NEXT(cref); } if (cbase) { data = rb_mod_const_of(cbase, data); } return rb_const_list(data);}
Returns the list ofModules
nested at the point of call.
moduleM1moduleM2$a =Module.nestingendend$a#=> [M1::M2, M1]$a[0].name#=> "M1::M2"
static VALUErb_mod_nesting(VALUE _){ VALUE ary = rb_ary_new(); const rb_cref_t *cref = rb_vm_cref(); while (cref && CREF_NEXT(cref)) { VALUE klass = CREF_CLASS(cref); if (!CREF_PUSHED_BY_EVAL(cref) && !NIL_P(klass)) { rb_ary_push(ary, klass); } cref = CREF_NEXT(cref); } return ary;}
Creates a new anonymous module. If a block is given, it is passed themodule object, and the block is evaluated in the context of this modulelikemodule_eval.
fred =Module.newdodefmeth1"hello"enddefmeth2"bye"endenda ="my string"a.extend(fred)#=> "my string"a.meth1#=> "hello"a.meth2#=> "bye"
Assign the module to a constant (name starting uppercase) if you want totreat it like a regular module.
static VALUErb_mod_initialize(VALUE module){ if (rb_block_given_p()) { rb_mod_module_exec(1, &module, module); } return Qnil;}
Returns an array of all modules used in the current scope. The ordering ofmodules in the resulting array is not defined.
moduleArefineObjectdoendendmoduleBrefineObjectdoendendusingAusingBpModule.used_modules
produces:
[B,A]
static VALUErb_mod_s_used_modules(VALUE _){ const rb_cref_t *cref = rb_vm_cref(); VALUE ary = rb_ary_new(); while (cref) { if (!NIL_P(CREF_REFINEMENTS(cref))) { rb_hash_foreach(CREF_REFINEMENTS(cref), used_modules_i, ary); } cref = CREF_NEXT(cref); } return rb_funcall(ary, rb_intern("uniq"), 0);}
Returns true ifmod is a subclass ofother. Returnsnil
if there's no relationship between the two. (Think ofthe relationship in terms of the class definition: “class A < B” implies“A < B”.)
static VALUErb_mod_lt(VALUE mod, VALUE arg){ if (mod == arg) return Qfalse; return rb_class_inherited_p(mod, arg);}
Returns true ifmod is a subclass ofother or is the sameasother. Returnsnil
if there's no relationshipbetween the two. (Think of the relationship in terms of the classdefinition: “class A < B” implies “A < B”.)
VALUErb_class_inherited_p(VALUE mod, VALUE arg){ if (mod == arg) return Qtrue; if (!CLASS_OR_MODULE_P(arg) && !RB_TYPE_P(arg, T_ICLASS)) { rb_raise(rb_eTypeError, "compared with non class/module"); } if (class_search_ancestor(mod, RCLASS_ORIGIN(arg))) { return Qtrue; } /* not mod < arg; check if mod > arg */ if (class_search_ancestor(arg, mod)) { return Qfalse; } return Qnil;}
Comparison—Returns -1, 0, +1 or nil depending on whethermodule
includesother_module
, they are the same,or ifmodule
is included byother_module
.
Returnsnil
ifmodule
has no relationship withother_module
, ifother_module
is not a module, orif the two values are incomparable.
static VALUErb_mod_cmp(VALUE mod, VALUE arg){ VALUE cmp; if (mod == arg) return INT2FIX(0); if (!CLASS_OR_MODULE_P(arg)) { return Qnil; } cmp = rb_class_inherited_p(mod, arg); if (NIL_P(cmp)) return Qnil; if (cmp) { return INT2FIX(-1); } return INT2FIX(1);}
Equality — At theObject level, #== returnstrue
only ifobj
andother
are thesame object. Typically, this method is overridden in descendant classes toprovide class-specific meaning.
Unlike #==, theequal?method should never be overridden by subclasses as it is used to determineobject identity (that is,a.equal?(b)
if and only ifa
is the same object asb
):
obj ="a"other =obj.dupobj==other#=> trueobj.equal?other#=> falseobj.equal?obj#=> true
Theeql? method returnstrue
ifobj
andother
refer to thesame hash key. This is used byHash to testmembers for equality. For any pair of objects whereeql? returnstrue
, thehash value of both objects must beequal. So any subclass that overrideseql? should also overridehash appropriately.
For objects of classObject,eql? is synonymous with #==. Subclasses normally continue this tradition by aliasingeql? to their overridden #== method,but there are exceptions.Numeric types, forexample, perform type conversion across #==, but not acrosseql?, so:
1==1.0#=> true1.eql?1.0#=> false
MJIT_FUNC_EXPORTED VALUErb_obj_equal(VALUE obj1, VALUE obj2){ if (obj1 == obj2) return Qtrue; return Qfalse;}
Case Equality—Returnstrue
ifobj is an instance ofmod or an instance of one ofmod's descendants. Oflimited use for modules, but can be used incase
statements toclassify objects by class.
static VALUErb_mod_eqq(VALUE mod, VALUE arg){ return rb_obj_is_kind_of(arg, mod);}
Returns true ifmod is an ancestor ofother. Returnsnil
if there's no relationship between the two. (Think ofthe relationship in terms of the class definition: “class A < B” implies“B > A”.)
static VALUErb_mod_gt(VALUE mod, VALUE arg){ if (mod == arg) return Qfalse; return rb_mod_ge(mod, arg);}
Returns true ifmod is an ancestor ofother, or the twomodules are the same. Returnsnil
if there's norelationship between the two. (Think of the relationship in terms of theclass definition: “class A < B” implies “B > A”.)
static VALUErb_mod_ge(VALUE mod, VALUE arg){ if (!CLASS_OR_MODULE_P(arg)) { rb_raise(rb_eTypeError, "compared with non class/module"); } return rb_class_inherited_p(arg, mod);}
Makesnew_name a new copy of the methodold_name. Thiscan be used to retain access to methods that are overridden.
moduleModalias_method :orig_exit, :exit#=> :orig_exitdefexit(code=0)puts"Exiting with code #{code}"orig_exit(code)endendincludeModexit(99)
produces:
Exitingwithcode99
static VALUErb_mod_alias_method(VALUE mod, VALUE newname, VALUE oldname){ ID oldid = rb_check_id(&oldname); if (!oldid) { rb_print_undef_str(mod, oldname); } VALUE id = rb_to_id(newname); rb_alias(mod, id, oldid); return ID2SYM(id);}
Returns a list of modules included/prepended inmod (includingmod itself).
moduleModincludeMathincludeComparableprependEnumerableendMod.ancestors#=> [Enumerable, Mod, Comparable, Math]Math.ancestors#=> [Math]Enumerable.ancestors#=> [Enumerable]
VALUErb_mod_ancestors(VALUE mod){ VALUE p, ary = rb_ary_new(); for (p = mod; p; p = RCLASS_SUPER(p)) { if (p != RCLASS_ORIGIN(p)) continue;if (BUILTIN_TYPE(p) == T_ICLASS) { rb_ary_push(ary, RBASIC(p)->klass);} else { rb_ary_push(ary, p);} } return ary;}
The first form is equivalent toattr_reader. The second form isequivalent toattr_accessor(name)
but deprecated. The lastform is equivalent toattr_reader(name)
but deprecated.Returns an array of defined method names as symbols.
VALUErb_mod_attr(int argc, VALUE *argv, VALUE klass){ if (argc == 2 && (argv[1] == Qtrue || argv[1] == Qfalse)) { ID id = id_for_attr(klass, argv[0]); VALUE names = rb_ary_new(); rb_category_warning(RB_WARN_CATEGORY_DEPRECATED, "optional boolean argument is obsoleted"); rb_attr(klass, id, 1, RTEST(argv[1]), TRUE); rb_ary_push(names, ID2SYM(id)); if (argv[1] == Qtrue) rb_ary_push(names, ID2SYM(rb_id_attrset(id))); return names; } return rb_mod_attr_reader(argc, argv, klass);}
Defines a named attribute for this module, where the name issymbol.id2name
, creating an instance variable(@name
) and a corresponding access method to read it. Alsocreates a method calledname=
to set the attribute.String arguments are converted to symbols. Returnsan array of defined method names as symbols.
moduleModattr_accessor(:one, :two)#=> [:one, :one=, :two, :two=]endMod.instance_methods.sort#=> [:one, :one=, :two, :two=]
static VALUErb_mod_attr_accessor(int argc, VALUE *argv, VALUE klass){ int i; VALUE names = rb_ary_new2(argc * 2); for (i=0; i<argc; i++) { ID id = id_for_attr(klass, argv[i]); rb_attr(klass, id, TRUE, TRUE, TRUE); rb_ary_push(names, ID2SYM(id)); rb_ary_push(names, ID2SYM(rb_id_attrset(id))); } return names;}
Creates instance variables and corresponding methods that return the valueof each instance variable. Equivalent to calling“attr
:name'' on each name in turn.String arguments are converted to symbols. Returnsan array of defined method names as symbols.
static VALUErb_mod_attr_reader(int argc, VALUE *argv, VALUE klass){ int i; VALUE names = rb_ary_new2(argc); for (i=0; i<argc; i++) { ID id = id_for_attr(klass, argv[i]); rb_attr(klass, id, TRUE, FALSE, TRUE); rb_ary_push(names, ID2SYM(id)); } return names;}
Creates an accessor method to allow assignment to the attributesymbol.id2name
.Stringarguments are converted to symbols. Returns an array of defined methodnames as symbols.
static VALUErb_mod_attr_writer(int argc, VALUE *argv, VALUE klass){ int i; VALUE names = rb_ary_new2(argc); for (i=0; i<argc; i++) { ID id = id_for_attr(klass, argv[i]); rb_attr(klass, id, FALSE, TRUE, TRUE); rb_ary_push(names, ID2SYM(rb_id_attrset(id))); } return names;}
Registersfilename to be loaded (using Kernel::require) the firsttime thatmodule (which may be aStringor a symbol) is accessed in the namespace ofmod.
moduleAendA.autoload(:B,"b")A::B.doit# autoloads "b"
static VALUErb_mod_autoload(VALUE mod, VALUE sym, VALUE file){ ID id = rb_to_id(sym); FilePathValue(file); rb_autoload_str(mod, id, file); return Qnil;}
Returnsfilename to be loaded ifname is registered asautoload
in the namespace ofmod or one of itsancestors.
moduleAendA.autoload(:B,"b")A.autoload?(:B)#=> "b"
Ifinherit
is false, the lookup only checks the autoloads inthe receiver:
classAautoload :CONST,"const.rb"endclassB<AendB.autoload?(:CONST)#=> "const.rb", found in A (ancestor)B.autoload?(:CONST,false)#=> nil, not found in B itself
static VALUErb_mod_autoload_p(int argc, VALUE *argv, VALUE mod){ int recur = (rb_check_arity(argc, 1, 2) == 1) ? TRUE : RTEST(argv[1]); VALUE sym = argv[0]; ID id = rb_check_id(&sym); if (!id) { return Qnil; } return rb_autoload_at_p(mod, id, recur);}
Evaluates the string or block in the context ofmod, except thatwhen a block is given, constant/class variable lookup is not affected. Thiscan be used to add methods to a class.module_eval
returns theresult of evaluating its argument. The optionalfilename andlineno parameters set the text for error messages.
classThingenda =%q{def hello() "Hello there!" end}Thing.module_eval(a)putsThing.new.hello()Thing.module_eval("invalid code","dummy",123)
produces:
Hello there!dummy:123:in `module_eval': undefined local variable or method `code' for Thing:Class
static VALUErb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod){ return specific_eval(argc, argv, mod, mod, RB_PASS_CALLED_KEYWORDS);}
Evaluates the given block in the context of the class/module. The methoddefined in the block will belong to the receiver. Any arguments passed tothe method will be passed to the block. This can be used if the block needsto access instance variables.
classThingendThing.class_exec{defhello()"Hello there!"end}putsThing.new.hello()
produces:
Hellothere!
static VALUErb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod){ return yield_under(mod, mod, argc, argv, RB_PASS_CALLED_KEYWORDS);}
Returnstrue
if the given class variable is defined inobj.String arguments are converted tosymbols.
classFred@@foo =99endFred.class_variable_defined?(:@@foo)#=> trueFred.class_variable_defined?(:@@bar)#=> false
static VALUErb_mod_cvar_defined(VALUE obj, VALUE iv){ ID id = id_for_var(obj, iv, class); if (!id) { return Qfalse; } return rb_cvar_defined(obj, id);}
Returns the value of the given class variable (or throws aNameError exception). The@@
part ofthe variable name should be included for regular class variables.String arguments are converted to symbols.
classFred@@foo =99endFred.class_variable_get(:@@foo)#=> 99
static VALUErb_mod_cvar_get(VALUE obj, VALUE iv){ ID id = id_for_var(obj, iv, class); if (!id) { rb_name_err_raise("uninitialized class variable %1$s in %2$s", obj, iv); } return rb_cvar_get(obj, id);}
Sets the class variable named bysymbol to the given object. Ifthe class variable name is passed as a string, that string is converted toa symbol.
classFred@@foo =99deffoo@@fooendendFred.class_variable_set(:@@foo,101)#=> 101Fred.new.foo#=> 101
static VALUErb_mod_cvar_set(VALUE obj, VALUE iv, VALUE val){ ID id = id_for_var(obj, iv, class); if (!id) id = rb_intern_str(iv); rb_cvar_set(obj, id, val); return val;}
Returns an array of the names of class variables inmod. Thisincludes the names of class variables in any included modules, unless theinherit parameter is set tofalse
.
classOne@@var1 =1endclassTwo<One@@var2 =2endOne.class_variables#=> [:@@var1]Two.class_variables#=> [:@@var2, :@@var1]Two.class_variables(false)#=> [:@@var2]
VALUErb_mod_class_variables(int argc, const VALUE *argv, VALUE mod){ bool inherit = true; st_table *tbl; if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]); if (inherit) {tbl = mod_cvar_of(mod, 0); } else {tbl = mod_cvar_at(mod, 0); } return cvar_list(tbl);}
Says whethermod or its ancestors have a constant with the givenname:
Float.const_defined?(:EPSILON)#=> true, found in Float itselfFloat.const_defined?("String")#=> true, found in Object (ancestor)BasicObject.const_defined?(:Hash)#=> false
Ifmod is aModule
, additionallyObject
and its ancestors are checked:
Math.const_defined?(:String)#=> true, found in Object
In each of the checked classes or modules, if the constant is not presentbut there is an autoload for it,true
is returned directlywithout autoloading:
moduleAdminautoload :User,'admin/user'endAdmin.const_defined?(:User)#=> true
If the constant is not found the callbackconst_missing
isnot called and the method returnsfalse
.
Ifinherit
is false, the lookup only checks the constants inthe receiver:
IO.const_defined?(:SYNC)#=> true, found in File::Constants (ancestor)IO.const_defined?(:SYNC,false)#=> false, not found in IO itself
In this case, the same logic for autoloading applies.
If the argument is not a valid constant name aNameError
israised with the message “wrong constant namename”:
Hash.const_defined?'foobar'#=> NameError: wrong constant name foobar
static VALUErb_mod_const_defined(int argc, VALUE *argv, VALUE mod){ VALUE name, recur; rb_encoding *enc; const char *pbeg, *p, *path, *pend; ID id; rb_check_arity(argc, 1, 2); name = argv[0]; recur = (argc == 1) ? Qtrue : argv[1]; if (SYMBOL_P(name)) { if (!rb_is_const_sym(name)) goto wrong_name; id = rb_check_id(&name); if (!id) return Qfalse; return RTEST(recur) ? rb_const_defined(mod, id) : rb_const_defined_at(mod, id); } path = StringValuePtr(name); enc = rb_enc_get(name); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)"); } pbeg = p = path; pend = path + RSTRING_LEN(name); if (p >= pend || !*p) { goto wrong_name; } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { mod = rb_cObject; p += 2; pbeg = p; } while (p < pend) { VALUE part; long len, beglen; while (p < pend && *p != ':') p++; if (pbeg == p) goto wrong_name; id = rb_check_id_cstr(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { if (p + 2 >= pend || p[1] != ':') goto wrong_name; p += 2; pbeg = p; } if (!id) { part = rb_str_subseq(name, beglen, len); OBJ_FREEZE(part); if (!rb_is_const_name(part)) { name = part; goto wrong_name; } else { return Qfalse; } } if (!rb_is_const_id(id)) { name = ID2SYM(id); goto wrong_name; }#if 0 mod = rb_const_search(mod, id, beglen > 0 || !RTEST(recur), RTEST(recur), FALSE); if (mod == Qundef) return Qfalse;#else if (!RTEST(recur)) { if (!rb_const_defined_at(mod, id)) return Qfalse; if (p == pend) return Qtrue; mod = rb_const_get_at(mod, id); } else if (beglen == 0) { if (!rb_const_defined(mod, id)) return Qfalse; if (p == pend) return Qtrue; mod = rb_const_get(mod, id); } else { if (!rb_const_defined_from(mod, id)) return Qfalse; if (p == pend) return Qtrue; mod = rb_const_get_from(mod, id); }#endif if (p < pend && !RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) { rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module", QUOTE(name)); } } return Qtrue; wrong_name: rb_name_err_raise(wrong_constant_name, mod, name); UNREACHABLE_RETURN(Qundef);}
Checks for a constant with the given name inmod. Ifinherit
is set, the lookup will also search the ancestors (andObject
ifmod is aModule
).
The value of the constant is returned if a definition is found, otherwise aNameError
is raised.
Math.const_get(:PI)#=> 3.14159265358979
This method will recursively look up constant names if a namespaced classname is provided. For example:
moduleFoo;classBar;endendObject.const_get'Foo::Bar'
Theinherit
flag is respected on each lookup. For example:
moduleFooclassBarVAL =10endclassBaz<Bar;endendObject.const_get'Foo::Baz::VAL'# => 10Object.const_get'Foo::Baz::VAL',false# => NameError
If the argument is not a valid constant name aNameError
willbe raised with a warning “wrong constant name”.
Object.const_get'foobar'#=> NameError: wrong constant name foobar
static VALUErb_mod_const_get(int argc, VALUE *argv, VALUE mod){ VALUE name, recur; rb_encoding *enc; const char *pbeg, *p, *path, *pend; ID id; rb_check_arity(argc, 1, 2); name = argv[0]; recur = (argc == 1) ? Qtrue : argv[1]; if (SYMBOL_P(name)) { if (!rb_is_const_sym(name)) goto wrong_name; id = rb_check_id(&name); if (!id) return rb_const_missing(mod, name); return RTEST(recur) ? rb_const_get(mod, id) : rb_const_get_at(mod, id); } path = StringValuePtr(name); enc = rb_enc_get(name); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)"); } pbeg = p = path; pend = path + RSTRING_LEN(name); if (p >= pend || !*p) { goto wrong_name; } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { mod = rb_cObject; p += 2; pbeg = p; } while (p < pend) { VALUE part; long len, beglen; while (p < pend && *p != ':') p++; if (pbeg == p) goto wrong_name; id = rb_check_id_cstr(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { if (p + 2 >= pend || p[1] != ':') goto wrong_name; p += 2; pbeg = p; } if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) { rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module", QUOTE(name)); } if (!id) { part = rb_str_subseq(name, beglen, len); OBJ_FREEZE(part); if (!rb_is_const_name(part)) { name = part; goto wrong_name; } else if (!rb_method_basic_definition_p(CLASS_OF(mod), id_const_missing)) { part = rb_str_intern(part); mod = rb_const_missing(mod, part); continue; } else { rb_mod_const_missing(mod, part); } } if (!rb_is_const_id(id)) { name = ID2SYM(id); goto wrong_name; }#if 0 mod = rb_const_get_0(mod, id, beglen > 0 || !RTEST(recur), RTEST(recur), FALSE);#else if (!RTEST(recur)) { mod = rb_const_get_at(mod, id); } else if (beglen == 0) { mod = rb_const_get(mod, id); } else { mod = rb_const_get_from(mod, id); }#endif } return mod; wrong_name: rb_name_err_raise(wrong_constant_name, mod, name); UNREACHABLE_RETURN(Qundef);}
Invoked when a reference is made to an undefined constant inmod.It is passed a symbol for the undefined constant, and returns a value to beused for that constant. The following code is an example of the same:
defFoo.const_missing(name)name# return the constant name as SymbolendFoo::UNDEFINED_CONST#=> :UNDEFINED_CONST: symbol returned
In the next example when a reference is made to an undefined constant, itattempts to load a file whose name is the lowercase version of the constant(thus classFred
is assumed to be in filefred.rb
). If found, it returns the loaded class. It thereforeimplements an autoload feature similar toKernel#autoload and#autoload.
defObject.const_missing(name)@looked_for||= {}str_name =name.to_sraise"Class not found: #{name}"if@looked_for[str_name]@looked_for[str_name] =1file =str_name.downcaserequirefileklass =const_get(name)returnklassifklassraise"Class not found: #{name}"end
VALUErb_mod_const_missing(VALUE klass, VALUE name){ VALUE ref = GET_EC()->private_const_reference; rb_vm_pop_cfunc_frame(); if (ref) {rb_name_err_raise("private constant %2$s::%1$s referenced", ref, name); } uninitialized_constant(klass, name); UNREACHABLE_RETURN(Qnil);}
Sets the named constant to the given object, returning that object. Createsa new constant if no constant with the given name previously existed.
Math.const_set("HIGH_SCHOOL_PI",22.0/7.0)#=> 3.14285714285714Math::HIGH_SCHOOL_PI-Math::PI#=> 0.00126448926734968
Ifsym
orstr
is not a valid constant name aNameError
will be raised with a warning “wrong constant name”.
Object.const_set('foobar',42)#=> NameError: wrong constant name foobar
static VALUErb_mod_const_set(VALUE mod, VALUE name, VALUE value){ ID id = id_for_var(mod, name, const); if (!id) id = rb_intern_str(name); rb_const_set(mod, id, value); return value;}
Returns the Ruby source filename and line number containing the definitionof the constant specified. If the named constant is not found,nil
is returned. If the constant is found, but its sourcelocation can not be extracted (constant is defined in C code), empty arrayis returned.
inherit specifies whether to lookup inmod.ancestors
(true
by default).
# test.rb:classA# line 1C1 =1C2 =2endmoduleM# line 6C3 =3endclassB<A# line 10includeMC4 =4endclassA# continuation of A definitionC2 =8# constant redefinition; warned yet allowedendpB.const_source_location('C4')# => ["test.rb", 12]pB.const_source_location('C3')# => ["test.rb", 7]pB.const_source_location('C1')# => ["test.rb", 2]pB.const_source_location('C3',false)# => nil -- don't lookup in ancestorspA.const_source_location('C2')# => ["test.rb", 16] -- actual (last) definition placepObject.const_source_location('B')# => ["test.rb", 10] -- top-level constant could be looked through ObjectpObject.const_source_location('A')# => ["test.rb", 1] -- class reopening is NOT considered new definitionpB.const_source_location('A')# => ["test.rb", 1] -- because Object is in ancestorspM.const_source_location('A')# => ["test.rb", 1] -- Object is not ancestor, but additionally checked for modulespObject.const_source_location('A::C1')# => ["test.rb", 2] -- nesting is supportedpObject.const_source_location('String')# => [] -- constant is defined in C code
static VALUErb_mod_const_source_location(int argc, VALUE *argv, VALUE mod){ VALUE name, recur, loc = Qnil; rb_encoding *enc; const char *pbeg, *p, *path, *pend; ID id; rb_check_arity(argc, 1, 2); name = argv[0]; recur = (argc == 1) ? Qtrue : argv[1]; if (SYMBOL_P(name)) { if (!rb_is_const_sym(name)) goto wrong_name; id = rb_check_id(&name); if (!id) return Qnil; return RTEST(recur) ? rb_const_source_location(mod, id) : rb_const_source_location_at(mod, id); } path = StringValuePtr(name); enc = rb_enc_get(name); if (!rb_enc_asciicompat(enc)) { rb_raise(rb_eArgError, "invalid class path encoding (non ASCII)"); } pbeg = p = path; pend = path + RSTRING_LEN(name); if (p >= pend || !*p) { goto wrong_name; } if (p + 2 < pend && p[0] == ':' && p[1] == ':') { mod = rb_cObject; p += 2; pbeg = p; } while (p < pend) { VALUE part; long len, beglen; while (p < pend && *p != ':') p++; if (pbeg == p) goto wrong_name; id = rb_check_id_cstr(pbeg, len = p-pbeg, enc); beglen = pbeg-path; if (p < pend && p[0] == ':') { if (p + 2 >= pend || p[1] != ':') goto wrong_name; p += 2; pbeg = p; } if (!id) { part = rb_str_subseq(name, beglen, len); OBJ_FREEZE(part); if (!rb_is_const_name(part)) { name = part; goto wrong_name; } else { return Qnil; } } if (!rb_is_const_id(id)) { name = ID2SYM(id); goto wrong_name; } if (p < pend) { if (RTEST(recur)) { mod = rb_const_get(mod, id); } else { mod = rb_const_get_at(mod, id); } if (!RB_TYPE_P(mod, T_MODULE) && !RB_TYPE_P(mod, T_CLASS)) { rb_raise(rb_eTypeError, "%"PRIsVALUE" does not refer to class/module", QUOTE(name)); } } else { if (RTEST(recur)) { loc = rb_const_source_location(mod, id); } else { loc = rb_const_source_location_at(mod, id); } break; } recur = Qfalse; } return loc; wrong_name: rb_name_err_raise(wrong_constant_name, mod, name); UNREACHABLE_RETURN(Qundef);}
Returns an array of the names of the constants accessible inmod.This includes the names of constants in any included modules (example atstart of section), unless theinherit parameter is set tofalse
.
The implementation makes no guarantees about the order in which theconstants are yielded.
IO.constants.include?(:SYNC)#=> trueIO.constants(false).include?(:SYNC)#=> false
Also see#const_defined?.
VALUErb_mod_constants(int argc, const VALUE *argv, VALUE mod){ bool inherit = true; if (rb_check_arity(argc, 0, 1)) inherit = RTEST(argv[0]); if (inherit) {return rb_const_list(rb_mod_const_of(mod, 0)); } else {return rb_local_constants(mod); }}
Defines an instance method in the receiver. Themethod parametercan be aProc
, aMethod
or anUnboundMethod
object. If a block is specified, it is used asthe method body. If a block or themethod parameter hasparameters, they're used as method parameters. This block is evaluatedusinginstance_eval.
classAdeffredputs"In Fred"enddefcreate_method(name,&block)self.class.define_method(name,&block)enddefine_method(:wilma) {puts"Charge it!" }define_method(:flint) {|name|puts"I'm #{name}!"}endclassB<Adefine_method(:barney,instance_method(:fred))enda =B.newa.barneya.wilmaa.flint('Dino')a.create_method(:betty) {pself }a.betty
produces:
In FredCharge it!I'm Dino!#<B:0x401b39e8>
static VALUErb_mod_define_method(int argc, VALUE *argv, VALUE mod){ ID id; VALUE body; VALUE name; const rb_cref_t *cref = rb_vm_cref_in_context(mod, mod); const rb_scope_visibility_t default_scope_visi = {METHOD_VISI_PUBLIC, FALSE}; const rb_scope_visibility_t *scope_visi = &default_scope_visi; int is_method = FALSE; if (cref) { scope_visi = CREF_SCOPE_VISI(cref); } rb_check_arity(argc, 1, 2); name = argv[0]; id = rb_check_id(&name); if (argc == 1) { body = rb_block_lambda(); } else { body = argv[1]; if (rb_obj_is_method(body)) { is_method = TRUE; } else if (rb_obj_is_proc(body)) { is_method = FALSE; } else { rb_raise(rb_eTypeError, "wrong argument type %s (expected Proc/Method/UnboundMethod)", rb_obj_classname(body)); } } if (!id) id = rb_to_id(name); if (is_method) { struct METHOD *method = (struct METHOD *)DATA_PTR(body); if (method->me->owner != mod && !RB_TYPE_P(method->me->owner, T_MODULE) && !RTEST(rb_class_inherited_p(mod, method->me->owner))) { if (FL_TEST(method->me->owner, FL_SINGLETON)) { rb_raise(rb_eTypeError, "can't bind singleton method to a different class"); } else { rb_raise(rb_eTypeError, "bind argument must be a subclass of % "PRIsVALUE, method->me->owner); } } rb_method_entry_set(mod, id, method->me, scope_visi->method_visi); if (scope_visi->module_func) { rb_method_entry_set(rb_singleton_class(mod), id, method->me, METHOD_VISI_PUBLIC); } RB_GC_GUARD(body); } else { VALUE procval = rb_proc_dup(body); if (vm_proc_iseq(procval) != NULL) { rb_proc_t *proc; GetProcPtr(procval, proc); proc->is_lambda = TRUE; proc->is_from_method = TRUE; } rb_add_method(mod, id, VM_METHOD_TYPE_BMETHOD, (void *)procval, scope_visi->method_visi); if (scope_visi->module_func) { rb_add_method(rb_singleton_class(mod), id, VM_METHOD_TYPE_BMETHOD, (void *)body, METHOD_VISI_PUBLIC); } } return ID2SYM(id);}
Makes a list of existing constants deprecated. Attempt to refer to themwill produce a warning.
moduleHTTPNotFound =Exception.newNOT_FOUND =NotFound# previous version of the library used this namedeprecate_constant :NOT_FOUNDendHTTP::NOT_FOUND# warning: constant HTTP::NOT_FOUND is deprecated
VALUErb_mod_deprecate_constant(int argc, const VALUE *argv, VALUE obj){ set_const_visibility(obj, argc, argv, CONST_DEPRECATED, CONST_DEPRECATED); return obj;}
Prevents further modifications tomod.
This method returns self.
static VALUErb_mod_freeze(VALUE mod){ rb_class_name(mod); return rb_obj_freeze(mod);}
Invokes#append_featureson each parameter in reverse order.
static VALUErb_mod_include(int argc, VALUE *argv, VALUE module){ int i; ID id_append_features, id_included; CONST_ID(id_append_features, "append_features"); CONST_ID(id_included, "included"); rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); for (i = 0; i < argc; i++) Check_Type(argv[i], T_MODULE); while (argc--) { rb_funcall(argv[argc], id_append_features, 1, module); rb_funcall(argv[argc], id_included, 1, module); } return module;}
Returnstrue
ifmodule is included or prepended inmod or one ofmod's ancestors.
moduleAendclassBincludeAendclassC<BendB.include?(A)#=> trueC.include?(A)#=> trueA.include?(A)#=> false
VALUErb_mod_include_p(VALUE mod, VALUE mod2){ VALUE p; Check_Type(mod2, T_MODULE); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) { if (RBASIC(p)->klass == mod2) return Qtrue;} } return Qfalse;}
Returns the list of modules included or prepended inmod or one ofmod's ancestors.
moduleSubendmoduleMixinprependSubendmoduleOuterincludeMixinendMixin.included_modules#=> [Sub]Outer.included_modules#=> [Sub, Mixin]
VALUErb_mod_included_modules(VALUE mod){ VALUE ary = rb_ary_new(); VALUE p; VALUE origin = RCLASS_ORIGIN(mod); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { if (p != origin && RCLASS_ORIGIN(p) == p && BUILTIN_TYPE(p) == T_ICLASS) { VALUE m = RBASIC(p)->klass; if (RB_TYPE_P(m, T_MODULE))rb_ary_push(ary, m);} } return ary;}
Returns anUnboundMethod
representing the given instancemethod inmod.
classInterpreterdefdo_a()print"there, ";enddefdo_d()print"Hello ";enddefdo_e()print"!\n";enddefdo_v()print"Dave";endDispatcher = {"a" =>instance_method(:do_a),"d" =>instance_method(:do_d),"e" =>instance_method(:do_e),"v" =>instance_method(:do_v) }definterpret(string)string.each_char {|b|Dispatcher[b].bind(self).call }endendinterpreter =Interpreter.newinterpreter.interpret('dave')
produces:
Hellothere,Dave!
static VALUErb_mod_instance_method(VALUE mod, VALUE vid){ ID id = rb_check_id(&vid); if (!id) { rb_method_name_error(mod, vid); } return mnew(mod, Qundef, id, rb_cUnboundMethod, FALSE);}
Returns an array containing the names of the public and protected instancemethods in the receiver. For a module, these are the public and protectedmethods; for a class, they are the instance (not singleton) methods. If theoptional parameter isfalse
, the methods of any ancestors arenot included.
moduleAdefmethod1()endendclassBincludeAdefmethod2()endendclassC<Bdefmethod3()endendA.instance_methods(false)#=> [:method1]B.instance_methods(false)#=> [:method2]B.instance_methods(true).include?(:method1)#=> trueC.instance_methods(false)#=> [:method3]C.instance_methods.include?(:method2)#=> true
VALUErb_class_instance_methods(int argc, const VALUE *argv, VALUE mod){ return class_instance_method_list(argc, argv, mod, 0, ins_methods_i);}
Returnstrue
if the named method is defined bymod. Ifinherit is set, the lookup will also searchmod'sancestors. Public and protected methods are matched.String arguments are converted to symbols.
moduleAdefmethod1()enddefprotected_method1()endprotected :protected_method1endclassBdefmethod2()enddefprivate_method2()endprivate :private_method2endclassC<BincludeAdefmethod3()endendA.method_defined? :method1#=> trueC.method_defined?"method1"#=> trueC.method_defined?"method2"#=> trueC.method_defined?"method2",true#=> trueC.method_defined?"method2",false#=> falseC.method_defined?"method3"#=> trueC.method_defined?"protected_method1"#=> trueC.method_defined?"method4"#=> falseC.method_defined?"private_method2"#=> false
static VALUErb_mod_method_defined(int argc, VALUE *argv, VALUE mod){ rb_method_visibility_t visi = check_definition_visibility(mod, argc, argv); return (visi == METHOD_VISI_PUBLIC || visi == METHOD_VISI_PROTECTED) ? Qtrue : Qfalse;}
Evaluates the string or block in the context ofmod, except thatwhen a block is given, constant/class variable lookup is not affected. Thiscan be used to add methods to a class.module_eval
returns theresult of evaluating its argument. The optionalfilename andlineno parameters set the text for error messages.
classThingenda =%q{def hello() "Hello there!" end}Thing.module_eval(a)putsThing.new.hello()Thing.module_eval("invalid code","dummy",123)
produces:
Hello there!dummy:123:in `module_eval': undefined local variable or method `code' for Thing:Class
static VALUErb_mod_module_eval_internal(int argc, const VALUE *argv, VALUE mod){ return specific_eval(argc, argv, mod, mod, RB_PASS_CALLED_KEYWORDS);}
Evaluates the given block in the context of the class/module. The methoddefined in the block will belong to the receiver. Any arguments passed tothe method will be passed to the block. This can be used if the block needsto access instance variables.
classThingendThing.class_exec{defhello()"Hello there!"end}putsThing.new.hello()
produces:
Hellothere!
static VALUErb_mod_module_exec_internal(int argc, const VALUE *argv, VALUE mod){ return yield_under(mod, mod, argc, argv, RB_PASS_CALLED_KEYWORDS);}
Returns the name of the modulemod. Returns nil for anonymousmodules.
VALUErb_mod_name(VALUE mod){ int permanent; return classname(mod, &permanent);}
Invokes#prepend_features on eachparameter in reverse order.
static VALUErb_mod_prepend(int argc, VALUE *argv, VALUE module){ int i; ID id_prepend_features, id_prepended; CONST_ID(id_prepend_features, "prepend_features"); CONST_ID(id_prepended, "prepended"); rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); for (i = 0; i < argc; i++) Check_Type(argv[i], T_MODULE); while (argc--) { rb_funcall(argv[argc], id_prepend_features, 1, module); rb_funcall(argv[argc], id_prepended, 1, module); } return module;}
Makes existing class methods private. Often used to hide the defaultconstructornew
.
String arguments are converted to symbols. AnArray of Symbols and/or Strings are also accepted.
classSimpleSingleton# Not thread safeprivate_class_method :newdefSimpleSingleton.create(*args,&block)@me =new(*args,&block)if!@me@meendend
static VALUErb_mod_private_method(int argc, VALUE *argv, VALUE obj){ set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PRIVATE); return obj;}
Makes a list of existing constants private.
VALUErb_mod_private_constant(int argc, const VALUE *argv, VALUE obj){ set_const_visibility(obj, argc, argv, CONST_PRIVATE, CONST_VISIBILITY_MASK); return obj;}
Returns a list of the private instance methods defined inmod. Ifthe optional parameter isfalse
, the methods of any ancestorsare not included.
moduleModdefmethod1()endprivate :method1defmethod2()endendMod.instance_methods#=> [:method2]Mod.private_instance_methods#=> [:method1]
VALUErb_class_private_instance_methods(int argc, const VALUE *argv, VALUE mod){ return class_instance_method_list(argc, argv, mod, 0, ins_methods_priv_i);}
Returnstrue
if the named private method is defined bymod. Ifinherit is set, the lookup will also searchmod's ancestors.String argumentsare converted to symbols.
moduleAdefmethod1()endendclassBprivatedefmethod2()endendclassC<BincludeAdefmethod3()endendA.method_defined? :method1#=> trueC.private_method_defined?"method1"#=> falseC.private_method_defined?"method2"#=> trueC.private_method_defined?"method2",true#=> trueC.private_method_defined?"method2",false#=> falseC.method_defined?"method2"#=> false
static VALUErb_mod_private_method_defined(int argc, VALUE *argv, VALUE mod){ return check_definition(mod, argc, argv, METHOD_VISI_PRIVATE);}
Returns a list of the protected instance methods defined inmod.If the optional parameter isfalse
, the methods of anyancestors are not included.
VALUErb_class_protected_instance_methods(int argc, const VALUE *argv, VALUE mod){ return class_instance_method_list(argc, argv, mod, 0, ins_methods_prot_i);}
Returnstrue
if the named protected method is definedmod. Ifinherit is set, the lookup will also searchmod's ancestors.String argumentsare converted to symbols.
moduleAdefmethod1()endendclassBprotecteddefmethod2()endendclassC<BincludeAdefmethod3()endendA.method_defined? :method1#=> trueC.protected_method_defined?"method1"#=> falseC.protected_method_defined?"method2"#=> trueC.protected_method_defined?"method2",true#=> trueC.protected_method_defined?"method2",false#=> falseC.method_defined?"method2"#=> true
static VALUErb_mod_protected_method_defined(int argc, VALUE *argv, VALUE mod){ return check_definition(mod, argc, argv, METHOD_VISI_PROTECTED);}
Makes a list of existing class methods public.
String arguments are converted to symbols. AnArray of Symbols and/or Strings are also accepted.
static VALUErb_mod_public_method(int argc, VALUE *argv, VALUE obj){ set_method_visibility(rb_singleton_class(obj), argc, argv, METHOD_VISI_PUBLIC); return obj;}
Makes a list of existing constants public.
VALUErb_mod_public_constant(int argc, const VALUE *argv, VALUE obj){ set_const_visibility(obj, argc, argv, CONST_PUBLIC, CONST_VISIBILITY_MASK); return obj;}
Similar toinstance_method, searches public method only.
static VALUErb_mod_public_instance_method(VALUE mod, VALUE vid){ ID id = rb_check_id(&vid); if (!id) { rb_method_name_error(mod, vid); } return mnew(mod, Qundef, id, rb_cUnboundMethod, TRUE);}
Returns a list of the public instance methods defined inmod. Ifthe optional parameter isfalse
, the methods of any ancestorsare not included.
VALUErb_class_public_instance_methods(int argc, const VALUE *argv, VALUE mod){ return class_instance_method_list(argc, argv, mod, 0, ins_methods_pub_i);}
Returnstrue
if the named public method is defined bymod. Ifinherit is set, the lookup will also searchmod's ancestors.String argumentsare converted to symbols.
moduleAdefmethod1()endendclassBprotecteddefmethod2()endendclassC<BincludeAdefmethod3()endendA.method_defined? :method1#=> trueC.public_method_defined?"method1"#=> trueC.public_method_defined?"method1",true#=> trueC.public_method_defined?"method1",false#=> trueC.public_method_defined?"method2"#=> falseC.method_defined?"method2"#=> true
static VALUErb_mod_public_method_defined(int argc, VALUE *argv, VALUE mod){ return check_definition(mod, argc, argv, METHOD_VISI_PUBLIC);}
Removes the named class variable from the receiver, returning thatvariable's value.
classExample@@var =99putsremove_class_variable(:@@var)p(defined?@@var)end
produces:
99nil
VALUErb_mod_remove_cvar(VALUE mod, VALUE name){ const ID id = id_for_var_message(mod, name, class, "wrong class variable name %1$s"); st_data_t val, n = id; if (!id) { goto not_defined; } rb_check_frozen(mod); if (RCLASS_IV_TBL(mod) && st_delete(RCLASS_IV_TBL(mod), &n, &val)) {return (VALUE)val; } if (rb_cvar_defined(mod, id)) {rb_name_err_raise("cannot remove %1$s for %2$s", mod, ID2SYM(id)); } not_defined: rb_name_err_raise("class variable %1$s not defined for %2$s", mod, name); UNREACHABLE_RETURN(Qundef);}
Removes the method identified bysymbol from the current class.For an example, see#undef_method.String arguments are converted to symbols.
static VALUErb_mod_remove_method(int argc, VALUE *argv, VALUE mod){ int i; for (i = 0; i < argc; i++) { VALUE v = argv[i]; ID id = rb_check_id(&v); if (!id) { rb_name_err_raise("method `%1$s' not defined in %2$s", mod, v); } remove_method(mod, id); } return mod;}
Returnstrue
ifmod is a singleton class orfalse
if it is an ordinary class or module.
classCendC.singleton_class?#=> falseC.singleton_class.singleton_class?#=> true
static VALUErb_mod_singleton_p(VALUE klass){ if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) return Qtrue; return Qfalse;}
Returns a string representing this module or class. For basic classes andmodules, this is the name. For singletons, we show information on the thingwe're attached to as well.
static VALUErb_mod_to_s(VALUE klass){ ID id_defined_at; VALUE refined_class, defined_at; if (FL_TEST(klass, FL_SINGLETON)) { VALUE s = rb_usascii_str_new2("#<Class:"); VALUE v = rb_ivar_get(klass, id__attached__); if (CLASS_OR_MODULE_P(v)) { rb_str_append(s, rb_inspect(v)); } else { rb_str_append(s, rb_any_to_s(v)); } rb_str_cat2(s, ">"); return s; } refined_class = rb_refinement_module_get_refined_class(klass); if (!NIL_P(refined_class)) { VALUE s = rb_usascii_str_new2("#<refinement:"); rb_str_concat(s, rb_inspect(refined_class)); rb_str_cat2(s, "@"); CONST_ID(id_defined_at, "__defined_at__"); defined_at = rb_attr_get(klass, id_defined_at); rb_str_concat(s, rb_inspect(defined_at)); rb_str_cat2(s, ">"); return s; } return rb_class_name(klass);}
Prevents the current class from responding to calls to the named method.Contrast this withremove_method
, which deletes the methodfrom the particular class; Ruby will still search superclasses and mixed-inmodules for a possible receiver.String argumentsare converted to symbols.
classParentdefhelloputs"In parent"endendclassChild<Parentdefhelloputs"In child"endendc =Child.newc.helloclassChildremove_method :hello# remove from child, still in parentendc.helloclassChildundef_method :hello# prevent any calls to 'hello'endc.hello
produces:
In childIn parentprog.rb:23: undefined method `hello' for #<Child:0x401b3bb4> (NoMethodError)
static VALUErb_mod_undef_method(int argc, VALUE *argv, VALUE mod){ int i; for (i = 0; i < argc; i++) { VALUE v = argv[i]; ID id = rb_check_id(&v); if (!id) { rb_method_name_error(mod, v); } rb_undef(mod, id); } return mod;}
When this module is included in another, Ruby callsappend_features in thismodule, passing it the receiving module inmod. Ruby's defaultimplementation is to add the constants, methods, and module variables ofthis module tomod if this module has not already been added tomod or one of its ancestors. See also#include.
static VALUErb_mod_append_features(VALUE module, VALUE include){ if (!CLASS_OR_MODULE_P(include)) { Check_Type(include, T_CLASS); } rb_include_module(include, module); return module;}
Extends the specified object by adding this module's constants andmethods (which are added as singleton methods). This is the callback methodused byObject#extend.
modulePickydefPicky.extend_object(o)ifString===oputs"Can't add Picky to a String"elseputs"Picky added to #{o.class}"superendendend(s =Array.new).extendPicky# Call Object.extend(s ="quick brown fox").extendPicky
produces:
Picky added to ArrayCan't add Picky to a String
static VALUErb_mod_extend_object(VALUE mod, VALUE obj){ rb_extend_object(obj, mod); return obj;}
The equivalent ofincluded
, but for extended modules.
moduleAdefself.extended(mod)puts"#{self} extended in #{mod}"endendmoduleEnumerableextendAend# => prints "A extended in Enumerable"
static VALUErb_obj_dummy1(VALUE _x, VALUE _y){ return rb_obj_dummy();}
Callback invoked whenever the receiver is included in another module orclass. This should be used in preference toModule.append_features
if your code wants to perform someaction when a module is included in another.
moduleAdefA.included(mod)puts"#{self} included in #{mod}"endendmoduleEnumerableincludeAend# => prints "A included in Enumerable"
static VALUErb_obj_dummy1(VALUE _x, VALUE _y){ return rb_obj_dummy();}
Invoked as a callback whenever an instance method is added to the receiver.
moduleChattydefself.method_added(method_name)puts"Adding #{method_name.inspect}"enddefself.some_class_method()enddefsome_instance_method()endend
produces:
Adding :some_instance_method
static VALUErb_obj_dummy1(VALUE _x, VALUE _y){ return rb_obj_dummy();}
Invoked as a callback whenever an instance method is removed from thereceiver.
moduleChattydefself.method_removed(method_name)puts"Removing #{method_name.inspect}"enddefself.some_class_method()enddefsome_instance_method()endclass<<selfremove_method :some_class_methodendremove_method :some_instance_methodend
produces:
Removing :some_instance_method
static VALUErb_obj_dummy1(VALUE _x, VALUE _y){ return rb_obj_dummy();}
static VALUErb_obj_dummy1(VALUE _x, VALUE _y){ return rb_obj_dummy();}
Creates module functions for the named methods. These functions may becalled with the module as a receiver, and also become available as instancemethods to classes that mix in the module.Modulefunctions are copies of the original, and so may be changed independently.The instance-method versions are made private. If used with no arguments,subsequently defined methods become module functions.String arguments are converted to symbols.
moduleModdefone"This is one"endmodule_function :oneendclassClsincludeModdefcall_oneoneendendMod.one#=> "This is one"c =Cls.newc.call_one#=> "This is one"moduleModdefone"This is the new one"endendMod.one#=> "This is one"c.call_one#=> "This is the new one"
static VALUErb_mod_modfunc(int argc, VALUE *argv, VALUE module){ int i; ID id; const rb_method_entry_t *me; if (!RB_TYPE_P(module, T_MODULE)) { rb_raise(rb_eTypeError, "module_function must be called for modules"); } if (argc == 0) { rb_scope_module_func_set(); return module; } set_method_visibility(module, argc, argv, METHOD_VISI_PRIVATE); for (i = 0; i < argc; i++) { VALUE m = module; id = rb_to_id(argv[i]); for (;;) { me = search_method(m, id, 0); if (me == 0) { me = search_method(rb_cObject, id, 0); } if (UNDEFINED_METHOD_ENTRY_P(me)) { rb_print_undef(module, id, METHOD_VISI_UNDEF); } if (me->def->type != VM_METHOD_TYPE_ZSUPER) { break; /* normal case: need not to follow 'super' link */ } m = RCLASS_SUPER(m); if (!m) break; } rb_method_entry_set(rb_singleton_class(module), id, me, METHOD_VISI_PUBLIC); } return module;}
When this module is prepended in another, Ruby callsprepend_features in thismodule, passing it the receiving module inmod. Ruby's defaultimplementation is to overlay the constants, methods, and module variablesof this module tomod if this module has not already been added tomod or one of its ancestors. See also#prepend.
static VALUErb_mod_prepend_features(VALUE module, VALUE prepend){ if (!CLASS_OR_MODULE_P(prepend)) { Check_Type(prepend, T_CLASS); } rb_prepend_module(prepend, module); return module;}
The equivalent ofincluded
, but for prepended modules.
moduleAdefself.prepended(mod)puts"#{self} prepended to #{mod}"endendmoduleEnumerableprependAend# => prints "A prepended to Enumerable"
static VALUErb_obj_dummy1(VALUE _x, VALUE _y){ return rb_obj_dummy();}
With no arguments, sets the default visibility for subsequently definedmethods to private. With arguments, sets the named methods to have privatevisibility.String arguments are converted tosymbols. AnArray of Symbols and/or Strings arealso accepted.
moduleModdefa()enddefb()endprivatedefc()endprivate :aendMod.private_instance_methods#=> [:a, :c]
Note that to show a private method on RDoc, use:doc:
.
static VALUErb_mod_private(int argc, VALUE *argv, VALUE module){ return set_visibility(argc, argv, module, METHOD_VISI_PRIVATE);}
With no arguments, sets the default visibility for subsequently definedmethods to protected. With arguments, sets the named methods to haveprotected visibility.String arguments areconverted to symbols. AnArray of Symbols and/orStrings are also accepted.
If a method has protected visibility, it is callable only whereself
of the context is the same as the method. (methoddefinition or instance_eval). This behavior is different from Java'sprotected method. Usuallyprivate
should be used.
Note that a protected method is slow because it can't use inline cache.
To show a private method on RDoc, use:doc:
instead of this.
static VALUErb_mod_protected(int argc, VALUE *argv, VALUE module){ return set_visibility(argc, argv, module, METHOD_VISI_PROTECTED);}
With no arguments, sets the default visibility for subsequently definedmethods to public. With arguments, sets the named methods to have publicvisibility.String arguments are converted tosymbols. AnArray of Symbols and/or Strings arealso accepted.
static VALUErb_mod_public(int argc, VALUE *argv, VALUE module){ return set_visibility(argc, argv, module, METHOD_VISI_PUBLIC);}
Refinemod in the receiver.
Returns a module, where refined methods are defined.
static VALUErb_mod_refine(VALUE module, VALUE klass){ VALUE refinement; ID id_refinements, id_activated_refinements, id_refined_class, id_defined_at; VALUE refinements, activated_refinements; rb_thread_t *th = GET_THREAD(); VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); if (block_handler == VM_BLOCK_HANDLER_NONE) { rb_raise(rb_eArgError, "no block given"); } if (vm_block_handler_type(block_handler) != block_handler_type_iseq) { rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine"); } ensure_class_or_module(klass); CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) { refinements = hidden_identity_hash_new(); rb_ivar_set(module, id_refinements, refinements); } CONST_ID(id_activated_refinements, "__activated_refinements__"); activated_refinements = rb_attr_get(module, id_activated_refinements); if (NIL_P(activated_refinements)) { activated_refinements = hidden_identity_hash_new(); rb_ivar_set(module, id_activated_refinements, activated_refinements); } refinement = rb_hash_lookup(refinements, klass); if (NIL_P(refinement)) { VALUE superclass = refinement_superclass(klass); refinement = rb_module_new(); RCLASS_SET_SUPER(refinement, superclass); FL_SET(refinement, RMODULE_IS_REFINEMENT); CONST_ID(id_refined_class, "__refined_class__"); rb_ivar_set(refinement, id_refined_class, klass); CONST_ID(id_defined_at, "__defined_at__"); rb_ivar_set(refinement, id_defined_at, module); rb_hash_aset(refinements, klass, refinement); add_activated_refinement(activated_refinements, klass, refinement); } rb_yield_refine_block(refinement, activated_refinements); return refinement;}
Removes the definition of the given constant, returning that constant'sprevious value. If that constant referred to a module, this will notchange that module's name and can lead to confusion.
VALUErb_mod_remove_const(VALUE mod, VALUE name){ const ID id = id_for_var(mod, name, a, constant); if (!id) { undefined_constant(mod, name); } return rb_const_remove(mod, id);}
For the given method names, marks the method as passing keywords through anormal argument splat. This should only be called on methods that acceptan argument splat (*args
) but not explicit keywords or akeyword splat. It marks the method such that if the method is called withkeyword arguments, the final hash argument is marked with a special flagsuch that if it is the final element of a normal argument splat to anothermethod call, and that method call does not include explicit keywords or akeyword splat, the final element is interpreted as keywords. In otherwords, keywords will be passed through the method to other methods.
This should only be used for methods that delegate keywords to anothermethod, and only for backwards compatibility with Ruby versions before 2.7.
This method will probably be removed at some point, as it exists only forbackwards compatibility. As it does not exist in Ruby versions before 2.7,check that the module responds to this method before calling it. Also, beaware that if this method is removed, the behavior of the method willchange so that it does not pass through keywords.
moduleModdeffoo(meth,*args,&block)send(:"do_#{meth}",*args,&block)endruby2_keywords(:foo)ifrespond_to?(:ruby2_keywords,true)end
static VALUErb_mod_ruby2_keywords(int argc, VALUE *argv, VALUE module){ int i; VALUE origin_class = RCLASS_ORIGIN(module); rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS); rb_check_frozen(module); for (i = 0; i < argc; i++) { VALUE v = argv[i]; ID name = rb_check_id(&v); rb_method_entry_t *me; VALUE defined_class; if (!name) { rb_print_undef_str(module, v); } me = search_method(origin_class, name, &defined_class); if (!me && RB_TYPE_P(module, T_MODULE)) { me = search_method(rb_cObject, name, &defined_class); } if (UNDEFINED_METHOD_ENTRY_P(me) || UNDEFINED_REFINED_METHOD_P(me->def)) { rb_print_undef(module, name, METHOD_VISI_UNDEF); } if (module == defined_class || origin_class == defined_class) { switch (me->def->type) { case VM_METHOD_TYPE_ISEQ: if (me->def->body.iseq.iseqptr->body->param.flags.has_rest && !me->def->body.iseq.iseqptr->body->param.flags.has_kw && !me->def->body.iseq.iseqptr->body->param.flags.has_kwrest) { me->def->body.iseq.iseqptr->body->param.flags.ruby2_keywords = 1; rb_clear_method_cache(module, name); } else { rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name)); } break; case VM_METHOD_TYPE_BMETHOD: { VALUE procval = me->def->body.bmethod.proc; if (vm_block_handler_type(procval) == block_handler_type_proc) { procval = vm_proc_to_block_handler(VM_BH_TO_PROC(procval)); } if (vm_block_handler_type(procval) == block_handler_type_iseq) { const struct rb_captured_block *captured = VM_BH_TO_ISEQ_BLOCK(procval); const rb_iseq_t *iseq = rb_iseq_check(captured->code.iseq); if (iseq->body->param.flags.has_rest && !iseq->body->param.flags.has_kw && !iseq->body->param.flags.has_kwrest) { iseq->body->param.flags.ruby2_keywords = 1; rb_clear_method_cache(module, name); } else { rb_warn("Skipping set of ruby2_keywords flag for %s (method accepts keywords or method does not accept argument splat)", rb_id2name(name)); } return Qnil; } } /* fallthrough */ default: rb_warn("Skipping set of ruby2_keywords flag for %s (method not defined in Ruby)", rb_id2name(name)); break; } } else { rb_warn("Skipping set of ruby2_keywords flag for %s (can only set in method defining module)", rb_id2name(name)); } } return Qnil;}
Import class refinements frommodule into the current class ormodule definition.
static VALUEmod_using(VALUE self, VALUE module){ rb_control_frame_t *prev_cfp = previous_frame(GET_EC()); if (prev_frame_func()) { rb_raise(rb_eRuntimeError, "Module#using is not permitted in methods"); } if (prev_cfp && prev_cfp->self != self) { rb_raise(rb_eRuntimeError, "Module#using is not called on self"); } if (rb_block_given_p()) { ignored_block(module, "Module#"); } rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module); return self;}
This page was generated for Ruby 3.0.0
Generated with Ruby-doc Rdoc Generator 0.42.0.