Issue #12697 has been updated by Marc-Andre Lafortune.


Hi,

As stated by bughit, a typical case where we have to resort to `send` for these is in meta programming, say:

    def self.included(base)
      base.send(:define_method, :foo) { ... } unless base.column_names.include?(:foo)
    end

Yukihiro Matsumoto wrote:
> I still believe
> 
> ```
> class String
>   include Term::ANSIColor
> end
> ```
> 
> is far better than `String.include Term::ANSIColor`. It is clearer and has more space to optimize.

I respect your opinion. Please realize that not everybody agree with this though. I feel that `String.include Term::ANSIColor` is clearer as it does one and one thing only. It's a single atomic operation. The `class ...` form, for me, means "Reopen the class", followed by "include ANSIColor", followed by "ok, that's actually all we wanted to do for this class".

The same way some people will prefer

    if some_condition
      do_this_single_thing
    end

I usually prefer

    do_this_single_thing if some_condition

Typical scenario of a gem: define modules in `lib/my_gem/...`, then in `lib/my_gem.rb`:

    require_relative 'lib/...'

    String.include MyGem::StringExtension
    SomethingElse.extend MyGem::Something

That is my preference over

    require_relative 'lib/...'

    class String
      include MyGem::StringExtension
    end

    class SomethingElse
      extend MyGem::Something
    end

Here are some actual examples of other people that feel this way, from a quick github search:

https://github.com/edgecase/authorize_me/blob/4a1ccf42b2d89a53cafbc0cb4ace236b57ba12ea/rails/init.rb
https://github.com/redradiant/centsible/blob/e4cc35ee1ccb8b1e66992bc18a9b7a26643affe4/vendor/bundle/ruby/1.9.1/gems/recaptcha-0.2.3/lib/recaptcha/merb.rb
https://github.com/nbino/eegloo/blob/a51e6ba77616bc4dd84c76bd0bf07f7ada3a7bd7/vendor/plugins/paginating_find/init.rb
https://github.com/mailserv/mailserv/blob/36b9ff211ba71df0b77aa9de2f6382f60787151b/admin/vendor/plugins/spawn/init.rb
etc.

The search returns over 2.6 million hits (but that includes a lot of duplicates): https://github.com/search?utf8=%E2%9C%93&q=send+include+language%3Aruby+&type=Code&ref=searchresults

> Besides that the fact that `include` etc may have huge performance penalty is also a reason to prohibit casual class/module modification.

I'm afraid I don't see this; I feel that if a programmer is calling `include`, then it is because `include` is needed. It will be called no matter what. I doubt this prevented a single misuse of `include`!

> Is there any reason to allow this in addition to saving extra few keystrokes?

As I stated in my original request, I feel that calling `send` is what should be discouraged, not `include`. Using `public_send` is fine, but needing to use `send` means:
- I'm doing something I shouldn't be doing
- I'm calling a method that was not intended for me to call
- this might break or have unintended consequences, now or in the future

But classes are *intended* to be augmented, to have methods defined, to have plugins included in them. We shouldn't have to use `send` to do that.

----------------------------------------
Feature #12697: Why shouldn't Module meta programming methods be public?
https://bugs.ruby-lang.org/issues/12697#change-60290

* Author: bug hit
* Status: Feedback
* Priority: Normal
* Assignee: Yukihiro Matsumoto
----------------------------------------
Methods like alias_method, attr_accessor, define_method, and similar

I don't think Ruby discourages this kind of meta programming, so why make it less convenient, by necessitating `send` or `module_eval`?



-- 
https://bugs.ruby-lang.org/

Unsubscribe: <mailto:ruby-core-request / ruby-lang.org?subject=unsubscribe>
<http://lists.ruby-lang.org/cgi-bin/mailman/options/ruby-core>