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!
Related
I apologize up front. I'm going to struggle articulating this question.
TL;DR - I have an object I'm using to call a method in the subclass. That method needs access to a method in a parent class (forcing inheritance...read below). I'm thinking this won't work because I'm instantiating the subclass, so the inheritance won't work right, but I'm not sure. I'm still seeking out documentation. Basically, the method in the parent class is not "seen" the way I'm doing this - NoMethodError is the exception.
I prefer DRY code, as most people do. I usually use compositing in lieu of inheritance in my code, but I think I'm at a point where if I want to keep this DRY, I have to use inheritance (though I could be wrong, so I'm open to suggestions), and so I'm trying it out, which leads me to this question.
Given the following Ruby "pseudo" code or example to kind of demonstrate what I'm trying to accomplish:
module SomeModule
class ParentClass
def initialize
end
def method_i_want_to_use(arg1, *args)
# does all the things
end
def self.method_i_want_to_use(arg1, *args)
arg = args.first unless args.empty?
self.class.method_i_want_to_use(arg1, arg)
end
end
end
And then in a different file, same module
module SomeModule
class SubClass < ParentClass
def initialize
end
# this isn't working
def my_other_method
# things get done and then
method_i_want_to_use(arg1, args) ## <<=== fails
end
end
end
Yet in another file
module SomeModule
class Thing
def initialize
#my_obj = SubClass.new
end
def my_method
#my_obj.my_other_method
end
end
end
So one important thing I missed. The method method_i_want_to_use is a method that is used all over the place in my code. It just so happens that in this one class, inheritance was NOT originally used because this class is basically atomic with the exception of this one method. So my problem is either I copy the method into this class and use it (but that kinda breaks the DRY principle sorta) or I find a way to share this method between classes.
This gets into OOP design pretty heavily and I am aware of that. One could ask: well, is the inheritance as it currently sits even relevant to the objects in question? Yes...and no. They can be. In short, principally, it works, but frankly, I don't like it. TBH, I almost prefer to just copy the method into the "subclass" and remove the inheritance and be done with it, but DRY -- unless I'm going a little too wild with DRY in this context and I kinda think I am.
Anyway, just curious what folks with more knowledge than I have for me on this. This really is the first time I've dabbled this deeply into inheritance. :)
I'd love pointers on how I can keep from implementing
There are two different methods here:
an instance method:
def method_i_want_to_use(arg1, *args)
# does all the things
end
and a class method:
def self.method_i_want_to_use(arg1, *args)
arg = args.first unless args.empty?
self.class.method_i_want_to_use(arg1, arg)
end
but what you probably want in this case is
def self.method_i_want_to_use(arg1, *args)
arg = args.first unless args.empty?
self.new.method_i_want_to_use(arg1, arg)
end
There are a few choices and it depends on what method_i_want_to_use is doing. Is it a separate thing? Then you can call it as a class method ParentClass.method_i_want_to_use inside the SubClass without inheritance.
Another way is to define it in a module and include it
include ModuleX
# and then in your code
method_i_want_to_use(...)
I'd use inheritance if you want to have some kind of common abstraction layer and you expect multiple subclasses to behave the same way. If the classes/objects that need to use method_i_want_to_use have different behaviours then inheritance is not the correct choice. Let's say you have a class that send a request to a 3rd party API and you have a class that does saves records to your db. For some reason you need to use the same piece of code (a method) in both cases, maybe to calculate some value. Using inheritance to include the method would be a mistake, because both classes have different behaviours.
Hope that helps.
After fixing some of the syntax errors and changing the call self.class.method_i_want_to_use to self.new.method_i_want_to_use as Adam also mentioned in his answer, this code seems to work fine.
I did not get any undefined methods until I tried to call SomeModule::ParentClass.method_i_want_to_use(3,4) and that was fixed by the change from class to new. Are you sure your undefined method error was not related to that?
module SomeModule
class ParentClass
def initialize
end
def method_i_want_to_use(arg1, *args)
# does all the things
puts "here #{arg1} , #{args}"
end
def self.method_i_want_to_use(arg1, *args)
arg = args.first unless args.empty?
self.new.method_i_want_to_use(arg1, arg)
end
end
end
module SomeModule
class SubClass < ParentClass
def initialize
end
# this isn't working
def my_other_method(arg1, arg2)
# things get done and then
method_i_want_to_use(arg1, arg2) ## <<=== fails
end
end
end
module SomeModule
class Thing
def initialize
#my_obj = SubClass.new
end
def my_method(arg1,arg2)
#my_obj.my_other_method(arg1, arg2)
end
end
end
SomeModule::Thing.new.my_method(1,2)
SomeModule::ParentClass.method_i_want_to_use(3,4)
prints:
here 1 , [2]
here 3 , [4]
I have this piece of code here:
class MyFile
attr_accessor :byte_content
alias_method :read, :byte_content
alias_method :write, :byte_content=
end
On the class MyFile there is an alias_method, but I do not understand how this method is working. Does it change the way the getter and setter for :byte_content are called?
Also, what is the difference between this method and just using alias? When should I one over the other?
Thanks in advance for your time!
This:
attr_accessor :byte_content
Essentially does:
def byte_content
#byte_content
end
def byte_content=(value)
#byte_content = value
end
Then
alias_method :read, :byte_content
alias_method :write, :byte_content=
will create copies of the byte_content and byte_content= methods with read and write as the new names . If you modify the byte_content or byte_content= methods after the aliasing, the read and write will remain unchanged.
So, the intention of the alias_method in the example appears to be to give the user a more "File-like" interface. Without the method aliases, you would use:
file = MyFile.new
file.byte_content = "abcd"
puts file.byte_content
With the aliases, the user can use:
file = MyFile.new
file.write("abcd")
file.read
Which is quite similar to the methods of the standard library File class,
file = File.open('/tmp/foo.txt', 'w')
file.write('hello')
file.rewind
puts file.read
And this makes it possible to use instances of MyFile in place of real File instances in some very simple use-cases, also known as Duck-typing.
alias vs alias_method
The differences of alias and alias_method are described in the answers to this question, most imporantly:
you can override alias_method but not alias
alias_method is used with symbols as the method names, making it useful for dynamically created methods
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)
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.
I found a blog post on alias vs. alias_method. As shown in the example given in that blog post, I simply want to alias a method to another within the same class. Which should I use? I always see alias used, but someone told me alias_method is better.
Usage of alias
class User
def full_name
puts "Johnnie Walker"
end
alias name full_name
end
User.new.name #=>Johnnie Walker
Usage of alias_method
class User
def full_name
puts "Johnnie Walker"
end
alias_method :name, :full_name
end
User.new.name #=>Johnnie Walker
Blog post link here
alias_method can be redefined if need be. (it's defined in the Module class.)
alias's behavior changes depending on its scope and can be quite unpredictable at times.
Verdict: Use alias_method - it gives you a ton more flexibility.
Usage:
def foo
"foo"
end
alias_method :baz, :foo
Apart from the syntax, the main difference is in the scoping:
# scoping with alias_method
class User
def full_name
puts "Johnnie Walker"
end
def self.add_rename
alias_method :name, :full_name
end
end
class Developer < User
def full_name
puts "Geeky geek"
end
add_rename
end
Developer.new.name #=> 'Geeky geek'
In the above case method “name” picks the method “full_name” defined in “Developer” class. Now lets try with alias.
class User
def full_name
puts "Johnnie Walker"
end
def self.add_rename
alias name full_name
end
end
class Developer < User
def full_name
puts "Geeky geek"
end
add_rename
end
Developer.new.name #=> 'Johnnie Walker'
With the usage of alias the method “name” is not able to pick the method “full_name” defined in Developer.
This is because alias is a keyword and it is lexically scoped. It means it treats self as the value of self at the time the source code was read . In contrast alias_method treats self as the value determined at the run time.
Source: http://blog.bigbinary.com/2012/01/08/alias-vs-alias-method.html
A point in favor of alias instead of alias_method is that its semantic is recognized by rdoc, leading to neat cross references in the generated documentation, while rdoc completely ignore alias_method.
I think there is an unwritten rule (something like a convention) that says to use 'alias' just for registering a method-name alias, means if you like to give the user of your code one method with more than one name:
class Engine
def start
#code goes here
end
alias run start
end
If you need to extend your code, use the ruby meta alternative.
class Engine
def start
puts "start me"
end
end
Engine.new.start() # => start me
Engine.class_eval do
unless method_defined?(:run)
alias_method :run, :start
define_method(:start) do
puts "'before' extension"
run()
puts "'after' extension"
end
end
end
Engine.new.start
# => 'before' extension
# => start me
# => 'after' extension
Engine.new.run # => start me
A year after asking the question comes a new article on the subject:
http://erniemiller.org/2014/10/23/in-defense-of-alias/
It seems that "so many men, so many minds." From the former article author encourages to use alias_method, while the latter suggests using alias.
However there's a common overview of these methods in both blogposts and answers above:
use alias when you want to limit aliasing to the scope where it's defined
use alias_method to allow inherited classes to access it
The rubocop gem contributors propose in their Ruby Style Guide:
Prefer alias when aliasing methods in lexical class scope as the
resolution of self in this context is also lexical, and it
communicates clearly to the user that the indirection of your alias
will not be altered at runtime or by any subclass unless made
explicit.
class Westerner
def first_name
#names.first
end
alias given_name first_name
end
Always use alias_method when aliasing methods of modules, classes, or
singleton classes at runtime, as the lexical scope of alias leads to
unpredictability in these cases
module Mononymous
def self.included(other)
other.class_eval { alias_method :full_name, :given_name }
end
end
class Sting < Westerner
include Mononymous
end
alias_method new_method, old_method
old_method will be declared in a class or module which is being inherited now to our class where new_method will be used.
these can be variable or method both.
Suppose Class_1 has old_method, and Class_2 and Class_3 both of them inherit Class_1.
If, initialization of Class_2 and Class_3 is done in Class_1 then both can have different name in Class_2 and Class_3 and its usage.