`require`ing files in a common codebase - ruby

I'm new to writing big Ruby projects (only mods and application scripting till now). I've made a project with some files in the project root and others in subfolders, including a "Test" folder.
So far I've tried:
Adding all folders and subfolders to the load path in RubyMine.
Declaring all the files to be part of the same module.
I've thought of using require_relative for loading all files needed but it seems tiresome and very Java-esque... Is there a better way?

Here is an example of a typical folder structure, its modules and how to include everything into the library. You would then only need to require 'lib' wherever you want to pull in the library for use.
# Root folder structure of project
lib.rb
./lib/a.rb
./lib/b.rb
./lib/b/c.rb
# lib.rb
require 'lib/a'
require 'lib/b'
module Lib
end
# ./lib/a.rb
module Lib
module A
end
end
# ./lib/b.rb
require 'lib/b/c'
module Lib
module B
end
end
# ./lib/b/c.rb
module Lib
module B
module C
end
end
end

Related

Should Rspec file structure match file structure of code being tested?

I am writing a gem. I want to test some of the classes. I have them in modules.
The file structure:
my_gem
/lib
/my_gem
/practices
/texas
/medical_practice.rb
medical_practice.rb:
module MyGem
module Practices
module Texas
class MedicalPractice < Practice
end
end
end
end
In my spec directory, should I follow the same structure?
spec
/practices
/texas
/medical_practice_spec.rb
Or is it best practice to place medical_practice_spec.rb right under the /spec directory?
In my spec directory, should I follow the same structure?
Yes.
Usually in RSpec the spec structure matches the directory structure of the files under test.
Another example (when using Rails):
spec/controllers/users_controller_spec.rb would test app/controllers/users_controller.rb

Ruby 1.9.3: import all files in a given directory

