ruby-core@ruby-lang.org archive (unofficial mirror)
 help / color / mirror / Atom feed
* [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods
@ 2022-10-23  3:01 jonathanhefner (Jonathan Hefner)
  2022-10-23  3:02 ` [ruby-core:110484] " jonathanhefner (Jonathan Hefner)
                   ` (4 more replies)
  0 siblings, 5 replies; 6+ messages in thread
From: jonathanhefner (Jonathan Hefner) @ 2022-10-23  3:01 UTC (permalink / raw)
  To: ruby-core

Issue #19079 has been reported by jonathanhefner (Jonathan Hefner).

----------------------------------------
Bug #19079: Modules included in a DelegateClass cannot override delegate methods
https://bugs.ruby-lang.org/issues/19079

* Author: jonathanhefner (Jonathan Hefner)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.1.2p20
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Because `DelegateClass` defines delegate methods on the class itself, those delegate methods come first in the method lookup chain.  This prevents included modules from overriding delegate methods:

  ```ruby
  Base = Class.new do
    def foo
      "base"
    end
  end

  Helper = Module.new do
    def foo
      "helper"
    end
  end

  WithHelper = DelegateClass(Base) { include Helper }

  WithHelper.new(Base.new).foo
  # => "base"
  ```

One possible solution would be to define the delegate methods in a separate module.  That way, other modules could come before it in the method lookup chain.



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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:110484] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods
  2022-10-23  3:01 [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods jonathanhefner (Jonathan Hefner)
@ 2022-10-23  3:02 ` jonathanhefner (Jonathan Hefner)
  2022-12-01  5:11 ` [ruby-core:111104] " matz (Yukihiro Matsumoto)
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: jonathanhefner (Jonathan Hefner) @ 2022-10-23  3:02 UTC (permalink / raw)
  To: ruby-core

Issue #19079 has been updated by jonathanhefner (Jonathan Hefner).


I have submitted a PR with the proposed solution: https://github.com/ruby/delegate/pull/14.

----------------------------------------
Bug #19079: Modules included in a DelegateClass cannot override delegate methods
https://bugs.ruby-lang.org/issues/19079#change-99804

* Author: jonathanhefner (Jonathan Hefner)
* Status: Open
* Priority: Normal
* ruby -v: ruby 3.1.2p20
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Because `DelegateClass` defines delegate methods on the class itself, those delegate methods come first in the method lookup chain.  This prevents included modules from overriding delegate methods:

  ```ruby
  Base = Class.new do
    def foo
      "base"
    end
  end

  Helper = Module.new do
    def foo
      "helper"
    end
  end

  WithHelper = DelegateClass(Base) { include Helper }

  WithHelper.new(Base.new).foo
  # => "base"
  ```

One possible solution would be to define the delegate methods in a separate module.  That way, other modules could come before it in the method lookup chain.



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

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:111104] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods
  2022-10-23  3:01 [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods jonathanhefner (Jonathan Hefner)
  2022-10-23  3:02 ` [ruby-core:110484] " jonathanhefner (Jonathan Hefner)
@ 2022-12-01  5:11 ` matz (Yukihiro Matsumoto)
  2022-12-01 12:38 ` [ruby-core:111126] " matz (Yukihiro Matsumoto)
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 6+ messages in thread
From: matz (Yukihiro Matsumoto) @ 2022-12-01  5:11 UTC (permalink / raw)
  To: ruby-core

Issue #19079 has been updated by matz (Yukihiro Matsumoto).

Status changed from Open to Rejected

The `DelegateClass` defines an anonymous class and defines forwarding methods to the class.  The reported (so-called) issue is a natural consequence of the above behavior. `include` add methods defined in a module **above** the current class, so forwarding methods have higher precedence. If you (re)define a method, it overwrites the forwarding method.

My opinion is that your assumption is wrong, so we don't need to fix. If you think we need to implement your assumption, you need to persuade us with the real world use-case.

Matz.


----------------------------------------
Bug #19079: Modules included in a DelegateClass cannot override delegate methods
https://bugs.ruby-lang.org/issues/19079#change-100371

* Author: jonathanhefner (Jonathan Hefner)
* Status: Rejected
* Priority: Normal
* ruby -v: ruby 3.1.2p20
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Because `DelegateClass` defines delegate methods on the class itself, those delegate methods come first in the method lookup chain.  This prevents included modules from overriding delegate methods:

  ```ruby
  Base = Class.new do
    def foo
      "base"
    end
  end

  Helper = Module.new do
    def foo
      "helper"
    end
  end

  WithHelper = DelegateClass(Base) { include Helper }

  WithHelper.new(Base.new).foo
  # => "base"
  ```

One possible solution would be to define the delegate methods in a separate module.  That way, other modules could come before it in the method lookup chain.



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:111126] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods
  2022-10-23  3:01 [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods jonathanhefner (Jonathan Hefner)
  2022-10-23  3:02 ` [ruby-core:110484] " jonathanhefner (Jonathan Hefner)
  2022-12-01  5:11 ` [ruby-core:111104] " matz (Yukihiro Matsumoto)
@ 2022-12-01 12:38 ` matz (Yukihiro Matsumoto)
  2022-12-01 14:57 ` [ruby-core:111129] " Hanmac (Hans Mackowiak)
  2022-12-01 17:19 ` [ruby-core:111132] " jonathanhefner (Jonathan Hefner)
  4 siblings, 0 replies; 6+ messages in thread
From: matz (Yukihiro Matsumoto) @ 2022-12-01 12:38 UTC (permalink / raw)
  To: ruby-core

Issue #19079 has been updated by matz (Yukihiro Matsumoto).


If you want to include a module to a delegated class, try the following:

```ruby
class WithHelper<DelegateClass(Base)
  include Helper
end
```

Matz.


----------------------------------------
Bug #19079: Modules included in a DelegateClass cannot override delegate methods
https://bugs.ruby-lang.org/issues/19079#change-100404

* Author: jonathanhefner (Jonathan Hefner)
* Status: Rejected
* Priority: Normal
* ruby -v: ruby 3.1.2p20
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Because `DelegateClass` defines delegate methods on the class itself, those delegate methods come first in the method lookup chain.  This prevents included modules from overriding delegate methods:

  ```ruby
  Base = Class.new do
    def foo
      "base"
    end
  end

  Helper = Module.new do
    def foo
      "helper"
    end
  end

  WithHelper = DelegateClass(Base) { include Helper }

  WithHelper.new(Base.new).foo
  # => "base"
  ```

One possible solution would be to define the delegate methods in a separate module.  That way, other modules could come before it in the method lookup chain.



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:111129] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods
  2022-10-23  3:01 [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods jonathanhefner (Jonathan Hefner)
                   ` (2 preceding siblings ...)
  2022-12-01 12:38 ` [ruby-core:111126] " matz (Yukihiro Matsumoto)
@ 2022-12-01 14:57 ` Hanmac (Hans Mackowiak)
  2022-12-01 17:19 ` [ruby-core:111132] " jonathanhefner (Jonathan Hefner)
  4 siblings, 0 replies; 6+ messages in thread
From: Hanmac (Hans Mackowiak) @ 2022-12-01 14:57 UTC (permalink / raw)
  To: ruby-core

Issue #19079 has been updated by Hanmac (Hans Mackowiak).


you can also try prepend instead of include:

```ruby
WithHelper = DelegateClass(Base) { prepend Helper }
```

----------------------------------------
Bug #19079: Modules included in a DelegateClass cannot override delegate methods
https://bugs.ruby-lang.org/issues/19079#change-100407

* Author: jonathanhefner (Jonathan Hefner)
* Status: Rejected
* Priority: Normal
* ruby -v: ruby 3.1.2p20
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Because `DelegateClass` defines delegate methods on the class itself, those delegate methods come first in the method lookup chain.  This prevents included modules from overriding delegate methods:

  ```ruby
  Base = Class.new do
    def foo
      "base"
    end
  end

  Helper = Module.new do
    def foo
      "helper"
    end
  end

  WithHelper = DelegateClass(Base) { include Helper }

  WithHelper.new(Base.new).foo
  # => "base"
  ```

One possible solution would be to define the delegate methods in a separate module.  That way, other modules could come before it in the method lookup chain.



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

* [ruby-core:111132] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods
  2022-10-23  3:01 [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods jonathanhefner (Jonathan Hefner)
                   ` (3 preceding siblings ...)
  2022-12-01 14:57 ` [ruby-core:111129] " Hanmac (Hans Mackowiak)
@ 2022-12-01 17:19 ` jonathanhefner (Jonathan Hefner)
  4 siblings, 0 replies; 6+ messages in thread
From: jonathanhefner (Jonathan Hefner) @ 2022-12-01 17:19 UTC (permalink / raw)
  To: ruby-core

Issue #19079 has been updated by jonathanhefner (Jonathan Hefner).


This issue occurred for a private module in Rails: https://github.com/rails/rails/pull/46189#discussion_r991440668.

Using `include` in a subclass works.  Using `prepend` also works, and is the workaround I used for the Rails module.

However, my proposed solution for this issue (https://github.com/ruby/delegate/pull/14) also solves #19079 with a performance improvement.

I opened this issue and #19079 because the current behavior seemed surprising to me.  In particular, I expected the `DelegateClass` block to behave just like a `Class.new` block.  I feel like that is a reasonable assumption based on [the documentation](https://github.com/ruby/delegate/blob/2e1272cadbf86a02a0084d03e336368556f0259e/lib/delegate.rb#L365-L369).

But, if my assumption is wrong, then I understand the decision.


----------------------------------------
Bug #19079: Modules included in a DelegateClass cannot override delegate methods
https://bugs.ruby-lang.org/issues/19079#change-100411

* Author: jonathanhefner (Jonathan Hefner)
* Status: Rejected
* Priority: Normal
* ruby -v: ruby 3.1.2p20
* Backport: 2.7: UNKNOWN, 3.0: UNKNOWN, 3.1: UNKNOWN
----------------------------------------
Because `DelegateClass` defines delegate methods on the class itself, those delegate methods come first in the method lookup chain.  This prevents included modules from overriding delegate methods:

  ```ruby
  Base = Class.new do
    def foo
      "base"
    end
  end

  Helper = Module.new do
    def foo
      "helper"
    end
  end

  WithHelper = DelegateClass(Base) { include Helper }

  WithHelper.new(Base.new).foo
  # => "base"
  ```

One possible solution would be to define the delegate methods in a separate module.  That way, other modules could come before it in the method lookup chain.



-- 
https://bugs.ruby-lang.org/
 ______________________________________________
 ruby-core mailing list -- ruby-core@ml.ruby-lang.org
 To unsubscribe send an email to ruby-core-leave@ml.ruby-lang.org
 ruby-core info -- https://ml.ruby-lang.org/mailman3/postorius/lists/ruby-core.ml.ruby-lang.org/

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2022-12-01 17:19 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-10-23  3:01 [ruby-core:110483] [Ruby master Bug#19079] Modules included in a DelegateClass cannot override delegate methods jonathanhefner (Jonathan Hefner)
2022-10-23  3:02 ` [ruby-core:110484] " jonathanhefner (Jonathan Hefner)
2022-12-01  5:11 ` [ruby-core:111104] " matz (Yukihiro Matsumoto)
2022-12-01 12:38 ` [ruby-core:111126] " matz (Yukihiro Matsumoto)
2022-12-01 14:57 ` [ruby-core:111129] " Hanmac (Hans Mackowiak)
2022-12-01 17:19 ` [ruby-core:111132] " jonathanhefner (Jonathan Hefner)

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).