Use cases for Ruby's EOB construct - ruby

I recently came across the Ruby EOB / -EOB construct within this context (from the Ruby id3 library) :
def initialize(...)
# ...
instance_eval <<-EOB
class << self
def parse
# ...
# Method code
# ...
end
EOB
self.parse # now we're using the just defined parsing routine
# ...
end
I understand that the code is used to generate a method on the fly, yet I would like to know if it would be possible to use the EOB snippet within a method. I would like to write a method which generates some other method code , which is to be included in yet another class. This sounds a bit confusing, I'll try to illustrate my intention with some simplified code samples :
# This class reads the code of another
# Ruby class and injects some methods
class ReadAndInject
# The method which defines another method
def get_code_to_be_injected
"\tdef self.foo\n"+
"\t\tputs 'bar'\n"+
"\tend\n"
end
# Main entry point, reads a generated Ruby Class
# and injects specific methods within it
def read_and_inject
# Assume placeholder for currently read line,
# add the generated code within
current_line += "\n#{get_code_to_be_injected}"
end
end # class ReadAndInject
This would work, since the method to be injected is added correctly. Yet I was wondering if using the EOB construct would yield some advantages (e.g. better visibility of the code, since no cumbersome tabs or string concatenations would have to be added.
To conclude, is this a good use case for EOB ?
It seems like a shady yet powerful construct, I've ducked it, googled and stackoverflow'd it yet no significant code samples other than one from RubyCocoa were returned. I've only recently started to use meta constructs in Ruby, so please be gentle :-)
Thanks in advance!

These are called "here documents", which are supported by several languages, and allow you to make a multi-line string. You can actually use any delimiter, not just EOB. Ruby has some extra features for heredocs: for example, the - in <<-EOB allows you to indent the delimiter.
You might use it like this:
def code_to_be_injected
<<-EOS
def self.foo
puts 'bar'
end
EOS
end
Some additional features in Ruby:
myvar = 42
<<EOS
variable: #{myvar}
EOS #=> "variable: 42"
<<'EOS'
variable: #{myvar}
EOS #=> "variable: #{myvar}"
print <<A, <<B
This will appear first
A
and this second
B

Related

Augmenting the methods with `alias` keyword

Having reading through The Ruby programming language I found an example of using alias keyword for augmenting the methods.
def hello # A nice simple method
puts 'Hello world' # Suppose we want to augment it...
end
alias original_hello hello # Give the method a backup name
def hello # Now we define a new method with the old name
puts "Your attention please" # That does some stuff
original_hello # Then calls the original method
puts "This has been a test" # Then does some more stuff
end
Indeed original hello preserves the old behavior even after the method the it had been referencing to was redefined.
But, to my mind, this example hardly clarifies the real benefit of this technique. Cannot the same be achieved in traditional way (e.g. by providing the block)? Then why applying this idiom? Can anyone provide an example from the real world when augmenting with alias really makes sense?
Rails code is full of those. Imagine the original hello method does not belong to your code base. Somewhere in 3rd-party library there is do_stuff(stuff) method declared on the class Stuffer.
You want to e.g. debug this method. You reopen the class, define an alias and, voilà:
class Stuffer
alias original_do_stuff do_stuff
def do_stuff(stuff)
puts stuff.inspect
original_do_stuff(stuff)
end
end
Now all the code, including original 3rd party code you might be even not aware about, would print out the parameter passed to every single call to do_stuff.
Real-life example (don’t try this at home and in the school :)
class String
alias _inspect inspect
def inspect
puts "I am a string: “#{_inspect}”"
end
end
"abc".inspect
#⇒ I am a string: “"abc"”
Can anyone provide an example from the real world when augmenting with alias really makes sense?
Not really. Today, you would do this (example taken from #mudasobwa's answer):
module WeirdInspectRefinement
module WeirdInspectExtension
def inspect
"I am a string: “#{super}”"
end
end
refine String do
prepend WeirdInspectExtension
end
end
using WeirdInspectRefinement
p 'abc'.inspect
#⇒ 'I am a string: “"abc"”'
But even before Module#prepend and Refinements existed, there was never a reason to use alias for this, which leaves unused methods around polluting the namespace, and Rails abandoned it quite a while ago:
class String
old_inspect = instance_method(:inspect)
define_method(:inspect) do
"I am a string: “#{old_inspect.bind(self).()}”"
end
end
'abc'.inspect
#⇒ 'I am a string: “"abc"”'

ruby: using blocks as normal (inline) expressions?

Looking for a little wisdom from fellow Rubyists. For a while now, I've used the following for convenience in some of my applications, and I'm wondering if there's a language feature I'm just missing:
class Object
def as_block
yield
end
end
There are other uses, but the normal case for me is a conditional assignment that requires a little non-trivial logic. Two obvious ways to do this:
# via a second method:
def foo
#foo ||= set_foo
end
# via conditional logic:
def foo
if #foo
#foo
else
# do complicated stuff
end
end
Both of these approaches seem kind of ugly: in the first case, #set_foo seems extraneous, and the second just looks kind of nasty. So, instead, I like this:
def foo
#foo ||= as_block do
# do complicated stuff
end
end
The problem here (aside from monkey patching Object) is that it's really a dependency (on the monkey patch) that looks like a language feature. That is, something like this really shouldn't be in (say) a Rails initializer---it seems like it should be in a gem, so the dependency can be managed correctly. Then I'm packaging an entire gem to run five lines of code to monkey patch Object...
So, my questions:
1. Anyone else use this, or something like it?
2. Has the Ruby team ever considered including something like this by default? It seems like a really easy way to use blocks as plain old expressions, but it's not there (as far as I know) which makes me wonder if there's some reason for not including it, or...
3. Is there already some better way of doing this that I'm just unaware of?
Thanks!
-E
What you're looking for is begin ... end. This isn't the same thing as a block or Proc, as it's not an object you can pass around or a closure which creates a new scope, but it should serve your purpose just fine:
def foo
#foo ||= begin
# do complicated stuff
end
end
You could use a lambda:
def foo
#foo ||= lambda do
# do complicated stuff
end.call
end
Note that it is important to call the lambda to actually execute the expression, ie
def foo
#foo ||= lambda do
# do complicated stuff
end
end
will return a lambda rather than your evaluated expression.

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.

How to get the name of the calling method?

is there a way in Ruby to find the calling method name inside of a method?
For example:
class Test
def self.foo
Fooz.bar
end
end
class Fooz
def self.bar
# get Test.foo or foo
end
end
puts caller[0]
or perhaps...
puts caller[0][/`.*'/][1..-2]
In Ruby 2.0.0, you can use:
caller_locations(1,1)[0].label
It's much faster than the Ruby 1.8+ solution:
caller[0][/`([^']*)'/, 1]
Will get included in backports when I get the time (or a pull request!).
Use caller_locations(1,1)[0].label (for ruby >= 2.0)
Edit: My answer was saying to use __method__ but I was wrong, it returns the current method name.
I use
caller[0][/`([^']*)'/, 1]
How about
caller[0].split("`").pop.gsub("'", "")
Much cleaner imo.
Instead you can write it as library function and make a call wherever needed. The code goes as follows :
module CallChain
def self.caller_method(depth=1)
parse_caller(caller(depth+1).first).last
end
private
# Copied from ActionMailer
def self.parse_caller(at)
if /^(.+?):(\d+)(?::in `(.*)')?/ =~ at
file = Regexp.last_match[1]
line = Regexp.last_match[2].to_i
method = Regexp.last_match[3]
[file, line, method]
end
end
end
To trigger the above module method you need to call like this:
caller = CallChain.caller_method
code reference from
In order to see the caller and callee information in any language, whether it be ruby or java or python, you would always want to look at the stack trace. In some languages, such as Rust and C++, there are options built into the compiler to turn on some sort of profiling mechanism you can view during run time. I do belive one exists for Ruby called ruby-prof.
And as mentioned above, you could look into the execution stack for ruby. This execution stack is an array containing backtrace location objects.
Essentially all you need to know about this command is as follows:
caller(start=1, length=nil) → array or nil

is it OK to use begin/end in Ruby the way I would use #region in C#?

I've recently moved from C# to Ruby, and I find myself missing the ability to make collapsible, labelled regions of code. It just occurred to me that it ought to be OK to do this sort of thing:
class Example
begin # a group of methods
def method1
..
end
def method2
..
end
end
def method3
..
end
end
...but is it actually OK to do that? Do method1 and method2 end up being the same kind of thing as method3? Or is there some Ruby idiom for doing this that I haven't seen yet?
As others have said this doesn't change the method definition.
However, if you want to label groups of methods, why not use Ruby semantics to label them? You could use modules to split your code into chunks that belong together. This is good practice for large classes, even if you don't reuse the modules. When the code grows, it will be easy to split the modules into separate files for better organisation.
class Example
module ExampleGroup
def method1
# ..
end
def method2
# ..
end
end
include ExampleGroup
def method3
# ..
end
end
Adding arbitrary Ruby code in order to please your editor doesn't seem reasonable to me at all. I think you should try to get a decent text editor, one that would be able to configure to use some keyword you put in your comments to enable code folding there, for example:
# region start AAA
some(:code, :here)
# region end AAA
And if you allow me to be sarcastic: you should know that Ruby is lot more expressive, elegant and pretty than C#, and chances are that there isn't any Ruby code ought to be hidden in the first place! ;)
I know this might be a bit old but I ran into this issue and found a killer solution. If you're using "Rubymine" you can do #regions.
This is where they talk about navigating regions
https://www.jetbrains.com/ruby/help/navigating-to-custom-region.html
#region Description
Your code goes here...
#endregion
So with the above in your code you will see the below:
Rubymine code editor - With a sample method using regions un-folded
Rubymine code editor - With a sample method using regions folded
I think it should be OK. I haven't seen it a lot though. Another way you could accomplish the same thing, while using less indentation, is to close and reopen the class, like so:
class Example
def method1
..
end
def method2
..
end
end
# optionally put some other code here
class Example
def method3
..
end
end
I think this is often used so that you can put other code in the middle, such as when there's a constant defined in the first class Example block, which is used to define a constant in the middle code, which is used to define a constant in the second class Example block. That way you never have to refer to a constant before it's defined.
Yes, it is okay to do that (i.e. it doesn't change the semantics of your code).
However this isn't a common pattern and it might be confusing to readers of your code who wouldn't understand what the purpose of the begin ... end block is.

Resources