Do not necessary require(s) matter? - ruby

I want to be able to have one ruby file that can require all the common dependencies, so that other files can just have one require on this shared file.for example; I have foo.rb and bar.rb and allrequires.rb. I want to have the line require "allrequires.rb" in both foo.rb and bar.rb, but bar.rb doesn't need all the requires.
Does it matter if I use require in .rb file that do not really require that file? Could it have an impact on performance maybe?
I am currently on ruby 1.8.7 (2010-08-16 patchlevel 302) [i386-mingw32]
Update
It looks like it is not the best idea to 'share'/use all requires in both .rb files. What would be solution to that?
Right now I can think of using file name in a condition.

There's two main performance penalties:
The time taken to do the require itself. In Ruby 1.9.1 and Ruby 1.9.2, the time taken to do all the requires had worse than linear scalability - if you doubled the number of requires, it took you more than twice as long - I think it took you four times as long.
The time taken to execute the code in the file being required. If you have code like the following, then executing the code will take a non-trivial amount of time.
class MyClass
MY_CONSTANT = File.read("data.txt")
end

Another approach of conditional requiring, the following script gives no error on the JSON parser because it is named require1.rb, in scripts that have no name like require1.rb of script2.rb the gem isn't required
require 'json' if "require1.rb, script2.rb"[File.basename(__FILE__)]
p File.basename(__FILE__)
text = '[{ "name" : "car", "status": "good"}, { "name" : "bus", "status": "bad"},{ "name" : "taxi", "status": "soso"},
{"noname":"", "status" : "worse"}
]'
data = JSON.parse(text)
p data.collect { |item| item['name'] }
EDIT: here a version that uses an array
["require1.rb","script1.rb"].find{|script|require 'json' if script===File.basename(__FILE__)}

Yes, there will be a speedpanalty, you can benchmark how mutch to consider if it realy matters.
With multiple require's i put hem in my code like this so that it doens't take much screenspace.
['green_shoes','Hpricot'].each(&method(:require))
You could also do a conditional require, but that would be ugly having all around your code
begin
data = JSON.parse(text)
rescue
require 'json_pure'
data = JSON.parse(text)
end
So in short, give each rb its own require's

My final solution is (in case someone finds it useful):
requires.rb is called from web.rb or testweb.rb, rufus.rb or testrufus.rb
called_from=caller[0].split(":")[0]
puts "loading web 'requires' for file: #{called_from} ..." if (["web"].any?{|s| called_from[s]})
puts "loading web 'requires' for file: #{called_from} ..." if (["rufus"].any?{|s| called_from[s]})
puts "loading web 'requires' for file: #{called_from} ..." if (["settings"].any?{|s| called_from[s]})
require 'rubygems'
require 'socket' if (["web","settings"].any?{|s| called_from[s]})
require 'ruby-growl' if (["web","settings","rufus"].any?{|s| called_from[s]})
require 'sinatra' if (["web"].any?{|s| called_from[s]})
Thank you #Andrew for the explanation and #peter for the hint how to solve this.

Related

require not working on ruby 2.0?