I am having trouble import all of the .rb files I need from a given directory, I know this question has been asked a lot but none of the earlier posts seem to solve my problem.
Here is my directory structure:
- Docs
- Lexer
- Parser
--> Parser.rb
- SyntaxTree
--> I want all the .rb files from here
--> Sets.rb (Module I want to import)
--> EMPTY_SET (constant I want to reference)
- Test
<Main Program>
I am currently working in Parser.rb and I need to get all of the .rb files from the SyntaxTree directory so I can reference them inside of Parser.rb. I also want to import the Sets module that is contained in Sets.rb.
Here is my current way of trying to import all of the ruby files that I saw in most of the previous posts:
Dir['../SyntaxTree/*.rb'].each {|file| require file}
I also tried:
Dir['../SyntaxTree/*.rb'].each {|file| require_relative file}
With either of these method I still get errors when trying to include the Sets module:
class Parser
include Sets
.
.
end
`<class:Parser>': uninitialized constant Parser::Sets (NameError)
If I directly include Sets.rb the error goes away
Any ideas would be very helpful.
The best approach is to set up proper autoload dependencies within your modules so that the required classes are loaded on demand. If you simply load all of the files in using require, it won't be obvious which order they have to be loaded based on filenames and any inter-dependenceies are not resolved.
This is why having a top-level namespace for your application can help. Example:
module MyApp
autoload(:Parser, 'my_app/parser')
autoload(:Sets, 'my_app/sets')
end
Now those classes should load automatically on-demand.

Make folder/scripts autoloadable in rails 3

I have downloaded a gem and cuztomized few of its methods and placed it in scripts folder. How do I auto load those scripts instead of requiring them in every controller/other scripts that I need.
lib folder is the place to put those files. Then you should edit your config/application.rb file to configure auto load paths like this:
# Custom directories with classes and modules you want to be autoloadable.
config.autoload_paths += %W(#{config.root}/lib)

Including a Ruby class from a separate file

For a while I had been including an entire class inside of a Ruby module. Apparently this is not what I am supposed to do. It appears that the point of a module is to store functions which can then be included as methods in a new class.
I don't want this. I have a class that I want to keep in a separate file which I can access from other files. How can I do this?
Thanks.
Modules serve a dual purpose as a holder for functions and as a namespace. Keeping classes in modules is perfectly acceptable. To put a class in a separate file, just define the class as usual and then in the file where you wish to use the class, simply put require 'name_of_file_with_class' at the top. For instance, if I defined class Foo in foo.rb, in bar.rb I would have the line require 'foo'.
If you are using Rails, this include often happens automagically
Edit: clarification of file layout
#file: foo.rb
class Foo
def initialize
puts "foo"
end
end
...
#file: bar.rb
require 'foo'
Foo.new
If you are in Rails, put these classes in lib/ and use the naming convention for the files of lowercase underscored version of the class name, e.g. Foo -> foo.rb, FooBar -> foo_bar.rb, etc.
As of ruby version 1.9 you can use require_relative, to require files relatively to the file you are editing.
You can also use load. Also you use require relative if the file is in the same directory. Read this link for further understanding: http://rubylearning.com/satishtalim/including_other_files_in_ruby.html
When Using Require, inside the string indicate the full path name of the class you are refereing to unless its in the Root Folder of Ruby
MyApp
|_ app
|_ bin
|_ etc, etc
root_level_file.rb
You can just do:
require './root_level_file'.
RootLevelFile.new

Directory layout for pure Ruby project

I'm starting to learn ruby. I'm also a day-to-day C++ dev.
For C++ projects I usually go with following dir structure
/
-/bin <- built binaries
-/build <- build time temporary object (eg. .obj, cmake intermediates)
-/doc <- manuals and/or Doxygen docs
-/src
--/module-1
--/module-2
-- non module specific sources, like main.cpp
- IDE project files (.sln), etc.
What dir layout for Ruby (non-Rails, non-Merb) would you suggest to keep it clean, simple and maintainable?
As of 2011, it is common to use jeweler instead of newgem as the latter is effectively abandoned.
Bundler includes the necessary infrastructure to generate a gem:
$ bundle gem --coc --mit --test=minitest --exe spider
Creating gem 'spider'...
MIT License enabled in config
Code of conduct enabled in config
create spider/Gemfile
create spider/lib/spider.rb
create spider/lib/spider/version.rb
create spider/spider.gemspec
create spider/Rakefile
create spider/README.md
create spider/bin/console
create spider/bin/setup
create spider/.gitignore
create spider/.travis.yml
create spider/test/test_helper.rb
create spider/test/spider_test.rb
create spider/LICENSE.txt
create spider/CODE_OF_CONDUCT.md
create spider/exe/spider
Initializing git repo in /Users/francois/Projects/spider
Gem 'spider' was successfully created. For more information on making a RubyGem visit https://bundler.io/guides/creating_gem.html
Then, in lib/, you create modules as needed:
lib/
spider/
base.rb
crawler/
base.rb
spider.rb
require "spider/base"
require "crawler/base"
Read the manual page for bundle gem for details on the --coc, --exe and --mit options.
The core structure of a standard Ruby project is basically:
lib/
foo.rb
foo/
share/
foo/
test/
helper.rb
test_foo.rb
HISTORY.md (or CHANGELOG.md)
LICENSE.txt
README.md
foo.gemspec
The share/ is rare and is sometimes called data/ instead. It is for general purpose non-ruby files. Most projects don't need it, but even when they do many times everything is just kept in lib/, though that is probably not best practice.
The test/ directory might be called spec/ if BDD is being used instead of TDD, though you might also see features/ if Cucumber is used, or demo/ if QED is used.
These days foo.gemspec can just be .gemspec --especially if it is not manually maintained.
If your project has command line executables, then add:
bin/
foo
man/
foo.1
foo.1.md or foo.1.ronn
In addition, most Ruby project's have:
Gemfile
Rakefile
The Gemfile is for using Bundler, and the Rakefile is for Rake build tool. But there are other options if you would like to use different tools.
A few other not-so-uncommon files:
VERSION
MANIFEST
The VERSION file just contains the current version number. And the MANIFEST (or Manifest.txt) contains a list of files to be included in the project's package file(s) (e.g. gem package).
What else you might see, but usage is sporadic:
config/
doc/ (or docs/)
script/
log/
pkg/
task/ (or tasks/)
vendor/
web/ (or site/)
Where config/ contains various configuration files; doc/ contains either generated documentation, e.g. RDoc, or sometimes manually maintained documentation; script/ contains shell scripts for use by the project; log/ contains generated project logs, e.g. test coverage reports; pkg/ holds generated package files, e.g. foo-1.0.0.gem; task/ could hold various task files such as foo.rake or foo.watchr; vendor/ contains copies of the other projects, e.g. git submodules; and finally web/ contains the project's website files.
Then some tool specific files that are also relatively common:
.document
.gitignore
.yardopts
.travis.yml
They are fairly self-explanatory.
Finally, I will add that I personally add a .index file and a var/ directory to build that file (search for "Rubyworks Indexer" for more about that) and often have a work directory, something like:
work/
NOTES.md
consider/
reference/
sandbox/
Just sort of a scrapyard for development purposes.
#Dentharg: your "include one to include all sub-parts" is a common pattern. Like anything, it has its advantages (easy to get the things you want) and its disadvantages (the many includes can pollute namespaces and you have no control over them). Your pattern looks like this:
- src/
some_ruby_file.rb:
require 'spider'
Spider.do_something
+ doc/
- lib/
- spider/
spider.rb:
$: << File.expand_path(File.dirname(__FILE__))
module Spider
# anything that needs to be done before including submodules
end
require 'spider/some_helper'
require 'spider/some/other_helper'
...
I might recommend this to allow a little more control:
- src/
some_ruby_file.rb:
require 'spider'
Spider.include_all
Spider.do_something
+ doc/
- lib
- spider/
spider.rb:
$: << File.expand_path(File.dirname(__FILE__))
module Spider
def self.include_all
require 'spider/some_helper'
require 'spider/some/other_helper'
...
end
end
Why not use just the same layout? Normally you won't need build because there's no compilation step, but the rest seems OK to me.
I'm not sure what you mean by a module but if it's just a single class a separate folder wouldn't be necessary and if there's more than one file you normally write a module-1.rb file (at the name level as the module-1 folder) that does nothing more than require everything in module-1/.
Oh, and I would suggest using Rake for the management tasks (instead of make).
I would stick to something similar to what you are familiar with: there's no point being a stranger in your own project directory. :-)
Typical things I always have are lib|src, bin, test.
(I dislike these monster generators: the first thing I want to do with a new project is get some code down, not write a README, docs, etc.!)
So I went with newgem.
I removed all unnecessary RubyForge/gem stuff (hoe, setup, etc.), created git repo, imported project into NetBeans. All took 20 minutes and everything's on green.
That even gave me a basic rake task for spec files.
Thank you all.

Resources