I’m playing with Ruby. As a dynamic language, it is one of the programming languages to explore. I like plain Ruby, and write small programs using TDD (see my video in Anglish Playing with Ruby).
Now, I want to explore Ruby on Rails. It’s not in my comfort zone, because I think it is a “big project”, now in version 4.0. But it could be interesting to see how easy or convoluted could be to program using Rails, and to study the internal implementation.
So, in my Windows machine, some weeks ago, I installed Rails 4.x, using
gem install rails --no-rdoc --no-ri
I added –no-rdoc, –no-ri to skip the generation of local documentation.
It was a long output, see the gems that were installed:
Fetching: i18n-0.6.5.gem (100%) Fetching: tzinfo-0.3.37.gem (100%) Fetching: minitest-4.7.5.gem (100%) Fetching: atomic-1.1.14.gem (100%) Temporarily enhancing PATH to include DevKit... Building native extensions. This could take a while... Fetching: thread_safe-0.1.3.gem (100%) Fetching: activesupport-4.0.0.gem (100%) Fetching: builder-3.1.4.gem (100%) Fetching: actionpack-4.0.0.gem (100%) Fetching: activemodel-4.0.0.gem (100%) Fetching: arel-4.0.0.gem (100%) Fetching: activerecord-deprecated_finders-1.0.3.gem (100%) Fetching: activerecord-4.0.0.gem (100%) Fetching: mail-2.5.4.gem (100%) Fetching: actionmailer-4.0.0.gem (100%) Fetching: thor-0.18.1.gem (100%) Fetching: railties-4.0.0.gem (100%) Fetching: bundler-1.3.5.gem (100%) Fetching: sprockets-2.10.0.gem (100%) Fetching: sprockets-rails-2.0.0.gem (100%) Fetching: rails-4.0.0.gem (100%) Successfully installed i18n-0.6.5 Successfully installed tzinfo-0.3.37 Successfully installed minitest-4.7.5 Successfully installed atomic-1.1.14 Successfully installed thread_safe-0.1.3 Successfully installed activesupport-4.0.0 Successfully installed builder-3.1.4 Successfully installed actionpack-4.0.0 Successfully installed activemodel-4.0.0 Successfully installed arel-4.0.0 Successfully installed activerecord-deprecated_finders-1.0.3 Successfully installed activerecord-4.0.0 Successfully installed mail-2.5.4 Successfully installed actionmailer-4.0.0 Successfully installed thor-0.18.1 Successfully installed railties-4.0.0 Successfully installed bundler-1.3.5 Successfully installed sprockets-2.10.0 Successfully installed sprockets-rails-2.0.0 Successfully installed rails-4.0.0 20 gems installed
It is interesting to note there were native extensions, something to explore.
Now, the rails command is in my path. How the install program added the command? Simply. If you have Ruby in your path, you have the bin folder in that list of directories. In my case, c:\Ruby193\bin. Every gem that has global commands, can put in that folder new files. In my case, rails, and rails.bat.
This is the content of the .bat file:
@ECHO OFF IF NOT "%~f0" == "~f0" GOTO :WinNT @"ruby.exe" "C:/Ruby193/bin/rails" %1 %2 %3 %4 %5 %6 %7 %8 %9 GOTO :EOF :WinNT @"ruby.exe" "%~dpn0" %*
It detects if it can use or not a ‘cmd trick’, see
It launch the ‘rails’ file in the same bin directory, using ruby.exe. The rails file has:
#!C:/Ruby193/bin/ruby.exe # # This file was generated by RubyGems. # # The application 'railties' is installed as part of a gem, and # this file is here to facilitate running it. # require 'rubygems' version = ">= 0" if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then version = $1 ARGV.shift end gem 'railties', version load Gem.bin_path('railties', 'rails', version)
It use rubygems, the Ruby packaging system, see:
It imports, not directly rails, but railties, using the gem method.
The Gem.bin_path returns the path for ‘railties’, see
In my case, the bin-path returns ‘c:\Ruby193\lib\ruby\gems\1.9.1\railties-4.0.0\bin\rails’. The second parameter ‘rails’ indicates the script to run. It is executed using the ‘load’ command:
load(filename, wrap=false) ? true
Loads and executes the Ruby program in the file filename. If the filename does not resolve to an absolute path, the file is searched for in the library directories listed in $:. If the optional wrap parameter is true, the loaded script will be executed under an anonymous module, protecting the calling program’s global namespace. In no circumstance will any local variables in the loaded file be propagated to the loading environment.
I should study the difference with ‘require’:
require(name) ? true or false
Loads the given name, returning true if successful and false if the feature is already loaded.
If the filename does not resolve to an absolute path, it will be searched for in the directories listed in $LOAD_PATH ($:).
If the filename has the extension “.rb”, it is loaded as a source file; if the extension is “.so”, “.o”, or “.dll”, or the default shared library extension on the current platform, Ruby loads the shared library as a Ruby extension. Otherwise, Ruby tries adding “.rb”, “.so”, and so on to the name until found. If the file named cannot be found, a LoadError will be raised.
For Ruby extensions the filename given may use any shared library extension. For example, on Linux the socket extension is “socket.so” and require ‘socket.dll’ will load the socket extension.
The absolute path of the loaded file is added to $LOADED_FEATURES ($"). A file will not be loaded again if its path already appears in $". For example, require ‘a’; require ‘./a’ will not load a.rb again.
Any constants or globals within the loaded source file will be available in the calling program’s global namespace. However, local variables will not be propagated to the loading environment.
That ‘rails’ file contains:
#!/usr/bin/env ruby git_path = File.join(File.expand_path('../../..', __FILE__), '.git') if File.exists?(git_path) railties_path = File.expand_path('../../lib', __FILE__) $:.unshift(railties_path) end require "rails/cli"
Apparently, the gem loader alters the require path, and the require of ‘rails/cli’ is resolved to ‘c:\Ruby193\lib\ruby\gems\1.9.1\railties-4.0.0\lib\rails’.
Ok, enough for today. Next steps: explore the load of rails, parameters, and create a site.
Angel "Java" Lopez