How to use Ruby Module? - ruby

The following code works fine:
class Float
def round
self.format.to_f
end
def format
"%.2f" % self
end
end
However, it seems bad practice to monkeypatch a class like Float because other people are doing the same thing and it causes problems.
Then I installed simplecov and the problem started: simplecov monkeypatches the same methods.
So I created a module and mixed it in to Float.
module MyModule
def round
self.format.to_f
end
def format
"%.2f" % self
end
end
Which I guess works as well. But the problem is that simplecov seems to be overwriting the mixed-in method above.
So, what is the proper way to extend built-in classes so that they do not conflict with other people's code?
Ruby 1.9.3

Why not use just argument on the round call?
13.6657.round(2) # => 13.67
But if you are sure you need module (to possibly adjust the format for all Floats out there, I'd propose you just define format method as such:
module MyModule
def format
("%.2f" % self).to_f
end
end
And mix this in to Float.
And later in code you call the format method instead of round:
13.6657.format # => 13.67
This way it does not hurt the core functionality (as your initial code dropped the argument from the round definition).
Even better - if you want (can) pinpoint the monkey-patching, simply extend specific instance:
a = 13.6657
a.extend MyModule
a.format # => 13.67
This way it wont mess with other Floats, but you can still adjust the format without finding all calls to a.round(2) in your code.

Related

How to override Ruby + method?

Just for learning purpose I am trying to override the Ruby + method, but I am not getting the desired output.
class Integer
def +(my_num)
"Plus method overridden"
end
end
puts 5.+(9)
Please let me know what I am doing wrong here.
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
The Ruby Language Specification allows Integer to have implementation-specific subclasses. See Section 15.2.8.1, lines 27-33.
It looks like your implementation does have such subclasses. In that case, the + method may be overridden in a subclass.
My best guess is that you have an implementation which distinguishes between Fixnums and Bignums, and that our Integer#+ gets overridden by Fixnum#+.
By the way, even if what you were trying to do were working, it wouldn't be overriding, it would be overwriting.
Also note that if what you were trying to do were working, you would have most likely broken your Ruby process, since Integers are fundamental and widely-used all over the place in Ruby.

Get list of classes and methods that call a specific global method

I have a method called $muffinize and I would like to find where it can be found in my code. In other words, given the following code:
class A
def foo
$muffinize(1)
end
def bar
...
end
end
class B
def shoop
$muffinize(2)
end
def woop
...
end
end
class C
def nope
...
end
end
I would like to the result to be (written to a file):
A:foo
B:shoop
I was thinking of accomplishing this with a Regex, but I was wondering if there would be some way of accomplishing this with Ruby meta-programming (which I might be accidentally using as a buzz-word)?
Kernel.caller() will help you show the line number and method that is calling it at runtime. If you put something like puts caller(1,1) in your muffinize function it will output those locations, but only if they are called at runtime.
If you want to do offline source analysis, you need to parse the AST (abstract syntax tree) with something like https://github.com/whitequark/parser.
Here is a quick example with ripper (built into new rubies) - this isn't strictly an AST but it's not extracting classes either
#!/usr/local/env ruby
require 'ripper'
#require 'pry'
contents = File.open('example.rb').read
code = Ripper.lex(contents)
code.each do |line|
if(line[1] == :on_ident and line[2] == "muffinize")
puts "muffinize found at line #{line.first.first}"
end
end
Ignoring the fact that your code isn't even syntactically valid, this is simply not possible.
Here's a simple example:
class A
def foo
bar
muffinize(1)
end
end
A#foo will call Object#muffinize if and only if bar terminates. Which means that figuring out whether or not A#foo calls Object#muffinize requires to solve the Halting Problem.
By getting a list of classes and methods via ri, I was then able to analyze each method to retreive their source code using the method_source gem and then searching for muffinize. This does not rule out the possibility of muffinize from appearing in a comment or a string, but I consider the likelihood of this happening to be small enough to ignore.

Is there a short way to write `{|x| x}`?

We often shorten a block using the & notation on a symbol like this:
some_array.group_by(&:foo)
Is there a similar way to shorten expressions like {|x| x}?
some_array.group_by{|x| x}
If there were a method Object#self that returns self, then we can do
some_array.group_by(&:self)
but unfortunately, there is no such method. In terms of the number of characters, it may be longer, but readability improves.
Yes. #itself was implemented in Ruby 2.2.0.
You can access the Ruby core team discussion about this feature here.
As an interesting analogue, the #ergo method has been proposed, which would yield the receiver to a given block.
If you haven't yet upgraded to Ruby 2.2.0, you may wish to backport #itself and/or define #ergo as follows:
class Object
def itself; self end
def ergo
fail ArgumentError, "Block expected!" unless block_given?
yield self
end
end
And then:
some_array.group_by &:itself
Well, there's no built-in as far as I know, but you can make a reusable identity block:
id = Proc.new {|x| x}
some_array.group_by(&id)
And then if you really wish this were a language feature:
class Object
def it
Proc.new {|x| x}
end
end
And then you can do:
some_array.group_by(&it)
wherever you like. This may void your warranty.
Yes! The method Kernel#itself was added in Ruby 2.2.0. This method simply returns the object it was called on, so you can write:
some_array.group_by(&:itself)
You can see the extensive discussion of this feature here: https://bugs.ruby-lang.org/issues/6373. The patch was submitted by Rafael França in message #53. You can see it in the official Ruby source by looking in object.c.
If you are using a version of Ruby older than 2.2.0, you can easily add Kernel#itself into your project by putting this code somewhere in your project and making sure it gets required:
module Kernel
def itself
self
end
end if !Kernel.instance_methods.include?(:itself)
However, monkey-patching a part of the Ruby core like that can be dangerous and I would not recommend it if you are making reusable code, like a gem. Instead I would recommend just making your own identity function, as suggested by user2246674:
module MyLibrary
IDENT = Proc.new { |x| x }
array.group_by(&IDENT)
end

What's the difference between these Ruby namespace conventions?

So Module can be used in Ruby to provide namespacing in addition to mixins, as so:
module SomeNamespace
class Animal
end
end
animal = SomeNamespace::Animal.new
But I've also seen the following used:
module SomeNamespace
end
class SomeNamespace::Animal
end
animal = SomeNamespace::Animal.new
My question is how they're different (if they are) and which is more idiomatic Ruby?
The difference lies in nesting.
In the example below, you can see that the former method using class Foo, can get the outer scope's constant variables BAR_A without errors.
Meanwhile, class Baz will bomb with an error of uninitialized constant A::B::Baz::BAR_A. As it doesn't bring in A::* implicitly, only A::B::*explicitly.
module A
BAR_A = 'Bar A!'
module B
BAR_B = 'Bar B!'
class Foo
p BAR_A
p BAR_B
end
end
end
class A::B::Baz
p BAR_A
p BAR_B
end
Both behaviors have their place. There's no real consensus in the community in my opinion as to which is the One True Ruby Way (tm). I personally use the former, most of the time.
The only difference between the two approaches is that the second one will throw uninitialized constant Object::SomeNamespace if the namespace hasn't previously been declared.
When declared in a single file, I would opt for the first one because you don't have to repeat SomeNamespace.
When using multiple files I also use the second one, to avoid running into the following problem:
# in a.rb
require 'b'
module SomeNamespace
def self.animal
Animal.new
end
end
# in b.rb
class SomeNamespace::Animal
end
# irb
require 'a' # explodes with the uninitialized constant error
This example may be contrived, but it's easy to trigger it if your code base is a little bit bigger. I usually use the explicit way (your first one) to avoid this.
One thing that may be helpful when using the second form is that it will detect typos in the namespace.
There doesn't seem to be an established way to create namespaces, Devise for example mixes both approaches: first one, second one.

Truncate #inspect output in irb (ruby)

I want to truncate #inspect output in irb (a large output must be cropped to MAX_LEN).
Currently, I override :inspect, :to_s methods for all specific objects.
Is there are other solution?
change $stdout ?
other?
For a clean solution, gem install hirb. hirb pages irb's returned values if they get too long.
If you want to monkeypatch irb:
module IRB
class Irb
def output_value
#context.last_value.to_s.slice(0, MAX_LEN)
end
end
end
I don't recommend this because it's a hack and breaks any time gems like ap and hirb are required.
Instead of monkeypatching irb, I'd recommend trying ripl, an irb alternative that is meant to extended.
The above as a ripl plugin would be:
require 'ripl'
module Ripl::SlicedInspect
def format_result(result)
result_prompt + result.inspect.slice(MAX_LEN)
end
end
Ripl::Shell.send :include, Ripl::SlicedInspect
With this plugin, you could require it as needed or add to your ~/.riplrc if you want to always use it.
Your solution is good.
It involves no dark magic, which might make the code less understandable and error-prone.
If you're just in IRB - you could define a monkeypatch in irb itself and or load a file that monkeypatches inspect via 'load'. This way you keep it out of your core codebase but you still get the functionality you need w/o having to override inspect in every class you wish to inspect....
If it's because you have a nested hash or something that's hard to decipher, try awesome_print. You can make it the default output formatter in irb by placing the following in your .irbrc:
require 'ap'
module IRB
class Irb
def output_value
ap #context.last_value
end
end
end
This makes objects with lots of data easy to decipher in IRB.
Even if you don't use awesome_print, you can truncate output using this same technique so you don't have to override to_s in your code.
For rails 3.1.1+, place the code below in helpers/irb_helper.rb
module IRB
class Irb
MAX_LEN = 10000
def output_value
if (#context.inspect_last_value.length > MAX_LEN)
printf #context.return_format, "#{#context.inspect_last_value[0..MAX_LEN]} <- Truncated"
else
printf #context.return_format, #context.inspect_last_value
end
end
end
end
If you'd like to customize your output more, check irb's source at https://github.com/Ruby/Ruby/blob/trunk/lib/irb.rb
I sometimes modify the objects themselves (via a module called BoringInspect which I include into the relevant classes) so that exception messages are also manageable.

Resources