github
Advanced Search
  • Home
  • Pricing and Signup
  • Explore GitHub
  • Blog
  • Login

drnic / rubigen

  • Admin
  • Watch Unwatch
  • Fork
  • Your Fork
  • Pull Request
  • Download Source
    • 46
    • 13
  • Source
  • Commits
  • Network (13)
  • Issues (0)
  • Downloads (9)
  • Wiki (1)
  • Graphs
  • Branch: master

click here to add a description

click here to add a homepage

  • Branches (3)
    • gh-pages
    • gsub_file
    • master ✓
  • Tags (9)
    • REL-1.5.2
    • REL-1.5.1
    • REL-1.5.0
    • REL-1.4.0
    • REL-1.3.4
    • REL-1.3.3
    • REL-1.3.2
    • REL-1.3.1
    • REL-1.3.0
Sending Request…
Enable Donations

Pledgie Donations

Once activated, we'll place the following badge in your repository's detail box:
Pledgie_example
This service is courtesy of Pledgie.

RubiGen - generator framework for your framework — Read more

  cancel

http://drnic.github.com/rubigen

  cancel
  • Private
  • Read-Only
  • HTTP Read-Only

This URL has Read+Write access

Merge branch 'master' of git://github.com/windock/rubigen 
drnic (author)
Mon Nov 09 01:05:30 -0800 2009
commit  76ebc1bccf2b0ebc4c04241124faefaa8470fef3
tree    7f416ef39ecb9f8c0f26e812e6f5c638ecb4ca07
parent  a312c8973b08282f60dc94b6903f876ed99e33fb parent  b8422db8ccb32bf5b83816ca6a22e6c5447d23d5
rubigen / README.rdoc README.rdoc
100644 223 lines (163 sloc) 8.777 kb
edit raw blame history

RubiGen - Ruby Generator Framework

  • drnic.github.com/rubigen

DESCRIPTION:

A framework to allow Ruby applications to generate file/folder stubs (like the `rails` command does for Ruby on Rails, and the ‘script/generate’ command within a Rails application during development).

Background

RubiGen is originally extracted from Ruby on Rails (specifically the rails_generator from its railties gem).

The rails_generator was hardcoded with Rails-specific dependencies (`RAILS_ROOT`), Rails generators (‘app’ = Rails application; ‘model’ = Rails model+tests+migration), and generally assumed it was the only generator framework within the Ruby world (it was). So, any RubyGem whose name ended with ‘_generator’ was assumed to be a generator for a Rails application.

But if you are developing an Adhearsion application, then you may want a different set of generators. If you are developing a RubyGem, then you will want a different set of generators.

RubiGen exists to give different development environments their own generator framework.

Thanks go to…

Jeremy Kemper wrote the original Rails Generator, which is 95% of the basis of RubiGen. He’s awesome.

Installation

RubiGen is only required at development time, and normally isn’t required at deployment time (unless your application uses it to generate files at runtime).

On your development machine:

    sudo gem install rubigen

Usage

RubiGen comes with a stand-alone executable to allow you to invoke generators:

For example, to run the rails’ `model` generator:

    rubigen rails model Person name:string

would replace the normal

    script/generate model Person name:string

RubiGen has been traditionally integrated into another project, such as `rails`, `newgem` or `camping`, rather than be used on its own.

These frameworks might use RubiGen for two reasons:

  1. To generate an initial stub for developers, e.g. `rails` generated a stub to write a Rails application. `newgem` generates a stub to write a RubyGem. BTW - RubiGen has a builtin application `ruby_app` which generates a bare-bones Ruby application stub (lib, test, and script folders, plus a Rakefile, and a script/generate script)
  2. To generate components within their development areas, e.g. Rails had its `script/generate` script within each Rails application, which hooked back into the rails_generator to lookup and execute generators.

So, there are two steps to integrating RubiGen into your framework:

  1. Use it to generate an initial stub for the developers of your framework. This would create the folders (`lib/app`, `test`, `script`, `doc`, `log`, etc) and starting files (`Rakefile`, `README.txt`, `test/test_helper.rb` etc). Importantly, it would generate a `script/generate` file. The `script/generate` file (example below) will allow developers of your framework to generate components/extensions within the framework. RubiGen allows you to restrict which generators are available. For example, within RubyGem development environment (as generated by `newgem`), the `script/generator` only shows `rubygem`-related generators. Rails could restrict `script/generator` to only show Rails related generators
  2. Your framework RubyGem (e.g. `newgem` or `rails`) needs to add `rubigen` as a dependency, so that users of your RubyGem can access the generator framework.

Creating generators