I'm doing a test with "require" under ruby 2.0.0p576 (2014-09-19 revision 47628) [x86_64-darwin13.4.0] it doesn't work in many ways.
There are two files in ruby directory as shown below:
string_extensions.rb
class String
def vowels
self.scan(/[aeiou]/i)
end
end
vowels_test.rb
require 'string_extensions'
puts "This is a test".vowels.join('-')
fire up IRB
Snailwalkers-MacBook-Pro:ruby snailwalker$ ruby vowels_test.rb
returs : `require': cannot load such file -- string_extensions (LoadError)
I tried to change require 'string_extensions' to " require_relative 'string_extensions' ; require './string_extensions.rb' . They all didn't work.
both return error : vowels_test.rb:1:in require_relative': /Users/snailwalker/Ruby/string_extensions.rb:1: class/module name must be CONSTANT (SyntaxError)
Your help will be greatly appreciated!
You can use require_relative instead:
require_relative 'string_extensions'
puts "This is a test".vowels.join('-')
Or even require './string_extensions'.
Use:
ruby -I. vowels_test.rb
Automatic inclusion of the current directory in the load paths was removed in Ruby 2.

load error when run the ruby file from a different location

I have the following problem:
My ruby project structure : Ruby_Source\
file1.rb
file2.rb
file3.rb
In file1.rb,
require 'file2'
require 'file3'
now ,if I run the file1.rb from Ruby_Source, am not getting any error.
but , when I run the same from a different system location eg(c:)
error is Load error.
Can some one help me please?
You might want to use require_relative:
require_relative complements the builtin method require by allowing you to load a file that is relative to the file containing the require_relative statement.
See further discussion:
What is the difference between require_relative and require in Ruby?
And if you run Ruby 1.8:
Ruby: require vs require_relative - best practice to workaround running in both Ruby <1.9.2 and >=1.9.2
Try this:
require_relative 'file2'
in Ruby 1.9.x. It will search for file2 in the directory of file1.
In older versions you might try something like:
$: << File.dirname($0)
which will add the current program's path to the require-search path.

Ruby 'require' error: cannot load such file

I've one file, main.rb with the following content:
require "tokenizer.rb"
The tokenizer.rb file is in the same directory and its content is:
class Tokenizer
def self.tokenize(string)
return string.split(" ")
end
end
If i try to run main.rb I get the following error:
C:\Documents and Settings\my\src\folder>ruby main.rb
C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require': cannot load such file -- tokenizer.rb (LoadError)
from C:/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `require '
from main.rb:1:in `<main>'
I just noticed that if I use load instead of require everything works fine. What may the problem be here?
I just tried and it works with require "./tokenizer".
Just do this:
require_relative 'tokenizer'
If you put this in a Ruby file that is in the same directory as tokenizer.rb, it will work fine no matter what your current working directory (CWD) is.
Explanation of why this is the best way
The other answers claim you should use require './tokenizer', but that is the wrong answer, because it will only work if you run your Ruby process in the same directory that tokenizer.rb is in. Pretty much the only reason to consider using require like that would be if you need to support Ruby 1.8, which doesn't have require_relative.
The require './tokenizer' answer might work for you today, but it unnecessarily limits the ways in which you can run your Ruby code. Tomorrow, if you want to move your files to a different directory, or just want to start your Ruby process from a different directory, you'll have to rethink all of those require statements.
Using require to access files that are on the load path is a fine thing and Ruby gems do it all the time. But you shouldn't start the argument to require with a . unless you are doing something very special and know what you are doing.
When you write code that makes assumptions about its environment, you should think carefully about what assumptions to make. In this case, there are up to three different ways to require the tokenizer file, and each makes a different assumption:
require_relative 'path/to/tokenizer': Assumes that the relative path between the two Ruby source files will stay the same.
require 'path/to/tokenizer': Assumes that path/to/tokenizer is inside one of the directories on the load path ($LOAD_PATH). This generally requires extra setup, since you have to add something to the load path.
require './path/to/tokenizer': Assumes that the relative path from the Ruby process's current working directory to tokenizer.rb is going to stay the same.
I think that for most people and most situations, the assumptions made in options #1 and #2 are more likely to hold true over time.
Ruby 1.9 has removed the current directory from the load path, and so you will need to do a relative require on this file, as David Grayson says:
require_relative 'tokenizer'
There's no need to suffix it with .rb, as Ruby's smart enough to know that's what you mean anyway.
require loads a file from the $LOAD_PATH. If you want to require a file relative to the currently executing file instead of from the $LOAD_PATH, use require_relative.
I would recommend,
load './tokenizer.rb'
Given, that you know the file is in the same working directory.
If you're trying to require it relative to the file, you can use
require_relative 'tokenizer'
I hope this helps.
Another nice little method is to include the current directory in your load path with
$:.unshift('.')
You could push it onto the $: ($LOAD_PATH) array but unshift will force it to load your current working directory before the rest of the load path.
Once you've added your current directory in your load path you don't need to keep specifying
require './tokenizer'
and can just go back to using
require 'tokenizer'
This will work nicely if it is in a gem lib directory and this is the tokenizer.rb
require_relative 'tokenizer/main'
For those who are absolutely sure their relative path is correct, my problem was that my files did not have the .rb extension! (Even though I used RubyMine to create the files and selected that they were Ruby files on creation.)
Double check the file extensions on your file!
What about including the current directory in the search path?
ruby -I. main.rb
I used jruby-1.7.4 to compile my ruby code.
require 'roman-numerals.rb'
is the code which threw the below error.
LoadError: no such file to load -- roman-numerals
require at org/jruby/RubyKernel.java:1054
require at /Users/amanoharan/.rvm/rubies/jruby-1.7.4/lib/ruby/shared/rubygems/custom_require.rb:36
(root) at /Users/amanoharan/Documents/Aptana Studio 3 Workspace/RubyApplication/RubyApplication1/Ruby2.rb:2
I removed rb from require and gave
require 'roman-numerals'
It worked fine.
The problem is that require does not load from the current directory. This is what I thought, too but then I found this thread. For example I tried the following code:
irb> f = File.new('blabla.rb')
=> #<File:blabla.rb>
irb> f.read
=> "class Tokenizer\n def self.tokenize(string)\n return string.split(
\" \")\n end\nend\n"
irb> require f
LoadError: cannot load such file -- blabla.rb
from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
from D:/dev/Ruby193/lib/ruby/1.9.1/rubygems/custom_require.rb:36:in `req
uire'
from (irb):24
from D:/dev/Ruby193/bin/irb:12:in `<main>'
As it can be seen it read the file ok, but I could not require it (the path was not recognized). and here goes code that works:
irb f = File.new('D://blabla.rb')
=> #<File:D://blabla.rb>
irb f.read
=> "class Tokenizer\n def self.tokenize(string)\n return string.split(
\" \")\n end\nend\n"
irb> require f
=> true
As you can see if you specify the full path the file loads correctly.
First :
$ sudo gem install colored2
And,you should input your password
Then :
$ sudo gem update --system
Appear
Updating rubygems-update
ERROR: While executing gem ... (OpenSSL::SSL::SSLError)
hostname "gems.ruby-china.org" does not match the server certificate
Then:
$ rvm -v
$ rvm get head
Last
What language do you want to use?? [ Swift / ObjC ]
ObjC
Would you like to include a demo application with your library? [ Yes / No ]
Yes
Which testing frameworks will you use? [ Specta / Kiwi / None ]
None
Would you like to do view based testing? [ Yes / No ]
No
What is your class prefix?
XMG
Running pod install on your new library.
you need to give the path.
Atleast you should give the path from the current directory. It will work for sure.
./filename

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'
#...

Best way to require all files from a directory in ruby?

What's the best way to require all files from a directory in ruby ?
How about:
Dir["/path/to/directory/*.rb"].each {|file| require file }
If it's a directory relative to the file that does the requiring (e.g. you want to load all files in the lib directory):
Dir[File.dirname(__FILE__) + '/lib/*.rb'].each {|file| require file }
Edit: Based on comments below, an updated version:
Dir[File.join(__dir__, 'lib', '*.rb')].each { |file| require file }
Try the require_all gem:
http://github.com/jarmo/require_all
https://rubygems.org/gems/require_all
It lets you simply:
require_all 'path/to/directory'
Dir[File.dirname(__FILE__) + '/../lib/*.rb'].each do |file|
require File.basename(file, File.extname(file))
end
If you don't strip the extension then you may end up requiring the same file twice (ruby won't realize that "foo" and "foo.rb" are the same file). Requiring the same file twice can lead to spurious warnings (e.g. "warning: already initialized constant").
Dir.glob(File.join('path', '**', '*.rb'), &method(:require))
or alternatively, if you want to scope the files to load to specific folders:
Dir.glob(File.join('path', '{folder1,folder2}', '**', '*.rb'), &method(:require))
explanation:
Dir.glob takes a block as argument.
method(:require) will return the require method.
&method(:require) will convert the method to a bloc.
The best way is to add the directory to the load path and then require the basename of each file. This is because you want to avoid accidentally requiring the same file twice -- often not the intended behavior. Whether a file will be loaded or not is dependent on whether require has seen the path passed to it before. For example, this simple irb session shows that you can mistakenly require and load the same file twice.
$ irb
irb(main):001:0> require 'test'
=> true
irb(main):002:0> require './test'
=> true
irb(main):003:0> require './test.rb'
=> false
irb(main):004:0> require 'test'
=> false
Note that the first two lines return true meaning the same file was loaded both times. When paths are used, even if the paths point to the same location, require doesn't know that the file was already required.
Here instead, we add a directory to the load path and then require the basename of each *.rb file within.
dir = "/path/to/directory"
$LOAD_PATH.unshift(dir)
Dir[File.join(dir, "*.rb")].each {|file| require File.basename(file) }
If you don't care about the file being required more than once, or your intention is just to load the contents of the file, perhaps load should be used instead of require. Use load in this case, because it better expresses what you're trying to accomplish. For example:
Dir["/path/to/directory/*.rb"].each {|file| load file }
Instead of concatenating paths like in some answers, I use File.expand_path:
Dir[File.expand_path('importers/*.rb', File.dirname(__FILE__))].each do |file|
require file
end
Update:
Instead of using File.dirname you could do the following:
Dir[File.expand_path('../importers/*.rb', __FILE__)].each do |file|
require file
end
Where .. strips the filename of __FILE__.
Dir[File.join(__dir__, "/app/**/*.rb")].each do |file|
require file
end
This will work recursively on your local machine and a remote (Like Heroku) which does not use relative paths.
In Rails, you can do:
Dir[Rails.root.join('lib', 'ext', '*.rb')].each { |file| require file }
Update: Corrected with suggestion of #Jiggneshh Gohel to remove slashes.
I'm a few years late to the party, but I kind of like this one-line solution I used to get rails to include everything in app/workers/concerns:
Dir[ Rails.root.join *%w(app workers concerns *) ].each{ |f| require f }
And what about: require_relative *Dir['relative path']?

Resources