Ruby require module/class on another folder - ruby

I am new to Ruby and I'm trying to understand a good way to require modules or classes defines elsewhere. I have this setup:
test/
database/
base.rb
scripts/
run.rb
base.rb
module A
def hi
puts "It works"
end
end
run.rb
# I don't know how to require module A here
hi()
Now I know I can do something like: require "#{File.dirname(__FILE__)}/database/base" but that looks fragile. I want to know if there is a way to add a folder to the LOAD_PATH of a particular folder or the whole application.

I believe the following will work:
require_relative '../database/base'
Inside run.rb file, include A and then run file

It depends on from which file you are requiring other ruby file. Its relative to the host file.
In you situation
test/
database/
base.rb
scripts/
run.rb
I suppose you are tying to require the base.rb from run.rb then do this
require '../database/base.rb'
class SomeClass
include A
def some_method
hi()
end
end

Related

RSpec: kernel_require.rb:45:in `require': cannot load such file -- bowling.rb (LoadError)

Following the example here:
http://rspec.info
however it fails with:
kernel_require.rb:45:in `require': cannot load such file -- bowling.rb (LoadError)
even though I've got a bowling.rb file.
Any suggestions?
UPDATE
Project listing:
ls -l
-rw-r--r-- 1 snowcrash snowcrash 77 10 Jul 19:43 bowling.rb
-rw-r--r-- 1 snowcrash snowcrash 205 10 Jul 19:49 bowling_spec.rb
$ rspec bowling_spec.rb
/Users/snowcrash/.rvm/rubies/ruby-2.0.0-p195/lib/ruby/site_ruby/2.0.0/rubygems/core_ext/kernel_require.rb:45:in `require': cannot load such file -- bowling (LoadError)
and code listings:
Spec:
# bowling_spec.rb
require 'bowling'
describe Bowling, "#score" do
it "returns 0 for all gutter game" do
bowling = Bowling.new
20.times { bowling.hit(0) }
bowling.score.should eq(0)
end
end
Class file:
# bowling.rb
class Bowling
def hit(pins)
end
def score
0
end
end
The rspec home page unfortunately does not tell you about initializing rspec in your project.
Assuming you have a project folder called 'bowling', inside the bowling folder run
rspec --init
This will create the spec directory and two files
spec/spec_helper.rb
.rspec
The .rspec file lets you define preferences like color and format
--color
--format documentation
Now in spec_helper.rb, add require "bowling"
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# Require this file using `require "spec_helper"` to ensure that it is only
# loaded once.
require "bowling"
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
config.treat_symbols_as_metadata_keys_with_true_values = true
config.run_all_when_everything_filtered = true
config.filter_run :focus
# Run specs in random order to surface order dependencies. If you find an
# order dependency and want to debug it, you can fix the order by providing
# the seed, which is printed after each run.
# --seed 1234
config.order = 'random'
end
Now inside your bowling_spec.rb, add `require "spec_helper"
require "spec_helper"
class Bowling
def hit(pins)
end
def score
0
end
end
Also, any other specs you add you need to add require "spec_helper". The comments in spec_helper.rb explain why this is necessary.
Here is a good beginner explanation of setting up and working with rspec
Good luck
I'm a complete noob in ruby (coming from java) and had a similar problem to get rspec running.
The above answer helped to point the right way but did not work for me at first.
After reading the provided link i got it running with the following solution:
first run rspec --init.
then i edited the spec_helper.rb file with require_relative '../bowling'.
looked like this:
# This file was generated by the `rspec --init` command. Conventionally, all
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
# The generated `.rspec` file contains `--require spec_helper` which will cause this
# file to always be loaded, without a need to explicitly require it in any files.
#
# Given that it is always loaded, you are encouraged to keep this file as
# light-weight as possible. Requiring heavyweight dependencies from this file
# will add to the boot time of your test suite on EVERY test run, even for an
# individual file that may not need all of that loaded. Instead, consider making
# a separate helper file that requires the additional dependencies and performs
# the additional setup, and require it from the spec files that actually need it.
#
# The `.rspec` file also contains a few flags that are not defaults but that
# users commonly want.
#
require_relative '../bowling'
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
RSpec.configure do |config|
# rspec-expectations config goes here. You can use an alternate
# assertion/expectation library such as wrong or the stdlib/minitest
# assertions if you prefer.
config.expect_with :rspec do |expectations|
The other two files looked like this:
bowling_spec.rb:
# bowling_spec.rb
describe Bowling, "#score" do
it "returns 0 for all gutter game" do
bowling = Bowling.new
20.times { bowling.hit(0) }
bowling.score.should eq(0)
end
end
and bowling.rb:
# bowling.rb
class Bowling
def hit(pins)
end
def score
-1
end
end
That was enough. I found it strange that there is no hint in the docs to run rspec --init first to get it running.
Maybe something is wrong with my installation (rbenv ) so that i have to use require_relative ?

