Suppose I've got a section of Ruby code where I'd like to alias a method (I don't know why; let's just suppose I have a good reason).
class String
alias_method :contains?, :include?
end
Would it be possible for me, after this section, to remove this alias?
remove_method should work in most cases. But if your alias_method overwrites an existing method, you may need to save the original via a separate alias_method call.
# assuming :contains? is already a method
alias_method :original_contains?, :contains?
alias_method :contains?, :include?
Then to restore the original state:
alias_method :contains?, :original_contains?
remove_method :original_contains? # optional
Note also that modifying a class that's used in multiple threads is prone to race conditions. And if you're trying to disallow libs from using the alias, you can't prevent that if you're calling those libs' methods while the alias exists. We might see a way to do this in ruby 2.0: http://yehudakatz.com/2010/11/30/ruby-2-0-refinements-in-practice/
It would be helpful if you could say why you want to remove the alias. If the method name did not exist before, no other libs should be affected by your monkey-patch. Also, you should consider subclassing String (or delegating to a string instance) rather than patching String.
def hello
puts "Hello World"
end
alias :hi :hello
hi #=> "Hello World"
undef hi
hi #=> NameError
hello #=> "Hello World"
EDIT: Note that this will only work on methods created on the main object. In order to enact this on a class, you'd need to do something like , Hello.class_eval("undef hi")
However, from a metaprogramming standpoint, when dealing with classes, I like the usage of remove_method :hi since it'll cause the method lookup to fall down and grab the method from a parent class.
class Nums < Array
def include?
puts "Just Kidding"
end
end
n = Nums.new
n << 4 #=> [4]
n.include? #=> "Just kidding"
Nums.class_eval("remove_method :include?")
n.include? 4 #=> true
Number.class_eval("undef include?")
n.include? 4 #=> NoMethodError
remove_method is much more meta friendly.
Related
Define a class as follows. I want to call one_method dynamically. By default, wow.one_method calls the first one_method. If I want to change the behavior of the method, just call redefine.
I can implement the method as a function type property, but that is not what I want.
If I use the following code directly, it would report errors. Could you modify it slightly.
class Wow
def one_method
puts "hello Ruby"
end
def redefine(what="none")
define_method :one_method do
puts what
end
end
end
wow = Wow.new
wow.redefine("Whatever I want.")
You can achieve that via class_eval or instance_eval:
class Wow
def one_method
puts "hello Ruby"
end
def redefine(what="none")
self.class.class_eval do
define_method :one_method do
puts what
end
end
end
end
wow = Wow.new
wow.one_method #=> hello Ruby
wow.redefine("Whatever I want.")
wow.one_method #=> Whatever I want.
Reason is that define_method defines instance method on the receiver and is a class's instance method so you'll have to call it on the eigen class of the object that you want to redefine a method on.
I would recommend achieving your goal in a more canonical way, just redefine the method on the instance itself:
class Wow
def one
:one
end
end
w = Wow.new
w.one
#=> :one
def w.one
:two
end
w.one
#=> :two
Drawbacks are:
your methods lookup table caches will be dropped
the code is becoming more obscure and hard to debug
Alternatives:
I don't know your real problem, but for your particular question it is better to parameterize your one_method method just to receive an argument for puts. Also, you can pass a block, so you will receive more grained control over the behavior.
Just want to enquire what the right practice is.
My preference is to use procs, simply because I think that defining methods inside of methhods is a bit untidy and should be done only when necessary. To get around it, I simply use procs.
What is the right / better way to do it and why? (apart from the proc's ability to access the main method's variables defined before itself)
def meth( params_prime )
calculations = do_something_with_whatever
def sub_meth( params_sub )
do_something_with_params_sub
end
sub_meth_params(calculations) # is this better?
proc1 = proc{ |params_sub| do_something_with_params_sub }
proc1.call(calculations) # or is this?
end
It is not clear what your specific use-case is, but I would definitely go for procs or lambdas. There is less overhead when defining a proc or lambda dynamically, they are passable, so if needed you could return them and they could be used outside the function.
Using "def" exposes the method as an instance method outside of the current method scope (so in the containing class, which could be Object in your case). This may or may not be with you want. If you want to use an anonymous function only available in the local scope, use a lambda.
Also Proc vs Lambda: I generally prefer to use lambdas since they behave a little more "predictable", meaning: as you would expect (check passed variables, and return just returns from the lambda, proc returns from the called scope). But from your example it is hard to deduce what would apply. I think the key-difference is: lambas are ment to be passed around, and thus behave a little more sanely. If this is not your use-case, use Proc :) (a write-up of the difference).
If you want to use sub_func to encapsulate it from call from other methods you can use a class to group function and sub_func together and make sub_func private. Otherwise if you want to pass this function as a parameter further you can declare it as lamda.
def func params_prime
sub_func = ->(params_sub){do_something_with_params}
sub_func.call(params_prime)
end
Defining methods inside methods is a feature of Ruby that may have its use. But something is telling me that you are asking a very advanced question while you are still a beginner level Rubyist. Do you know what default definee is? If not, check this article by Yugui.
Procs are very important in Ruby, but newbies tend to use them instead of defining methods in appropriate objects, which is the exact smell I'm getting from your question. The normal way of doing things in OO languages of Ruby family is to define methods on objects:
class Foo
def bar *params
# do something with params
end
end
Since you do not understand the meaning of defining methods inside methods, refrain from doing it for the next 6 months. Once you understand objects, you can start experimenting with this very advanced feature again.
APPENDIX:
Since you demonstrated intrest, let me show you that using def in def at the top level is a frownable-upon thing to do. Normally, when you define a method on some class without further adornment, it becomes a public instance method of that class:
class X
def foo; "foo" end
end
X.instance_methods.include? :foo
#=> true
When you use def in a def, the definee for the inner def is going to be X:
class X
def bar
def baz
"baz"
end
"bar"
end
end
When you execute the above code, instance method #bar becomes defined on X:
X.instance_methods.include? :bar
#=> true
But #baz not yet:
X.instance_methods.include? :baz
#=> false
Only after you call #bar at least once does the method become defined on X:
X.new.bar
#=> "bar"
X.instance_methods.include? :baz
#=> true
And now I would like to ask you to appreciate how terrible thing just happened: An instance just modified its mother class. That's a violation. A violation of such a basic principle of OO design, that I'm not even sure it has a name. This technique is great for obfuscated coding competitions, but in production, it's taboo. Ruby gives you the freedom to break that taboo, gives you the rope to hang yourself on, but you don't do it under any kind of normal circumstances.
So what can be worse than a def inside a def in a class definition? The answer is, a def inside a def at the top level. Let me show you why. Normally, when you define methods with def at the top level, the default definee is Object, but the top level defnitions become private instance methods of object. This is to prevent the unintended consequence of top level defs, because almost all Ruby objects inherit from Object. For example, if you define:
class Object
def foo; "foo" end
end
Now all your objects will respond to foo:
foo #=> "foo"
1.foo #=> "foo"
[].foo #=> "foo
When we define methods at the top level, we usually just intend to use the method at the top level, and don't want every single object to inherit it. For that reason, top level defs become private:
hello #=> NameError: undefined local variable or method `hello' for main:Object
1.hello #=> NoMethodError: undifined method 'hello' for 1:Fixnum
Now we use def at the top level:
def hello; "hello" end
We can see that method #hello is has not become an instance methods of Object:
Object.instance_methods.include? :hello
#=> false
Mysteriously, it became its private method:
Object.private_instance_methods.include? :hello
#=> true
This way, we avoid the unintended consequence of defining #hello method for every single object. But the inheritance is there. The error message has changed:
1.hello #=> NoMethodError: private method 'hello' called for 1:Fixnum
And we can forcibly call the method via #send:
1.send :hello
#=> "hello"
Mysteriously, at the top level, we are allowed to call this private method without #send:
hello
#=> "hello"
And now, what happens when you do def in def at the top level:
def bar
def baz; "baz" end
"bar"
end
You define a private instance method Object#bar in an expected way. But when you call it, alas, the top level magic no longer works and a public method Object#baz gets defined:
bar #=> "bar"
This way, not just the top level, but every single Ruby object got polluted with your #baz method:
1.baz #=> "baz"
Class.baz #=> "baz"
This is why I told you to refrain from using this idiom until you progress from the level of unconscious incompetence to the level of conscious incompetence. I recommend you to read more about top level methods in Ruby.
I know I can do the following, and it's just 3 lines:
class << self
alias :generate :new
end
But out of curiosity, is there a simpler way (without semicolons) like:
class_alias :generate, :new
Since Ruby 1.9 you can use the singleton_class method to access the singleton object of a class. This way you can also access the alias_method method. The method itself is private so you need to invoke it with send. Here is your one liner:
singleton_class.send(:alias_method, :generate, :new)
Keep in mind though, that alias will not work here.
I am pasting some alias method examples
class Test
def simple_method
puts "I am inside 'simple_method' method"
end
def parameter_instance_method(param1)
puts param1
end
def self.class_simple_method
puts "I am inside 'class_simple_method'"
end
def self.parameter_class_method(arg)
puts arg
end
alias_method :simple_method_new, :simple_method
alias_method :parameter_instance_method_new, :parameter_instance_method
singleton_class.send(:alias_method, :class_simple_method_new, :class_simple_method)
singleton_class.send(:alias_method, :parameter_class_method_new, :parameter_class_method)
end
Test.new.simple_method_new
Test.new.parameter_instance_method_new("I am parameter_instance_method")
Test.class_simple_method_new
Test.parameter_class_method_new(" I am parameter_class_method")
OUTPUT
I am inside 'simple_method' method
I am parameter_instance_method
I am inside 'class_simple_method'
I am parameter_class_method
I don't believe there is any class-specific version of alias. I usually use it as you have previously demonstrated.
However you may want to investigate the difference between alias and alias_method. This is one of those tricky areas of ruby that can be a bit counter-intuitive. In particular the behavior of alias with regard to descendants is probably not what you expect.
Hope this helps!
as far as I understand 'send' method, this
some_object.some_method("im an argument")
is same as this
some_object.send :some_method, "im an argument"
So what is the point using 'send' method?
It can come in handy if you don't know in advance the name of the method, when you're doing metaprogramming for example, you can have the name of the method in a variable and pass it to the send method.
It can also be used to call private methods, although this particular usage is not considered to be a good practice by most Ruby developers.
class Test
private
def my_private_method
puts "Yay"
end
end
t = Test.new
t.my_private_method # Error
t.send :my_private_method #Ok
You can use public_send though to only be able to call public methods.
In addition to Intrepidd's use cases, it is convenient when you want to route different methods on the same receiver and/or arguments. If you have some_object, and want to do different things on it depending on what foo is, then without send, you need to write like:
case foo
when blah_blah then some_object.do_this(*some_arguments)
when whatever then some_object.do_that(*some_arguments)
...
end
but if you have send, you can write
next_method =
case foo
when blah_blah then :do_this
when whatever then :do_that
....
end
some_object.send(next_method, *some_arguments)
or
some_object.send(
case foo
when blah_blah then :do_this
when whatever then :do_that
....
end,
*some_arguments
)
or by using a hash, even this:
NextMethod = {blah_blah: :do_this, whatever: :do_that, ...}
some_object.send(NextMethod[:foo], *some_arguments)
In addition to everyone else's answers, a good use case would be for iterating through methods that contain an incrementing digit.
class Something
def attribute_0
"foo"
end
def attribute_1
"bar"
end
def attribute_2
"baz"
end
end
thing = Something.new
3.times do |x|
puts thing.send("attribute_#{x}")
end
#=> foo
# bar
# baz
This may seem trivial, but it's occasionally helped me keep my Rails code and templates DRY. It's a very specific case, but I think it's a valid one.
The summing briefly up what was already said by colleagues: send method is a syntax sugar for meta-programming. The example below demonstrates the case when native calls to methods are likely impossible:
class Validator
def name
'Mozart'
end
def location
'Salzburg'
end
end
v = Validator.new
'%name% was born in %location%'.gsub (/%(?<mthd>\w+)%/) do
# v.send :"#{Regexp.last_match[:mthd]}"
v.send Regexp.last_match[:mthd].to_sym
end
=> "Mozart was born in Salzburg"
I like this costruction
Object.get_const("Foo").send(:bar)
Sometimes you can see:
do_this do
available_method1 "arg1"
available_method2 "arg1"
end
When I use the block from do_this method then I get some methods I could use inside that block.
I wonder how this is accomplished? How does the code look like behind the scenes?
I want to be able to provide some methods through a block.
It's called a Domain-Specific Language (DSL). Here's (Last archived version) some great info on various forms of Ruby DSL blocks.
There are really two ways to go about doing this, with different syntaxes:
do_thing do |thing| # with a block parameter
thing.foo :bar
thing.baz :wibble
end
# versus
do_thing do # with block-specific methods
foo :bar
baz :wibble
end
The first is more explicit and less likely to fail, while the second is more concise.
The first can be implemented like so, by simply passing a new instance as the block parameter with yield:
class MyThing
def self.create
yield new
end
def foo(stuff)
puts "doing foo with #{stuff}"
end
end
MyThing.create do |thing|
thing.foo :bar
end
And the second, which runs the block in the context of the new object, giving it access to self, instance variables, and methods:
class MyThing
def self.create(&block)
new.instance_eval &block
end
def foo(stuff)
puts "doing foo with #{stuff}"
end
end
MyThing.create do
foo :bar
end
And if you really want to do it without calling MyThing.create, just:
def create_thing(&block)
MyThing.create &block
end
This is usually done using instance_eval to change the value of self inside the block to be some different object, which then handles those method calls.
As a quick example:
class ExampleReceiver
def available_method1 arg ; p [:available_method1, arg] ; end
def available_method2 arg ; p [:available_method2, arg] ; end
end
def do_this(&blk) ; ExampleReceiver.new.instance_eval(&blk) ; end
do_this do
available_method1 "arg1" #=> [:available_method1, "arg1"]
available_method2 "arg1" #=> [:available_method2, "arg1"]
end
Though this is a powerful language feature, and has been used before to great effect, there is still some debate on whether it's a good idea or not. If you don't know what's going on, you might be surprised that the value of #some_instance_variable changes inside and outside the block, since it's relative to the current value of self.
See Daniel Azuma's excellent article for more discussion and details.