Access ri documentation right from the ruby terminal or rails console? - ruby-on-rails

I know exiting irb for a moment or opening a new terminal tab to use ri is trivial, but it could be slightly more convenient in terms of developer flow to be able to use ri in the irb (or rails console) itself. That would allow retrieval of documentation right from the irb. Is that possible with ri, and if so, how?
Desired result
To be clear, I'd like to be able to do something like this (example in irb):
2 * 2
# => 4
ri "File.open"
# = File.open
#
# (from ruby core)
# ------------------------------------------------------------------------
# File.open(filename, mode="r" [, opt]) -> file
# File.open(filename [, mode [, perm]] [, opt]) -> file
# File.open(filename, mode="r" [, opt]) {|file| block } -> obj
# File.open(filename [, mode [, perm]] [, opt]) {|file| block } -> obj
# ------------------------------------------------------------------------
# With no associated block, File.open is a synonym for File.new. If the
# optional code block is given, it will be passed the opened file as an
# argument and the File object will automatically be closed when the block
# terminates. The value of the block will be returned from File.open.
# If a file is being created, its initial permissions may be set using the
# perm parameter. See File.new for further discussion.
# See IO.new for a description of the mode and opt parameters.
2 * 2
# => 4
That is, be using some ruby, grab documentation for some method, back to using some ruby, without skipping a beat.

Related

Sourcing nvim.init does not source required Lua files

I have neovim 0.7.0 running and my .vimrc is at ~/.config/nvim/init.vim
I also have the following file: ~/.config/nvim/lua/statusline.lua with one line of code:
print('message from statusline.lua')
Inside init.vim I have:
echo 'from init.vim'
lua require('statusline')
When I start nvim I get both messages printed out ('from init.vim' and 'message from statusline.lua') which is what I would expect.
When I run :source $MYVIMRC I only see 'from init.vim'. I would expect the other message ('message from statusline.lua') to appear as well.
I assume this means any changes I make in statusline.lua will not take effect when I run :source $MYVIMRC. How should I source my init.vim file plus any files it requires without closing and restarting neovim?
Either invalidate cache entry by appending return false to the end of a module.
Or don't use require at all, as you need neither cache nor path search anyway. E.g.
for k, v in ipairs(vim.fn.glob("~/.config/nvim/init.d/*.lua", false, true)) do
dofile(v)
end
P.S. Lua is not a "config tool". It is a full-featured programming language. If you don't like wasting your time by learning it properly (i.e. reading books and tutorials) you're highly suggested to use VimScript instead. It has some "dark corners" of its own but it is much better suited for writing config.
It depends on the design of your statusline.lua and knowledge about Lua' module loader system.
It looks, because i have to riddle about statusline.lua, that it nothing returns.
Because the return is going into package.loaded and same require in same session looks first there for statusline
So give following a try...
-- statusline.lua
print('message from statusline.lua')
return 'message from package.loaded.statusline'
I have tested above with...
$ lua -i
Lua 5.4.4 Copyright (C) 1994-2022 Lua.org, PUC-Rio
> require('statusline')
message from statusline.lua
message from package.loaded.statusline ./lua/statusline.lua
> require('statusline')
message from package.loaded.statusline
> require('statusline')
message from package.loaded.statusline
EDIT
Another design for doing something usefull...
-- ~.config/nvim/init.vim
lua print("init.vim")
lua dump = require("dump")
And...
-- ~/.config/nvim/lua/dump.lua
local dump = function(tab)
for key, value in pairs(tab) do
print(key, '=>', value)
end
end
return dump
Than you have a table viewer and you can see where the functions and tables come from with...
:lua dump(_G) -- The global environment table
:lua dump(vim) -- The nvim stuff (aka Module)
:lua dump(vim.api) -- The nvim API functions (aka Library)
:lua dump(jit) -- The Just In Time Compiler ;-)
:lua dump([Table Name]) -- Any table that looks interesting
:lua dump(package.loaded) -- The required or requireable stuff
Above function can be executed without defining dump first with: :lua require('dump')(_G)
So: First require loads dump.lua into package.loaded.dump and returning it and every further require returning: package.loaded.dump
If you have an sharp eye than take a look on _G.dump thats only a reference (pointer/link) to package.loaded.dump.
EDIT2
Preparing dump.lua for using it with vim.api.nvim_input()
-- ~/.config/nvim/lua/dump.lua
local dump = function(tab)
local tmp = ''
for key, value in pairs(tab) do
tmp = tmp .. ('%s %s %s\n'):format(key, '=>', value)
end
return tmp
end
return dump
Now the dump function returning a string and the output can be loaded into nvim with: :lua vim.api.nvim_input('i') vim.api.nvim_input(dump(vim.api))
Since many nvim API functions returning a table the dump function becomes handy with...

