Getting current line of code in Ruby
You can use __LINE__
variable. See this https://stackoverflow.com/a/2496240/100466 answer also.
How to get current file and line number in Ruby?
You'll have to use caller
def mylog(str)
caller_line = caller.first.split(":")[1]
puts "#{__FILE__} : #{caller_line} : #{str}"
end
You'll probably want to know the file from which mylog
was called too...
def mylog(str)
caller_infos = caller.first.split(":")
puts "#{caller_infos[0]} : #{caller_infos[1]} : #{str}"
end
How to find out from which line number the method was called in Ruby?
You can use caller_locations
which has been added recently. It returns an array of Location
objects. See http://ruby-doc.org/core-2.2.3/Thread/Backtrace/Location.html for details.
No need to parse the return of caller
. Hooray.
To add on to this caller_locations.first
or caller_locations(0)
gets the last method location, increment the parameter to pull specific steps.
Ruby CSV - get current line/row number
Because of changes in CSV in current Rubies, we need to make some changes. See farther down in the answer for the original solution with Ruby prior to 2.6. and the use of with_index
which continues to work regardless of the version.
For 2.6+ this'll work:
require 'csv'
puts RUBY_VERSION
csv_file = CSV.open('test.csv')
csv_file.each do |csv_row|
puts '%i %s' % [csv_file.lineno, csv_row]
end
csv_file.close
If I read:
Year,Make,Model,Description,Price
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1999,Chevy,"Venture ""Extended Edition, Very Large""","",5000.00
1996,Jeep,Grand Cherokee,"MUST SELL!\nair, moon roof, loaded",4799.00
The code results in this output:
2.6.3
1 ["Year", "Make", "Model", "Description", "Price"]
2 ["1997", "Ford", "E350", "ac, abs, moon", "3000.00"]
3 ["1999", "Chevy", "Venture \"Extended Edition\"", "", "4900.00"]
4 ["1999", "Chevy", "Venture \"Extended Edition, Very Large\"", "", "5000.00"]
5 ["1996", "Jeep", "Grand Cherokee", "MUST SELL!\\nair, moon roof, loaded", "4799.00"]
The change is because we have to get access to the current file handle. Previously we could use the global $.
, which always had a possibility of failure because globals can get stomped on by other sections of called code. If we have the handle of the file being opened, then we can use lineno
without that concern.
$.
Ruby prior to 2.6 would let us do this:
Ruby has a magic variable $.
which is the line number of the current file being read:
require 'csv'
CSV.foreach('test.csv') do |csv|
puts $.
end
with the code above, I get:
1
2
3
4
5
$INPUT_LINE_NUMBER
$.
is used all the time in Perl. In Ruby, it's recommended we use it the following way to avoid the "magical" side of it:
require 'english'
puts $INPUT_LINE_NUMBER
If it's necessary to deal with embedded line-ends in fields, it's easily handled by a minor modification. Assuming a CSV file "test.csv" which contains a line with an embedded new-line:
Year,Make,Model,Description,Price
1997,Ford,E350,"ac, abs, moon",3000.00
1999,Chevy,"Venture ""Extended Edition""","",4900.00
1996,Jeep,Grand Cherokee,"MUST SELL!
air, moon roof, loaded",4799.00
1999,Chevy,"Venture ""Extended Edition, Very Large""","",5000.00
with_index
Using Enumerator's with_index(1)
makes it easy to keep track of the number of times CSV yields to the block, effectively simulating using $.
but honoring CSV's work when reading the extra lines necessary to deal with the line-ends:
require 'csv'
CSV.foreach('test.csv', headers: true).with_index(1) do |row, ln|
puts '%-3d %-5s %-26s %s' % [ln, *row.values_at('Make', 'Model', 'Description')]
end
Which, when run, outputs:
$ ruby test.rb
1 Ford E350 ac, abs, moon
2 Chevy Venture "Extended Edition"
3 Jeep Grand Cherokee MUST SELL!
air, moon roof, loaded
4 Chevy Venture "Extended Edition, Very Large"
Ruby - Read file and print line number
Ruby, like Perl, has the special variable $.
which contains the line number of a file.
File.open("file.txt").each do |line|
puts line, $.
end
Prints:
#Hello
1
#My name is John Smith
2
#How are you?
3
Strip the \n
from line
if you want the number on the same line:
File.open("file.txt").each do |line|
puts "#{line.rstrip} #{$.}"
end
#Hello 1
#My name is John Smith 2
#How are you? 3
As stated in comments, rather than use File.open
you can use File.foreach with the benefit of autoclose at the end of the block:
File.foreach('file.txt') do |line|
puts line, $.
end
# same output...
Ruby script to check how many lines of code are in an application
Generally I wouldn't - I'd use a shell utility. Seriously.
Also, do you want to include comments? Etc. etc.
There's a very good answer to this, not using Ruby here: How to count all the lines of code in a directory recursively?
If I were approaching this with the intent of actually doing it I'd do this:
Dir['**/*.*'].each do |fname|
puts "#{fname} #{linecount(fname)}"
end
Linecount would be something like
def linecount(fname)
File.open(fname, "r") do |f|
return f.readlines.length
end
end
This is a nasty hack by the way, because it reads the whole file into memory just to see how long the array is, you might want to get each line and count them as you read through.
You could get rid of blanks or lines that are only comments too by only incrementing the counter.
Something like
lines = f.readlines
lines.delete_if { |l| l =~ /^[[:space:]]*#|^$/ }
return lines.length
I haven't tested that regexp by the way.
As an exercise for the reader - work out what the 'if' statement is you need to put on the end of the puts to stop it barfing on directories :D
Get the error line in a Ruby Opal code
Opal has source map support, to facilitate this kind of source level of debugging. I will not go into details about sourcemaps, but HTML5Rocks has a great article that covers the topic in depth.
Here is the minimal boilerplate to set that up with Opal:
Let index.rb
be our source file:
class Test
def initialize
end
def crash
print x
end
end
Test.new.crash
Since you would rather not use a lot of extraneous utilties, let us directly use the Opal API. Create a file builder.rb
which will compile the file above:
require 'opal'
Opal::Processor.source_map_enabled = true
Opal.append_path "."
builder = Opal::Builder.new.build('index')
# Write the output file containing a referece to sourcemap
# which we generate below : this will help the browser locate the
# sourcemap. Note that we are generating sourcemap for only code and not
# the entire Opal corelib.
#
File.binwrite "build.js", "#{builder.to_s}\n//# sourceMappingURL=build.js.map"
File.binwrite "build.js.map", builder.source_map.to_s
File.binwrite "opal_lib.js", Opal::Builder.build('opal_lib')
Also create an opal_lib.rb
file containing only:
require 'opal'
Finally create an index.html
which will allow us to run the script in browser.
<!DOCTYPE html>
<html>
<head>
<script src="opal_lib.js"></script>
<script src="build.js"></script>
</head>
<body>
</body>
</html>
Now to actually compile your file, run:
ruby builder.rb
This will generate compiled javascript files opal_lib.js
and build.js
which are referenced by our index.html
file. Now just open index.html
in your browser. You will get a full call-stack and source view:
The line numbers of the source file are available:
As an alternative to using the browser, you can also use Node.js for the same purpose. This requires you have Node.js
and npm
installed. You will also need to install npm module source-map-support
npm install source-map-support
Now you can open the node repl and enter the following:
require('source-map-support').install();
require('./opal_lib');
require('./build');
You will get a stack trace with correct source line numbers :
/home/gaurav/Workspace/opal-playground/opal_lib.js:4436
Error.captureStackTrace(err);
^
NoMethodError: undefined method `x' for #<Test:0x102>
at OpalClass.$new (/home/gaurav/Workspace/opal-playground/opal_lib.js:4436:15)
at OpalClass.$exception (/home/gaurav/Workspace/opal-playground/opal_lib.js:4454:31)
at $Test.$raise (/home/gaurav/Workspace/opal-playground/opal_lib.js:4204:31)
at $Test.Opal.defn.TMP_1 (/home/gaurav/Workspace/opal-playground/opal_lib.js:3032:19)
at $Test.method_missing_stub [as $x] (/home/gaurav/Workspace/opal-playground/opal_lib.js:886:35)
at $Test.$crash (/home/gaurav/Workspace/opal-playground/index.rb:8:11)
at /home/gaurav/Workspace/opal-playground/index.rb:13:10
at Object.<anonymous> (/home/gaurav/Workspace/opal-playground/index.rb:13:10)
at Module._compile (module.js:435:26)
at Object.Module._extensions..js (module.js:442:10)
I recommend that you use bundler for gem management. Here is the Gemfile
for fetching Opal master:
source 'http://production.cf.rubygems.org'
gem 'opal', github: 'opal/opal'
To compile you will have to run:
bundle install
bundle exec ruby builder.rb
Sprockets integration / rack integration that others have mentioned use the same API underneath, abstracting away the plumbing.
Update:
Since we have the correct line numbers in stack, it is fairly to programatically parse the stack and extract this line number into a variable:
require('./opal_lib');
require('source-map-support').install();
var $e = null;
try {
require('./build');
} catch (e) {
$e = e;
}
var lines = e.split('\n').map(function(line){ return line.match(/^.*\((\S+):(\d+):(\d+)\)/) })
var first_source_line;
for (var i = 0; i < lines.length ; i++) {
var match = lines[i];
if (match == null) continue;
if (match[1].match(/index.rb$/) {
first_source_line = match;
break;
}
}
var line_number;
if (first_source_line) line_number = first_source_line[2] // ==> 8
And of course you can do it ruby as well (but if you are running this in browser you will have to include source-map-support here as well):
class Test
def initialize
end
def crash
print x
end
end
line_num = nil
begin
Test.new.crash
rescue => e
if line = e.backtrace.map{|line| line.match(/^.*\((\S+):(\d+):(\d+)\)/) }.compact.find{|match| match[1] =~ /index.rb$/ }
line_num = line[2]
end
end
puts "line_num => #{line_num}" # ==> 8
Related Topics
How to Use Mongodb Ruby Driver to Do a "Group" (Group By)
Ubuntu 12.10 - Ruby Gem Rmagick Missing Dependency Issue
Uploading a File to a Website with Ruby/Rails
Installing Ruby Gem Less-Rails on Windows MAChine Using Therubyracer
Sorting a Hash in Ruby by Its Value First Then Its Key
Ruby Scope of Data After _End_
How to Convert Activerecord Table Name to Model Class Name
How to Get a List of Gems That Are Installed That Have Native Extensions
Could Not Find Rake-10.0.4 in Any of the Sources (Bundler::Gemnotfound)
Clicking a Button with Ruby Mechanize
Array Typeerror: Can't Convert Fixnum into String
How to Do "Late" String Interpolation in Ruby
Actioncable - Failed to Upgrade to Websocket in Production
How to Require a Block in Ruby
How to Destroy a Record Without an Id Column in Ruby Activerecord
How to 'Unload' ('Un-Require') a Ruby Library
Open-Uri Returning Ascii-8Bit from Webpage Encoded in Iso-8859