views:

81

answers:

2

I am looking at this boot.rb file:

http://github.com/bestbuyremix/BBYIDX/blob/master/config/boot.rb

And after trying to understand it, it is as if I have learned nothing so far.

Can someone detail what is going on here?

I have no idea how someone could even come up with this?

# Don't change this file!
# Configure your app in config/environment.rb and config/environments/*.rb

RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)

module Rails
  class << self
    def boot!
      unless booted?
        preinitialize
        pick_boot.run
      end
    end

    def booted?
      defined? Rails::Initializer
    end

    def pick_boot
      (vendor_rails? ? VendorBoot : GemBoot).new
    end

    def vendor_rails?
      File.exist?("#{RAILS_ROOT}/vendor/rails")
    end

    def preinitialize
      load(preinitializer_path) if File.exist?(preinitializer_path)
    end

    def preinitializer_path
      "#{RAILS_ROOT}/config/preinitializer.rb"
    end
  end

  class Boot
    def run
      load_initializer
      Rails::Initializer.run(:set_load_path)
    end
  end

  class VendorBoot < Boot
    def load_initializer
      require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
      Rails::Initializer.run(:install_gem_spec_stubs)
    end
  end

  class GemBoot < Boot
    def load_initializer
      self.class.load_rubygems
      load_rails_gem
      require 'initializer'
    end

    def load_rails_gem
      if version = self.class.gem_version
        gem 'rails', version
      else
        gem 'rails'
      end
    rescue Gem::LoadError => load_error
      $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
      exit 1
    end

    class << self
      def rubygems_version
        Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
      end

      def gem_version
        if defined? RAILS_GEM_VERSION
          RAILS_GEM_VERSION
        elsif ENV.include?('RAILS_GEM_VERSION')
          ENV['RAILS_GEM_VERSION']
        else
          parse_gem_version(read_environment_rb)
        end
      end

      def load_rubygems
        require 'rubygems'
        min_version = '1.1.1'
        unless rubygems_version >= min_version
          $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
          exit 1
        end

      rescue LoadError
        $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
        exit 1
      end

      def parse_gem_version(text)
        $1 if text =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~<>=]*\s*[\d.]+)["']/
      end

      private
        def read_environment_rb
          File.read("#{RAILS_ROOT}/config/environment.rb")
        end
    end
  end
end

# All that for this:
Rails.boot!
+2  A: 

What this is really doing is a bunch of fancy footwork to determine where the rails source code is.

You have the ability to 'freeze' your current rails gem source code into the vendor directory. This is useful when you might have more than one version of rails installed and want to make sure that your application is developed and run with that version only.

This code is checking to see if a version of rails has been frozen into the vendor directory, and if so, use that. If a frozen version isn't available it tries to use the local gems, but first makes sure they meet a minimum version requirement.

For more information on 'freezing' your gems, look at the descriptions of the rake tasks availble to your project with "rake -T".

TreyE
+1  A: 

If you are learning Rails, this is not the place to do it. Perhaps you have the thought that in order to use it, you need to understand how the code flows from the beginning? Don't do that. :)

If you're learning rails, use any of the many guides and tutorials to build a basic site.

As for this bit of code, some concepts that it employs involve ruby's iconic class << self Here is a critical read on meta classes: http://yehudakatz.com/2009/11/15/metaprogramming-in-ruby-its-all-about-the-self/

The Rails.boot! at the bottom leads you to the conclusion "the method boot! is called on the object Rails ... going back up to the top, you see

module Rails
   class << self
     def boot!
       unless booted?
       preinitialize
       pick_boot.run
     end
   end
 ...

Here you can see the magic behind class << self ... it created the boot! method on the module itself. from there you can trace the method call throughout the file, as it checks for the existence of a preinitializer file...

pick_boot returns an object, either VendorBoot or GemBoot depending on the result of vendor_rails? and then call the run method on it.

From there you have some standard class inheritance of the Boot classes, as it sets up the rest of the libraries. Hopefully that gets you started. :)

This is actually very good OO style... small methods and classes that all do a simple task. There's also OO inheritance and several common ruby idioms. All in all, a very good bit of ruby code. :)

Update

Here's a rough estimate of how it would look if coded in a more procedural style:

RAILS_ROOT = "#{File.dirname(__FILE__)}/.." unless defined?(RAILS_ROOT)

unless defined? Rails::Initializer
  preinitializer_path = "#{RAILS_ROOT}/config/preinitializer.rb"
  load() if File.exist?(preinitializer_path)
  if File.exist?("#{RAILS_ROOT}/vendor/rails")
    require "#{RAILS_ROOT}/vendor/rails/railties/lib/initializer"
    Rails::Initializer.run(:install_gem_spec_stubs)
    Rails::Initializer.run(:set_load_path)
  else
    begin
      require 'rubygems'
      min_version = '1.1.1'
      rubygems_version = Gem::RubyGemsVersion if defined? Gem::RubyGemsVersion
      unless rubygems_version >= min_version
        $stderr.puts %Q(Rails requires RubyGems >= #{min_version} (you have #{rubygems_version}). Please `gem update --system` and try again.)
        exit 1
      end

    rescue LoadError
      $stderr.puts %Q(Rails requires RubyGems >= #{min_version}. Please install RubyGems and try again: http://rubygems.rubyforge.org)
      exit 1
    end
    begin
      if defined? RAILS_GEM_VERSION
         version = RAILS_GEM_VERSION
      elsif ENV.include?('RAILS_GEM_VERSION')
        version =  ENV['RAILS_GEM_VERSION']
      else
         version = $1 if (File.read("#{RAILS_ROOT}/config/environment.rb")) =~ /^[^#]*RAILS_GEM_VERSION\s*=\s*["']([!~=]*\s*[\d.]+)["']/
      end
      if version
        gem 'rails', version
      else
        gem 'rails'
      end
    rescue Gem::LoadError => load_error
      $stderr.puts %(Missing the Rails #{version} gem. Please `gem install -v=#{version} rails`, update your RAILS_GEM_VERSION setting in config/environment.rb for the Rails version you do have installed, or comment out RAILS_GEM_VERSION to use the latest version installed.)
      exit 1
    end
    require 'initializer'
  end
end
DGM
Where's the inheritance?
banister
`class VendorBoot < Boot` .... That's not saying VendorBoot is less than Boot... ;)
DGM
class << self .. It's saying that every class is way less important than itself :P
TreyE