Any way to do unqualified method calls? - ruby

If I have a script that looks like this:
require "FileUtils"
puts FileUtils.pwd()
is there anyway to do importing so that I don't have to write FileUtils? I want to just be able write pwd() instead of FileUtils.pwd().

require 'fileutils'
Object.include FileUtils
pwd
but never do it at home

Related

Require in an IRB shell

I'm working in an IRB shell on a dos CMD
I load a module from a mystuff file
require '.\mystuff'
I change the module in the mystuff file and I type again
require '.\mystuff'
How come the IRB does not pick up the changes in the file when I try to call functions or variables from the newest version of my mystuff module?
require will not load the same file twice. If you want to load the file again, you need to use load. See What is the difference between include and require in Ruby? for more information.
Your Syntax is Wrong
Ruby doesn't use backslashes. You need to use forward slashes, or use File#join.
Your $LOAD_PATH is Wrong
Your $LOAD_PATH (a.k.a $:) is wrong. You need to include the present working directory with:
$: << '.'
in irb, or use Kernel#require_relative in executable or sourced files.

Troublesoot ruby require

Ruby require only works for me with gems not with code that I have written. I'm not sure what it is that I am doing wrong.
This works
require "test-unit"
require "require "C:\\Users\\zreichert\\workspace\\FalconQA\\PageObjects\\Users\\user.rb"
This doesn't work
require "Users/user"
require "Users\user"
require "Users/user.rb"
require "Users\user.rb"
require_relative "Users/user"
require_relative "Users\user"
require_relative "Users/user.rb"
require_relative "Users\user.rb"
The script that I am running is located in - C:/Users/zreichert/workspace/FalconQA/testCases
I have tried to change directories before require like this
Dir.chdir "C:/Users/zreichert/workspace/FalconQA/testCases"
All errors look something like this
c:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:in require': cannot load such file -- Users/user (LoadError)
from c:/Ruby193/lib/ruby/site_ruby/1.9.1/rubygems/custom_require.rb:36:inrequire'
from C:/Users/zreichert/workspace/FalconQA/testCases/FAL001.rb:14:in `
you can try
require "./Users/user"
You can use this:
require_relative '../PageObjects/Users/user.rb'
Slash is better than two backslashes, because it works in both Windows and Linux/MacOS.
Just to expand on Roozbeh's answer slightly, require_relative allows you to load files relative to the location of the file containing the require_relative so doing a chdir will not have any effect on this.
From what you've said in the question, the relative path from FAL001.rb to user.rb is
../PageObjects/Users/user.rb
i.e. up one level and then down into PageObjects/Users, hence
require_relative '../PageObjects/Users/user.rb'
As a mental-safety tip, anything looking like "Users\user" will fail because of how escaped characters are interpreted in double-quoted strings.
Instead, use single-quotes for your require parameter to preserve your sanity:
require 'foo'
or
require './relative/path/to/foo'
require '../relative/path/to/bar'

Why doesn't require add all names?

I have a file, my_helper.rb, that looks like this:
require 'cgi'
require 'enumerator'
module MyHelper
# ...
end
class MyUpstreamError < StandardError
# ...
end
When I require 'my_helper' elsewhere, MyHelper becomes visible, but MyUpstreamError does not. Why is this?
Ruby's require is analogous to include in C.
You might want to have a read though:
http://rubylearning.com/satishtalim/including_other_files_in_ruby.html
http://ionrails.com/2009/09/19/ruby_require-vs-load-vs-include-vs-extend/
It turned out to be a filename conflict. There was another file named my_helper.rb, which I had never edited, in a helpers directory in my Rails setup. It was shadowing this file, which was in lib.

ERB not wanting to render file in Rack App

When I use an erb method using:
require 'erb'
def erb(template)
path = File.expand_path("../views/#{template}", __FILE__)
ERB.new(File.read(path)).result(binding)
end
And afterward use a:
Rack::Response.new(erb('default.html.erb'))
It raises an Errno::ENOENT. Why is this? Thanks!
Looks like you may have gotten your file path wrong. Check to make sure that's right.

Is there a shorter way to require a file in the same directory in ruby?

Is there a shorter way to require a file located in the same directory (as the script being executed)?
require File.expand_path(File.dirname(__FILE__) + '/some_other_script')
I read that require "my_script" and require "./my_script" will actually load the script twice (ruby will not recognize that it is actually the same script), and this is the reason why File.expand_path is recommended: if it is used every time the script is required, then it will only be loaded once.
It seems weird to me that a concise language like Ruby does not seem to have a shorter solution. For example, python simply has this:
import .some_other_module_in_the_same_directory
I guess I could monkey-patch require... but that's just evil! ;-)
Since ruby 1.9 you can use require_relative.
Check the latest doc for require_relative or another version of the Core API.
Just require filename.
Yes, it will import it twice if you specify it as filename and ./filename, so don't do that. You're not specifying the .rb, so don't specify the path. I usually put the bulk of my application logic into a file in lib, and then have a script in bin that looks something like this:
#!/usr/bin/env ruby
$: << File.join(File.dirname(__FILE__), "/../lib")
require 'app.rb'
App.new.run(ARGV)
Another advantage is that I find it easier to do unit testing if the loading the application logic doesn't automatically start executing it.
The above will work even when you're running the script from some other directory.
However, inside the same directory the shorter forms you refer to work as expected and at least for ruby 1.9 won't result in a double-require.
testa.rb
puts "start test A"
require 'testb'
require './testb'
puts "finish test A"
testb.rb
puts "start test B"
puts "finish test B"
running 'ruby testa.rb' will result in:
start test A
start test B
finish test B
finish test A
However, the longer form will work even from another directory (eg. ruby somedir/script.rb)
Put this in a standard library directory (somewhere that's already in your default loadpath $:):
# push-loadpath.rb
if caller.first
$: << File.expand_path(File.dirname(caller.first))
end
Then, this should work
% ls /path/to/
bin.rb lib1.rb lib2.rb #...
% cat /path/to/bin.rb
load 'push-loadpath.rb'
require 'lib1'
require 'lib2'
#...
caller gives you access to the current callstack, and tells you what file and where, so push-loadpath.rb uses that to add the file that load'd it to the loadpath.
Note that you should load the file, rather than require it, so the body can be invoked multiple times (once for each time you want to alter the loadpath).
Alternately, you could wrap the body in a method,
# push-loadpath.rb
def push_loadpath
$: << File.expand_path(File.dirname(caller.first))
end
This would allow you to require it, and use it this way:
% ls /path/to/
bin.rb lib1.rb lib2.rb #...
% cat /path/to/bin.rb
require 'push-loadpath'
push_loadpath
require 'lib1'
require 'lib2'
#...

Resources