Where to put helper functions for rake tasks and test files in Ruby on Rails?

In my Rails application I have a file sample_data.rb inside /lib/tasks as well as a bunch of test files inside my /spec directory.
All these files often share common functionality such as:
def random_address
[Faker::Address.street_address, Faker::Address.city].join("\n")
end
Where should I put those helper functions? Is there some sort of convention on this?
Thanks for any help!
You could create a static class, with static functions. That would look something like this:
class HelperFunctions
def self.random_address
[Faker::Address.street_address, Faker::Address.city].join("\n")
end
def self.otherFunction
end
end
Then, all you would need to do is:
include your helper class in the file you want to use
execute it like:
HelperFunctions::random_address(anyParametersYouMightHave)
When doing this, make sure you include any dependencies in your HelperFunctions class.
If you're sure it's rake only specific, you also can add in directly in RAILS_ROOT/Rakefile (that's probably not the case for the example you use).
I use this to simplify rake's invoke syntax :
#!/usr/bin/env rake
# Add your own tasks in files placed in lib/tasks ending in .rake,
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
require File.expand_path('../config/application', __FILE__)
def invoke( task_name )
Rake::Task[ task_name ].invoke
end
MyApp::Application.load_tasks
That way, I can use invoke "my_namespace:my_task" in rake tasks instead of Rake::Task[ "my_namespace:my_task" ].invoke.
You share methods in a module, and you place such a module inside the lib folder.
Something like lib/fake_data.rb containing
module FakeData
def random_address
[Faker::Address.street_address, Faker::Address.city].join("\n")
end
module_function
end
and inside your rake task just require the module, and call FakeData.random_address.
But, if it is like a seed you need to do every time you run your tests, you should consider adding this to your general before all.
E.g. my spec_helper looks like this:
# Requires supporting ruby files with custom matchers and macros, etc,
# in spec/support/ and its subdirectories.
Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
RSpec.configure do |config|
config.use_transactional_fixtures = true
config.infer_base_class_for_anonymous_controllers = false
config.order = "random"
include SetupSupport
config.before(:all) do
load_db_seed
end
end
and the module SetupSupport is defined in spec/support/setup_support.rb and looks as follows:
module SetupSupport
def load_db_seed
load(File.join(Rails.root, 'db', 'seeds.rb'))
end
end
Not sure if you need to load the seeds, or are already doing this, but this is the ideal spot to also generate needed fake data.
Note that my setup support class is defined in spec/support because the code is only relevant to my specs, I have no rake task also needing the same code.

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.

How to call a method from a module of an other ruby file

I have to Ruby files: one contains a module with some methods for statistical calculation, in the other file I want to call one of the methods in the module.
How can I do that in Ruby?
Is that the right way?
require 'name of the file with the module'
a=[1,2,3,4]
a.method1
Require needs the absolute path to the file unless the file is located in one of Ruby's load paths. You can view the default load paths with puts $:. It is common to do one of the following to load a file:
Add the main file's directory to the load path and then use relative paths with require:
$: << File.dirname(__FILE__)
require "my_module"
Ruby 1.8 code that only loads a single file will often contain a one-liner like:
require File.expand_path("../my_module", __FILE__)
Ruby 1.9 added require_relative:
require_relative "my_module"
In the module you will need to define the methods as class methods, or use Module#module_function:
module MyModule
def self.method1 ary
...
end
def method2
...
end
module_function :method2
end
a = [1,2,3,4]
MyModule.method1(a)
Your way is correct if your module file is in the require search path.
If your module provide methods to be used by the object itself, you must do:
require 'name of the file with the module'
a=[1,2,3,4]
a.extend MyModule # here "a" can use the methods of MyModule
a.method1
See Object#extend.
Otherwise, if you'll use the methods directly by the module, you'll use:
MyModule.method1(a)

Rspec, mapping spec files to ruby files under test

What I want is a way of not having to 'require' the class under test in each spec file.
So hoping there is a means of setting the root of the source code under test and rspec automatically mapping my tests, or any other means of automatically mapping specs to ruby files.
In Rspec for rails this happens magically, but this is not a rails project and I can't find any useful information.
I am assuming you have a lib folder and a spec folder within your project where you have code and specs respectively. Create a spec/spec_helper.rb and add
# project_name/spec/spec_helper.rb
$: << File.join(File.dirname(__FILE__), "/../lib")
require 'spec'
require 'main_file_within_lib_folder_that_requires_other_files'
Now within your individual spec files now you just need to add the following line like rails
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
What you have to do is to redefine Object.const_missing.
Found this basic example, modify it to fit your needs (set the right path, etc.):
def Object.const_missing(name)
#looked_for ||= {}
str_name = name.to_s
raise "Class not found: #{name}" if #looked_for[str_name]
#looked_for[str_name] = 1
file = str_name.downcase
require file
klass = const_get(name)
return klass if klass
raise "Class not found: #{name}"
end

Resources