PHP Namespacing vs Ruby Modules
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:
Finally we run composer dump
which will read the psr-4
entry and autoload our Cat
class inside of our defined PHPtoRuby
namespace:
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:
- 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
- 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
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.