New relic custom plugin data not showing up - ruby sdk

I am using newrelic's ruby sdk to develop a custom plugin. When I run the sample app, on the terminal it shows that the data is successfully captured. But when i go to the site, it cannot search the metrics and due to that I cannot look at any data reported.
the plugin name and everthing else shows up but don't where the data is going.
This what the agent file looks like:
require "rubygems"
require "bundler/setup"
require "newrelic_plugin"
module ExampleAgent
class Agent < NewRelic::Plugin::Agent::Base
agent_guid "com.phytel.Product1"
agent_version "1.0.1"
agent_config_options :hostname # frequency of the periodic functions
agent_human_labels("Product1") { "Call Statuses" }
def poll_cycle
# x = Time.now.to_f * hertz * Math::PI * 2
report_metric "Component/Status/Progressing", "Value", 10
report_metric "Component/Status/Scheduled", "Value", 20
report_metric "Component/Status/Busy", "Value", 2
end
end
#
# Register this agent with the component.
# The ExampleAgent is the name of the module that defines this
# driver (the module must contain at least three classes - a
# PollCycle, a Metric and an Agent class, as defined above).
#
NewRelic::Plugin::Setup.install_agent :example, ExampleAgent
#
# Launch the agent; this never returns.
#
NewRelic::Plugin::Run.setup_and_run
end
Don't put the Component part in your metric name. The SDK automatically adds that for you.

read and execute ruby script

