Up until this section, differences I’ve shown you between Ruby and PHP has been largely 1:1. Sure there are some syntatic sweetness to Ruby and a slightly different structure to commands because of it’s OOP approach to all the things.

Namespacing will be the first big diverage from what you expect.

Like before, let’s start with a PHP interpretation of Namespacing that we both know and love.

Let us assume we have a PSR-4 defined namespace, and our composer.json file says so:

{
    "name": "dylanpierce/examples",
    "require": {},
    "authors": [
        {
            "name": "Dylan Pierce",
            "email": "me@dylanjpierce.com"
        }
    ],
    "autoload": {
        "psr-4": {
            "PHPtoRuby\\": "app/"
        }
    }
}

Then let’s assume we have a lovely Cat.php inside of our app directory. So you can find Cat at app/Cat.php.

Since we’re adding Cat to the PHPtoRuby namespace, we have to update our Cat.php file to be included in that namespace:

// this is the contents of app/Cat.php

// we need to define that we're inside of the PHPtoRuby namespace now.
namespace PHPtoRuby;

class Cat {
  public function meow() {
    echo 'meow';
  }
}

Finally we run composer dump which will read the psr-4 entry and autoload our Cat class inside of our defined PHPtoRuby namespace:

// this is the contents of index.php

// Autoload the things:
require __DIR__ . '/vendor/autoload.php';

use PHPtoRuby\Cat;

$cat = new Cat;
$cat->meow();

=> 'meow'

Namespaces in Ruby

Just to clear up a misconception right off the bat, there is no dedicated namespace keyword concept in Ruby. But don’t fret, you can achieve the goal of namespacing in Ruby, which is to organize bunches of classes.

Maybe you’re starting to catch onto the overall theme so far, but there are actually muliple ways to achieve code organization in Ruby. It’s not so straightforward as PHP were we’re given one builtin option to modularize our code into “namespaces”.

Ah, great segway Dylan - yes the functionality we’re aiming for is modularization. We want to break up classes into clumps that make sense. One of my favorite ways of doing this was taught to me from my friend Frank (hi Frank) with the namespace by the context of the current user.

Say that your regular users have access to look up Pets in our Peer-to-Peer cat & dog sitting service called PetMyPets.

So you could have a group of classes devoted to controlling the pages and business logic for unauthenticated guests to the site:

PetMyPets\Front\Controllers\PetsController

Since there’s a slighty different context for owners of pets, where they can manage their pet’s profiles on the site it would belong to a different namespace called “Owner”:

PetMyPets\Owner\Controllers\PetsController

Lastly there could be another section of the site that’s reserved just for Administrators of the site, so they can moderate Pet profile listings and remove spam postings, etc:

PetMyPets\Admin\Controllers\PetsController

Let’s return to our Ruby-ifed Cat class:


class Cat
  def meow
    puts 'meow'
  end
end

Just for practice, let’s add a namespace around our Cat so we can isolate all of our local PHPtoRuby code in the same module:


module PHPtoRuby
  class Cat
    def meow
      puts 'meow' 
    end
  end
end

# Notice the namespacing separation isn't a '\' character
# it's actually '::' in Ruby
cat = PHPtoRuby::Cat.new
cat.meow

=> 'meow'

Let’s break this down into 2 major differences:

  1. The module wraps the entire class

You can think of the module almost like a PHP trait and a namespace mushed into one concept.

Like a namespace, it allows us to place multiple classes inside of it:


# import_cars/civic.rb

module ImportCars
  class Civic
    def miles_per_gallon
      30
    end
  end
end

civic = ImportCars::Civic.new


# import_cars/corolla.rb

module ImportCars
  class Corolla
    def miles_per_gallon
      32
    end
  end
end

corolla = ImportCars::Corolla.new

  1. A module cannot be instantiated

Just like a PHP trait a module cannot be instantiated on it’s own:


# indoor_cats.rb

module IndoorCats
  # crickets
end

=> indoor_cats = IndoorCats.new
*** NoMethodError Exception: undefined method `new' for IndoorCats:Module

trait IndoorCats {

}

$indoorCats = new IndoorCats;
=> Fatal error: Uncaught Error: Cannot instantiate trait IndoorCats in /home/pierce/projects/php_to_ruby/examples/IndoorCats.php:7
=> 

PHP’s Traits and Ruby’s Modules are more common than they lead on. We’ll cover more of that the Advanced Object Oriented Programming section.

But now you can see how Ruby’s interpretation of namespacing code and how it stacks up to PHP.