Reputation: 45943
I would like to refactor this code:
class Logger
class << self
def info title, msg
puts hash_for(title, msg, :info ).to_json
end
def unknown title, msg
puts hash_for(title, msg, :unknown).to_json
end
Into something like:
def print title, msg, level
puts hash_for(title, msg, level).to_json
end
alias :info, :print
alias :unknown, :print
But I need to inject the argument, which alias
and alias_method
do not appear to support.
Ruby 2.3
Upvotes: 0
Views: 1393
Reputation: 436
You can do this with meta programming!
class Logger
def self.define_printer(level)
define_singleton_method(level) do |title, msg|
print(title, msg, level)
end
end
def self.print(title, msg, level)
puts hash_for(title, msg, level).to_json
end
define_printer :info
define_printer :unknown
end
Logger.info('foo', 'bar')
# calls print with ["foo", "bar", :info]
Edit: For extra credit, I made a more general version.
class Object
def curry_singleton(new_name, old_name, *curried_args)
define_singleton_method(new_name) do |*moreArgs|
send(old_name, *curried_args.concat(moreArgs))
end
end
end
class Foobar
def self.two_arg_method(arg1, arg2)
p [arg1, arg2]
end
curry_singleton(:one_arg_method, :two_arg_method, 'first argument')
end
Foobar.one_arg_method('second argument')
#=> ["first argument", "second argument"]
Upvotes: 2
Reputation: 1352
alias
is a built in and won't support a parameter, in fact alias info print
without colons or commas is syntactically correct. But alias_method
should work. The following worked for me:
class G
def print
puts 'print'
end
a = :print
b = :info
alias_method b, a
end
G.new.info
Upvotes: 0
Reputation: 9692
As far as I know neither alias
nor alias_method
support arguments.
You could define the methods explicitly like this:
def print(title, msg, level)
puts hash_for(title, msg, level).to_json
end
def info(*args)
print(*args)
end
# More concise...
def unknown(*args); print(*args); end
Upvotes: 0