Feature #9704
open
Updated by matz (Yukihiro Matsumoto) about 11 years ago
So your key idea is sharing implementation between monkey-ing and refinements.
The motivation behind introducing refinements is discouraging monkey-ing. So it is not attractive for me to something that helps monkey-ing.
What is your intention behind the proposal? Maybe from monkey-ing to refinements transition?
Matz.
Updated by trans (Thomas Sawyer) about 11 years ago
Yes, the transition from monkey-ing to refinements is a major part of the intention.
But I also do not expect monkey-ing to ever completely go away. (Do you?) Monkey ing is more convenient, in that it can be done via one require for an entire project, where as refining has to specified per-file. So there will be cases where monkey-ing is still preferred.
Besides personal projects and small end-user tools, a good example, I think, is ActiveSupport. While some of it could be used as refinements, I suspect much of it will remain core extensions b/c it represents Rails' DSL, so to speak. And the parts that can become refinements, I would imagine users would still have an option to load them in as extensions.
Even so, I think the main intent is to ask the question: Do refinements need to be modules? If there is no compelling reason for them to be so, then making refinements file-based would simplify reuse and allow us to shed unnecessary boiler-plate.
Updated by trans (Thomas Sawyer) about 11 years ago
Just FYI, I created this project https://.com/rubyworks/reusing. I don't much care for what I had to do to implement it, i.e.
- it's not possible to simply override
#using
- had to use my finder gem to find libraries
- had to use clunky gsub and eval
But it appears to be working.
Updated by trans (Thomas Sawyer) about 11 years ago
I realized there is a downside to this approach.
# a.rb
require 'b'
class String
def ab
self + "a" + b
end
end
# b.rb
class String
def b
self + "b"
end
end
So what would happen with b.rb
when using 'a'
? Should the require 'b'
become a using
? If so, then what happens when it requires something that is not an extension, e.g. set
?
If that is an unsolvable issue. The only fix, it seems, would be a way to have something like require_or_using
which would act according to the initial loading method used. And that starts to look pretty ugly.
Updated by shugo (Shugo Maeda) about 11 years ago
Monkey-ing style has another problem that super cannot be supported in monkey ing.
I prefer another approach to extend classes both globally and locally in the same manner.
How about to provide a way to activate refinements globally?
using Foo, global: true
Refinements in Foo are activated globally.¶
Module#refine creates a module as a refinement, so it can be globally activated by Module#prepend-ing that module to the target class.
Updated by trans (Thomas Sawyer) about 11 years ago
Ah, attack the problem from the other way round. That's a great idea!
Updated by trans (Thomas Sawyer) almost 9 years ago
Has any more thought been given to this? I had a recent request to have Ruby Facets to work as refinements, but I hesitate b/c it literally means creating a second copy of every extension method.
Updated by shugo (Shugo Maeda) almost 9 years ago
- Assignee set to matz (Yukihiro Matsumoto)
Thomas Sawyer wrote:
Has any more thought been given to this? I had a recent request to have Ruby Facets to work as refinements, but I hesitate b/c it literally means creating a second copy of every extension method.
What do you think of the following idea, Matz?
Monkey-ing style has another problem that super cannot be supported in monkey ing.
I prefer another approach to extend classes both globally and locally in the same manner.
How about to provide a way to activate refinements globally?using Foo, global: true # Refinements in Foo are activated globally.
Module#refine creates a module as a refinement, so it can be globally activated by Module#prepend-ing that module to the target class.
Updated by pabloh (Pablo Herrero) almost 9 years ago
It would be interesting to be able apply a refinement to a whole app (without its gems) or inside a single gem without propagating to the rest of the app which loaded it.
Although I'm not really sure about the syntax or API to do it.
Updated by shugo (Shugo Maeda) almost 9 years ago
- Related to : Module#defined_refinements added
Updated by trans (Thomas Sawyer) over 8 years ago
Shugo Maeda wrote:
Monkey-ing style has another problem that super cannot be supported in monkey ing.
I prefer another approach to extend classes both globally and locally in the same manner.
How about to provide a way to activate refinements globally?using Foo, global: true
Refinements in Foo are activated globally.¶
Module#refine creates a module as a refinement, so it can be globally activated by Module#prepend-ing that module to the target class.
That last line just clicked with me, and I see old problem. This only works at one level. How would one write a refinement that adds methods to class level and instance level at the same time?
Updated by hsbt (Hiroshi SHIBATA) about 1 year ago
- Status changed from Open to Assigned