Project

General

Profile

Feature #14133

Module#{define|alias|undef}_method should be made public

Added by marcandre (Marc-Andre Lafortune) 9 months ago. Updated 9 months ago.

Status:
Closed
Priority:
Normal
Target version:
-
[ruby-core:83901]

Description

Modules and classes can be reopened and changed (unless frozen).

This is used in many meta programming techniques.

Currently, define_method is private, so we need to either do a class_eval, reopen the class somehow, or resort to :send.

As I previously stated in #6539, I feel that the use of send should be reserved for incorrect usage of actually private methods that might change of interface or aren't meant to be called this way (e.g. respond_to_missing?, puts)

Matz has stated before that "class/module operations should be done in the scope.". Nevertheless, common usage shows that there are many cases where Rubyists prefer using a single line for this, even if it means having to call send.

Here are 95k+ examples of send :define_method in the wild:
https://github.com/search?utf8=%E2%9C%93&q=language%3Aruby+%22send+%3Adefine_method%22&type=Code

Note that many of these are very bad usage of define_method. I feel this shows that even beginner programmers will use :send if privacy gets in the way. Let's not hinder advanced users in a failed attempt to protect the beginners.

Rails has good examples of use of send :define_method like https://github.com/rails/rails/blob/master/actionview/lib/action_view/lookup_context.rb#L27
That's despite the fact for most metaprogramming they don't use define_method and instead build a string of code and do a module_eval for both performance and ease debugging (see the next lines in the example). That's not possible when the new methods must access blocks though, like in the example given.

alias_method and undef_method can be seen as special cases of define_method and should have the same privacy.
55k+ examples of send :alias_method in the wild:
https://github.com/search?utf8=%E2%9C%93&q=language%3Aruby+%22send+%3Aalias_method%22&type=Code
30k+ examples of send :undef_method in the wild:
https://github.com/search?utf8=%E2%9C%93&q=language%3Aruby+%22send+%3Aundef_method%22&type=Code
20k+ examples of send :remove_method in the wild:
https://github.com/search?utf8=%E2%9C%93&q=language%3Aruby+%22send+%3Aundef_method%22&type=Code


Related issues

Related to Ruby trunk - Feature #14132: Module#attr{|_reader|_writer} should be publicClosed
Related to Ruby trunk - Feature #6539: public and private for core methodsClosed

Associated revisions

Revision 0c03a89e
Added by marcandre (Marc-Andre Lafortune) 9 months ago

Make Module#{define|alias|undef|remove}_method public [#14133]

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@60942 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 60942
Added by marcandre (Marc-Andre Lafortune) 9 months ago

Make Module#{define|alias|undef|remove}_method public [#14133]

Revision 60942
Added by marcandre (Marc-Andre Lafortune) 9 months ago

Make Module#{define|alias|undef|remove}_method public [#14133]

Revision ac1193d3
Added by tenderlove 24 days ago

Remove obsolete comment from Module#define_method documentation

Since 2.5, Module#define_method is public. (feature #14133)

Co-Authored-By: Miguel Landaeta miguel@miguel.cc

git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@64057 b2dd03c8-39d4-4d8f-98ff-823fe69b080e

Revision 64057
Added by tenderlovemaking (Aaron Patterson) 24 days ago

Remove obsolete comment from Module#define_method documentation

Since 2.5, Module#define_method is public. (feature #14133)

Co-Authored-By: Miguel Landaeta miguel@miguel.cc

History

#1 Updated by marcandre (Marc-Andre Lafortune) 9 months ago

  • Related to Feature #14132: Module#attr{|_reader|_writer} should be public added

#2 Updated by marcandre (Marc-Andre Lafortune) 9 months ago

  • Related to Feature #6539: public and private for core methods added

#3 [ruby-core:83913] Updated by shevegen (Robert A. Heiler) 9 months ago

Note that many of these are very bad usage of define_method. I feel
this shows that even beginner programmers will use :send if privacy
gets in the way. Let's not hinder advanced users in a failed attempt
to protect the beginners.

.send() is simply awesome. It's a basic OOP way - you send your message
to the object, which will have a look as to what to do, without any
fuzz.

The rails code looks very alien to me and not very pretty. A lot of
the metaprogramming makes the code hard to read IMO.

I think that people use .send() because it is so much simpler than
the alternatives. One could then also say that the alternatives may
be too complex or complicated. Lots of eval-methods and it is not
always easy to infer which eval method is now the right one or how
to use it.

Some weird code usage is out there too:

https://github.com/thangit93/yii2/blob/4802d9e0ef7281b50e793e0d3cf7aee3b238d22f/cookbooks/iis/libraries/matcher.rb#L8

self.class.send(:define_method, "#{action}_iis_app", proc do |app_name|

To your suggestion itself, I have nothing against it, but I guess
matz has to decide; and perhaps this may have to be for ruby 3.x
rather than the ruby 2.x branch.

#4 [ruby-core:83947] Updated by matz (Yukihiro Matsumoto) 9 months ago

OK, I understand. They will be public in 2.5

Matz.

#5 [ruby-core:83978] Updated by marcandre (Marc-Andre Lafortune) 9 months ago

  • Status changed from Open to Closed

Great, thank you!

Done.

Also available in: Atom PDF