There are two types of generators:

  1. Application Generators - used by developers of your framework to get started. Generally, you will create one Application Generator for your framework. It generates a base stub (such as the `rails` stub for new Rails applications) for your framework users.
  2. Component Generators - used by developers to extend their application. You may include 1+ built-in generators with your framework. Developers can also write generators for your framework, and like Rails’ generator install them in various places and have access to their via RubiGen.

Creating an Application Generator for your Framework

Without RubiGen, to give your users a head start and create a stub for them, you will copiously use `mkdir_p` and `File.open`. Your script will either be primitive (only create the bare folders and very few files) or it will be very long and unreadable (ok, perhaps I’m just talking about the `newgem` script, which I am dubiously responsible for… :P).

With RubiGen, you can create stubs using powerful, yet simple, syntax. Templates are extracted into a `templates` folder, and activating the generator from a script requires only a few lines of code.

These are the `newgem` files related to its Application Generator.

    bin/
      bin/newgem        # Appliction Generator script; Usage: newgem gemname [options]
    app_generators/
      app_generators/newgem/
        app_generators/newgem/newgem_generator.rb
        app_generators/newgem/USAGE
        app_generators/newgem/templates/
          app_generators/newgem/templates/app.rb
          app_generators/newgem/templates/History.txt
          app_generators/newgem/templates/... lots and lots of templates

The `bin/newgem` script is very simple, and looks like:

    require 'rubygems'
    require 'rubigen'

    if %w(-v --version).include? ARGV.first
      require 'newgem/version'
      puts "#{File.basename($0)} #{Newgem::VERSION}"
      exit(0)
    end

    require 'rubigen/scripts/generate'
    RubiGen::Base.use_application_sources!
    RubiGen::Scripts::Generate.new.run(ARGV, :generator => 'newgem')

You can copy and paste this for your own generator script, and place it in your RubyGem’s `bin` folder. Change `newgem` to your RubyGem’s name in the script above (and in all the folders listed above too)

NOTE: If you leave `newgem` there, then it will execute the `newgem_generator.rb` generator; as the generators are loaded from all RubyGem’s having `/app_generators` folders.

So, for your RubyGem, you need to keep the `/app_generators` folder (as you are creating an Application Generator, not a Component Generator), but change `newgem` to `your gem name` in all the subfolders and files. ESPECIALLY `newgem_generator.rb` -> `yourgem_generator.rb`, as this is how the generator is discovered (via `RubiGen::Base.use_application_sources!`).

All the generator work is performed within `yourgem_generator.rb`. A stub for it will be:

    require 'rbconfig'

    class YourgemGenerator < RubiGen::Base
      DEFAULT_SHEBANG = File.join(Config::CONFIG['bindir'],
                                  Config::CONFIG['ruby_install_name'])

      default_options   :shebang => DEFAULT_SHEBANG,
                        :an_option => 'some_default'

      attr_reader :app_name, :module_name

      def initialize(runtime_args, runtime_options = {})
        super
        usage if args.empty?
        @destination_root = args.shift
        @app_name     = File.basename(File.expand_path(@destination_root))
        @module_name  = app_name.camelize
        extract_options
      end

      def manifest
        # Use /usr/bin/env if no special shebang was specified
        script_options     = { :chmod => 0755, :shebang => options[:shebang] == DEFAULT_SHEBANG ? nil : options[:shebang] }
        windows            = (RUBY_PLATFORM =~ /dos|win32|cygwin/i) || (RUBY_PLATFORM =~ /(:?mswin|mingw)/)

        record do |m|
          # Root directory and all subdirectories.
          m.directory ''
          BASEDIRS.each { |path| m.directory path }

          # Root
          m.template_copy_each %w( Rakefile )
          m.file_copy_each     %w( README.txt )

          # Test helper
          m.template   "test_helper.rb",        "test/test_helper.rb"

          # Scripts
          %w( generate ).each do |file|
            m.template "script/#{file}",        "script/#{file}", script_options
            m.template "script/win_script.cmd", "script/#{file}.cmd",
              :assigns => { :filename => file } if windows
          end

        end
      end

      protected
        def banner
          <<-EOS
    Create a stub for #{File.basename $0} to get started.

    Usage: #{File.basename $0} /path/to/your/app [options]"
    EOS
        end

        def add_options!(opts)
          opts.separator ''
          opts.separator "#{File.basename $0} options:"
          opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
        end

      # Installation skeleton.  Intermediate directories are automatically
      # created so don't sweat their absence here.
      BASEDIRS = %w(
        doc
        lib
        log
        script
        test
        tmp
      )
    end

Easy peasy.

Creating a Component Generator for your Framework

Blog | Support | Training | Contact | API | Status | Twitter | Help | Security
© 2010 GitHub Inc. All rights reserved. | Terms of Service | Privacy Policy
Powered by the Dedicated Servers and
Cloud Computing of Rackspace Hosting®
Dedicated Server