script.rb:
puts 'hello'
puts 'foo'
main.rb:
puts `jruby script.rb` # receive the expected result
The question:
How can the same be achieved with reading the "script" before execution?
main.rb:
code=File.open('script.rb', 'r').read.gsub('"', '\"')
# puts `jruby -e '#{code}'` # Does not work for relatively big files;
Windows and unicode are the reasons of this question;
Please note that `jruby script.rb' creates a new process which is essential.
Store the modified script in a Tempfile and run that instead of passing the whole contents as an eval argument:
require 'tempfile'
code = IO.read('script.rb').gsub('"', '\"')
begin
tempfile = Tempfile.new 'mytempfile'
f.write code
f.close
puts `jruby '#{f.path}'`
ensure
f.close
f.unlink
end
The reason you’re likely getting an error is either a lack of proper escaping or a limit on the maximum argument length in the shell.
Also, beware that in your original implementation you never close the original file. I’ve fixed that by instead using IO.read.
In the command line, using
$ getconf ARG_MAX
will give the upper limit on how many bytes can be used for the command line argument and environment variables.
#Andrew Marshall's answer is better, but suppose you don't want to use a temp file, and assuming we can use fork in JRuby,
require 'ffi'
module Exec
extend FFI::Library
ffi_lib FFI::Platform::LIBC
attach_function :fork, [], :int
end
code = IO.read('script.rb')
pid = Exec.fork
if 0 == pid
eval code
exit 0
else
Process.waitpid pid
end
use require
main.rb:
require "script.rb"

Is there a way to achieve grep like functionality on output inside the Rails Console

In shell, I can do
$ cat name_of_file_with_a_lot_of_text | grep "What I am looking for"
Inside the Rails Console, can I achieve something similar, say when I run a command and the output is huge, especially say a DB query.
I am aware of outputting it as YAML but that Is not what I am looking for.
Thanks.
Yes, you can. The method is called gr... wait for it ...ep. Ruby's grep works on String, Array and many other built-in objects. For example to get all to_xxx methods of a number, just do:
1.methods.grep(/to_/)
I had the same question and wasn't very satisfied with the somewhat snarky response from ream88, so I decided to take a crack at it.
# Allows you to filter output to the console using grep
# Ex:
# def foo
# puts "Some debugging output here"
# puts "The value of x is y"
# puts "The value of foo is bar"
# end
#
# grep_stdout(/value/) { foo }
# # => The value of x is y
# # => The value of foo is bar
# # => nil
def grep_stdout(expression)
# First we need to create a ruby "pipe" which is two sets of IO subclasses
# the first is read only (which represents a fake $stdin) and the second is
# write only (which represents a fake $stdout).
placeholder_in, placeholder_out = IO.pipe
# This child process handles the grep'ing. Its done in a child process so that
# it can operate in parallel with the main process.
pid = fork {
# sync $stdout so we can report any matches asap
$stdout.sync
# replace $stdout with placeholder_out
$stdin.reopen(placeholder_in)
# we have to close both placeholder_out and placeholder_in because all instances
# of an IO stream must be closed in order for it to ever reach EOF. There's two
# in this method; one in the child process and one in the main process.
placeholder_in.close
placeholder_out.close
# loop continuously until we reach EOF (which happens when all
# instances of placeholder_out have closed)
read_buffer = ''
loop do
begin
read_buffer << $stdin.readpartial(4096)
if line_match = read_buffer.match(/(.*\n)(.*)/)
print line_match[1].grep(expression) # grep complete lines
read_buffer = line_match[2] # save remaining partial line for the next iteration
end
rescue EOFError
print read_buffer.grep(expression) # grep any remaining partial line at EOF
break
end
end
}
# Save the original stdout out to a variable so we can use it again after this
# method is done
original_stdout = $stdout
# Redirect stdout to our pipe
$stdout = placeholder_out
# sync $stdout so that we can start operating on it as soon as possible
$stdout.sync
# allow the block to execute and save its return value
return_value = yield
# Set stdout back to the original so output will flow again
$stdout = original_stdout
# close the main instances of placeholder_in and placeholder_out
placeholder_in.close
placeholder_out.close
# Wait for the child processes to finish
Process.wait pid
# Because the connection to the database has a tendency to go away when calling this, reconnect here
# if we're using ActiveRecord
if defined?(ActiveRecord)
suppress_stdout { ActiveRecord::Base.verify_active_connections! }
end
# return the value of the block
return_value
end
The obvious drawback of my solution is that the output is lost. I'm not sure how to get around that without calling yield twice.
EDIT I've changed my answer to only call fork once, which allows me to keep the output of the block and return it at the end. Win.
EDIT 2 You can get all of this functionality (and more!) in this gem now https://github.com/FutureAdvisor/console_util

Reading docs in irb

One thing I miss about ipython is it has a ? operator which diggs up the docs for a particular function.
I know ruby has a similar command line tool but it is extremely inconvenient to call it while I am in irb.
Does ruby/irb have anything similar?
Pry is a Ruby version of IPython, it supports the ? command to look up documentation on methods, but uses a slightly different syntax:
pry(main)> ? File.dirname
From: file.c in Ruby Core (C Method):
Number of lines: 6
visibility: public
signature: dirname()
Returns all components of the filename given in file_name
except the last one. The filename must be formed using forward
slashes (/'') regardless of the separator used on the
local file system.
File.dirname("/home/gumby/work/ruby.rb") #=> "/home/gumby/work"
You can also look up sourcecode with the $ command:
pry(main)> $ File.link
From: file.c in Ruby Core (C Method):
Number of lines: 14
static VALUE
rb_file_s_link(VALUE klass, VALUE from, VALUE to)
{
rb_secure(2);
FilePathValue(from);
FilePathValue(to);
from = rb_str_encode_ospath(from);
to = rb_str_encode_ospath(to);
if (link(StringValueCStr(from), StringValueCStr(to)) < 0) {
sys_fail2(from, to);
}
return INT2FIX(0);
}
See http://pry.github.com for more information :)
You can start with
irb(main):001:0> `ri Object`
Although the output of this is less than readable. You'd need to filter out some metacharacters.
In fact, someone already made a gem for it
gem install ori
Then in irb
irb(main):001:0> require 'ori'
=> true
irb(main):002:0> Object.ri
Looking up topics [Object] o
= Object < BasicObject
------------------------------------------------------------------------------
= Includes:
Java (from gem activesupport-3.0.9)
(from gem activesupport-3.0.9) [...]
No, it doesn't. Python has docstrings:
def my_method(arg1,arg2):
""" What's inside this string will be made available as the __doc__ attribute """
# some code
So, when the ? is called from ipython, it probably calls the __doc__ attribute on the object. Ruby doesn't have this.

Resources