Ruby: Overriding the Puts Method

Ruby: overriding the puts method

def puts(o)
if o.is_a? Array
super(o.to_s)
else
super(o)
end
end

puts [1,2,3] # => [1, 2, 3]

or just use p:

p [1, 2, 3] # => [1, 2, 3] 

Is there a way to redefine a method within a block?

On second thoughts, here's a better answer:

def always_upcase_strings(&block)
anon_class = Class.new do
def puts(str)
super(str.upcase)
end
end
anon_class.new.instance_eval(&block)
end

always_upcase_strings do
puts "abc" #=> "ABC"
puts "def" #=> "DEF"
puts "ghi" #=> "GHI"
end

puts "xyz" #=> "xyz"

This creates a temporary class (anonymous, because it has no need for a name) with the desired method override.

The yielded block is then invoked, within the context of this class instance.

As well as being less confusing than my "redefine-undefine-redefine the method" solution, this approach has the added advantage that it's thread-safe. So you won't get weird behaviour if, for example, running parallel tests whilst invoking the method.

...But I still stand by my original statement that redefining methods within a block is super surprising behaviour. Coworkers probably won't like you for choosing that design pattern (unless it's done in a limited manner, and for good reason!)

How to override Ruby + method?

It seems you use ruby < 2.4. If so you want to patch Fixnum and not Integer. Be careful as the system itself uses numbers as well.

class Fixnum
alias_method :add, :+

def +(other)
puts 'plus method overridden'
add(other)
end
end

puts 5 + 9

how to monkey patch the puts method in ruby

You could override the puts method like so:

def puts(object)
super('')
super(object)
super('')
end

If you really wanted to you could monkey patch the method like below. Although your changes would probably have unintended effects.

module Kernel
def puts(object)
# code
end
end

You can read about monkey patching in the Ruby docs here.

Overriding to_s method in ruby

def to_s
"I am a hi man"
end

You need to return the value, not output it.

Add functionality to a method by overriding, but still call original method

alias :old_fake_method :fake_method
def fake_method(cmd)
if (cmd) == "bla"
puts "caught cmd"
else
old_fake_method(cmd)
end
end

Is it possible to override a built-in Ruby method outside of a class or module?

The easiest way would be to split the string in a number and word, and sort by an Array of minus number (to get decreasing numbers) and word :

arr = ['2 xxx', '20 axxx', '2 m', '38 xxxx', '20 bx', '8540 xxxxxx', '2 z']

arr.sort_by! do |number_word|
number, word = number_word.split
[ -number.to_i, word ]
end

puts arr
# =>
# 8540 xxxxxx
# 38 xxxx
# 20 axxx
# 20 bx
# 2 m
# 2 xxx
# 2 z

When sorting arrays, the first element (-number) has priority. If both first elements are the same, the sort uses the second element (word).

ruby - override method and then revert

Another way to do that, without creating an extra method, is this:

class Foo
def bar
:old_method
end
end

Foo.new.bar # => :old_method

$old_method = Foo.new.method(:bar)

class Foo
def bar
:new_method
end
end

Foo.new.bar # => :new_method

class Foo
define_method($old_method.name, &$old_method)
end

Foo.new.bar # => :old_method

I think that this is better than using an alias method. In Ruby methods are, also, objects. I just take the reference of the object before destructing the association of the object (the method) with the class. After I add the same method. It also works if you use the undef keyword to remove the method from the class. The bad point is that you have to have an object of the class to take the reference of the method.

Overriding a method with a getter in Ruby

attr_reader :action_label is just defining a method. "getters" in Ruby are just methods like this

def action_label
@action_label
end

attr_reader is shorthand for defining such a method.

There is nothing wrong with redefining a method in a subclass, that's one of the big features of OOP.

Also that is not what NotImplementedError is for. Raise something else.



Related Topics



Leave a reply



Submit