Ruby anatomy

From wikinotes

Example

Sample Project

NOTE:

None of ruby bundler, ruby gems, ruby chruby set the $LOAD_PATH.
To add it automatically, you'll need to use something like direnv or nix.

NOTE:

You may also be interested in the examples section in ruby.
For example, ruby cli.

# project structure
myproject/
  lib/
    bar/baz.rb
    foo.rb
  test/
    foo_test.rb
  Gemfile
  .envrc

lib/bar/baz.rb


module Bar
  class Baz
    def initialize(name:)
      @name = name
    end

    def say_hi
      puts("hi, #{@name}")
    end
  end
end


lib/foo.rb


require 'bar/baz'

if __FILE__ == $0
    baz = Bar::Baz.new(name: "alex")
    baz.say_hi()
end


test/foo_test.rb


require 'foo'
require 'minitest/autorun'

class FooTest < Minitest::Test
  def test_constant_resolves
    assert(defined?(Foo))
  end
end


Gemfile


source 'https://rubygems.org'
gem 'minitest'
gem 'pry'


.envrc


export RUBYLIB="$(pwd)/lib:$RUBYLIB"


Setup

# allow env to be set by direnv
direnv allow

# use user-local gem cache
bundle config set --local path '~/.bundle'

Running 'foo.rb'

# '-I lib' sets the $LOAD_PATH so that the module can be found
ruby -I lib lib/foo.rb

Running 'foo_test.rb'

ruby -I.:test test/foo_test.rb

$RUBYLIB and $LOAD_PATH

Instead of ruby -I lib ... you can use another tool to setup the $LOAD_PATH.

direnv can set the environment $RUBYLIB

# myproject/.envrc

export RUBYLIB="$(pwd)/lib:$RUBYLIB"

nix can manage the environment as well

basics

RUBY_VERSION()       # ruby version
RUBY_PATCHLEVEL()    # ruby patch revision
RUBY_DESCRIPTION()   # ruby version
3.times {puts "hi"}  # loop 3 times

reflection

myclass = MyClass.new()

myclass.methods                   # print all methods
myclass.methods - Object.methods  # print non-object methods
myclass.class                     # type

myclass.__FILE__                               # file class belongs to
instance.method(:method_name).source_location  # file method is defined in (nil means compiled)

MyModule.constants.select {|c| MyModule.const_get(c).is_a? Class}  # list all classes within a namespace

# files module is defined in
$LOADED_FEATURES.select { |file| File.read(file).include?('module Foo') rescue false }

builtins

Keywords/functions/types built in to ruby are defined within the Kernel module.

Find common types/functions like:

  • at_exit
  • open
  • Integer
  • ...

How to read API Docs

Ruby documentation can be difficult to browse.
In order to determine the scope you must browse:

  • class inheritance hierarchy
  • includes/extends
  • parent-hierarchy's includes/extends
  • includes/extends parent hierarchy


Try using ruby pry instead:

  • ls (show methods/attrs by namespace/class)
  • show-source -ld <method> (show docs/sourcecode)