How to cancel evaluating a required Ruby file? (a.k.a. top-level return)
UPDATE:
A "top-level return" feature has been added.
ORIGINAL:
Commenter matt pointed out that Feature 4840, which would do exactly what I'm asking about, has been in discussion since June 2011. Further, the feature was still being discussed as late as November 2015 in core team meetings regarding new Ruby features.
There are a lot of difficulties involved in designing a feature like this; for a list of the pros and cons, I highly suggest checking out the discussions.
The proposed feature would allow exiting the required file while using any of the the following top-level statements:
if condition
return
end
while condition
# ...
return
end
begin
# ...
return
rescue
# ...
return
ensure
# ...
return
end
And it would not exit the required file in the following statements:
class Foo
return # LocalJumpError
end
def foo
return # returns from method, not from required file
end
proc do
return # LocalJumpError
end
x = -> { return } # returns as from lambda, not from required file
Since the feature remains unimplemented, I have awarded the bounty to steenslag for successfully solving the problem (as originally written) to the letter, if not the spirit.
How to skip require in ruby?
i have rescued LoadError but i want that if LoadError is executed., further code should not be executed. In the example given, the rake task db:import_to_heroku should not be called
Then do:
begin
require 'aws-sdk'
namespace :db do
desc "import local postgres database to heroku. user and database name is hardcoded"
task :import_to_heroku => [:environment, "db:dump_for_heroku"] do
# code using aws-sdk gem
end
end
rescue LoadError
puts "aws-sdk gem not found"
end
Can I conditionally skip loading further ruby code in the same file?
I haven't checked the source, but I suppose that, when you run ruby my_file.rb
at the console, or require/load
it from Ruby code, the file is read entirely into memory before being evaluated. I'm afraid there is no such thing as skipping a part of a file.
I had an idea with catch/throw.
requiring file (for example a Rake task ?) treq1.rb :
catch :aws_sdk do
require_relative 'original'
end
puts '... continued'
The original file that you don't want to modify, original.rb :
puts 'in original, not to be modified'
begin
require 'aws-sdk'
rescue LoadError
puts "aws-sdk gem not found"
throw :aws_sdk
end
puts ">>> to execute only if 'aws-sdk' is found"
# namespace :db do ... etc
#end
Execution :
$ ruby -w treq1.rb
in original, not to be modified
aws-sdk gem not found
treq1.rb:2:in `require_relative': method `backtrace' called on unexpected T_NODE object (0x007fd32b88e900 flags=0x381c klass=0x0) (NotImplementedError)
from treq1.rb:2:in `block in <main>'
from treq1.rb:1:in `catch'
from treq1.rb:1:in `<main>'
Googling with the error : http://www.ruby-forum.com/topic/4406870
Recent post, no answer. It works in a single file, if you want to wrap your code.
Let's try another solution. Supposing that you can change the Rake task, treq2.rb :
begin
require_relative 'original'
rescue LocalJumpError
puts 'rescued LocalJumpError'
end
puts '... continued'
In original.rb, replace throw :aws_sdk
by return
:
$ ruby -w treq2.rb
in original, not to be modified
aws-sdk gem not found
rescued LocalJumpError
... continued
This way it works.
HTH
Does ruby stop evaluating if statements when first condition is false?
Ruby, and most other programming languages use short circuiting boolean expressions. Meaning any expression of the form false && puts("hi")
will not run the right side of the expression puts("hi")
. This goes for if
conditions as well, anything with &&
really.
This is specially important to know because you always want to put faster or cheaper expressions/functions on the left side and more expensive expressions on the right side of a &&
operator.
Consider this
puts "hi" if expensive_method() && some_value
In the above example expensive_method
will always run. But what if some_value
is sometimes false? This would be more efficient:
puts "hi" if some_value && expensive_method()
Taking advantage of the possibility that some_value
might sometimes be false, we spare ourselves from having to evaluate expensive_method
in those cases.
In short, take advantage of boolean expression short circuiting.
https://en.wikipedia.org/wiki/Short-circuit_evaluation
How to Evaluate code of another ruby file?
You can use Kernel#eval
in order to achieve what you want.
but in code1.rb
you will need to remove puts
, or place it before, as puts
returns nil.
So use this changes
code1.rb
a = 10
b = 15
c = a+b
puts "c = #{c}"
c
code2.rb
code1 = File.open('code1.rb', 'r').read
c = eval(code1)
a = 10
e = c*5+a
puts "e = #{e}"
c = eval(code1)
This magic line will use return value of your code1.rb
file and then we can use it in code2.rb
Or another alternative you can allow your local variables to be overwritten by eval
method, but in that case you need to define them in your code2.rb
. Consider this
code2.rb
a,b,c = [0, 0, 0]
code1 = File.open('code1.rb', 'r').read
eval(code1)
a = 10
e = c*5+a
puts "e = #{e}"
That works due to local variables scope and evaluation. Both variants are working solutions
Does the || operator evaluate the second argument even if the first argument is true?
This happens because the ruby interpreter defines a variable when it sees an assignment to it (but before it executes the actual line of code). You can read more about it in this answer.
Boolean OR (||
) expression will evaluate to the value of left hand expression if it is not nil
and not false
, else ||
will evaluate to the value of right hand expression.
In your example the ruby interpreter sees an assignment to a
and rr
(but it doesn't execute this line yet), and initializes (defines, creates) a
and rr
with nil
. Then it executes the ||
expression. In this ||
expression, a
is assigned to 10
and 10
is returned. r=20
is not evaluated, and rr
is not changed (it is still nil
). This is why in the next line rr
is nil
.
FILE__ returns different value when using binding.pry
Use _file_
instead of __FILE__
. For example, given two files:
# foo.rb
require 'pry'
require './bar'
binding.pry
b = Bar.new
and:
# bar.rb
require 'pry'
class Bar
def initialize
binding.pry
end
end
Run them with ruby foo.rb
:
ruby foo.rb
From: /Users/username/foo.rb @ line 3 :
1: require 'pry'
2: require './bar'
=> 3: binding.pry
4: b = Bar.new
(main):1 ⇒ _file_
=> "/Users/username/foo.rb"
(main):2 ⇒ exit
From: /Users/username/bar.rb @ line 4 Bar#initialize:
3: def initialize
=> 4: binding.pry
5: end
(#<Bar:0x00007fbb6caaff08>):1 ⇒ _file_
=> "/Users/username/bar.rb"
_file_
and any other local variable names can be found in binding.local_variables
.
How to stop the Rails debugger for the current request
Just put conditions on the debugger statement so that it stops only when you want it to, e.g.:
debugger if animal == 'tiger'
or if, say, you want to examine the code only on loop 384:
animals.each_with_index do |animal, i|
debugger if i == 384
# do something
end
or put in a variable that will let you continue ad hoc:
continue_debugger = false
animals.each do |animal|
debugger unless continue_debugger
# in the debugger type `p continue_debugger = true` then `c` when done
end
Related Topics
Using Poltergeist with a Proxy
Ruby on Rails - £ Sign Troubles
Return Values Were Not Extracted in Ruby
Rubymine 6.0.2, Unable to Debug
Kaminari Undefined Method 'Total_Pages'
Permanently Switching User in Capistrano 3 (Separate Authorization & Deploy)
Ruby 1.9 - No Such File to Load 'Win32/Open3'
Iterate Through Array of Hashes in Ruby
Getting Rails to Accept European Date Format (Dd/Mm/Yyyy)
How to Download File from Google Drive API with Service Account
Trouble on Eager Loading "Second Degree" Associated Objects
Ruby: Length of a Line of a File in Bytes
How to Print All the Staged File Names Using Ruby Git Pre-Commit Hook
How to Link to a Page with Page.Url Without the HTML Extension in Jekyll