Class: RubiGen::Commands::Create

### Home Classes Methods

### In Files

- lib/rubigen/commands.rb

### Parent

RubiGen::Commands::Base

### Methods

- #class_collisions
- #complex_template
- #directory
- #file
- #file_copy_each
- #folder
- #identical?
- #migration_template
- #readme
- #route_resources
- #template
- #template_copy_each
- #write_manifest

### Files

- History.txt
- License.txt
- Manifest.txt
- Todo.txt
- README.txt
- index.txt
- version-raw.txt
- version.txt

### Class/Module Index

Quicksearch

- RubiGen
- RubiGen::AbstractGemSource
- RubiGen::Base
- RubiGen::Commands
- RubiGen::Commands::Base
- RubiGen::Commands::Create
- RubiGen::Commands::Destroy
- RubiGen::Commands::List
- RubiGen::Commands::RewindBase
- RubiGen::Commands::Update
- RubiGen::GemPathSource
- RubiGen::GeneratedAttribute
- RubiGen::GeneratorError
- RubiGen::GeneratorTestHelper
- RubiGen::Lookup
- RubiGen::Lookup::ClassMethods
- RubiGen::Manifest
- RubiGen::Options
- RubiGen::Options::ClassMethods
- RubiGen::PathFilteredSource
- RubiGen::PathSource
- RubiGen::Scripts
- RubiGen::Scripts::Base
- RubiGen::Scripts::Destroy
- RubiGen::Scripts::Generate
- RubiGen::Scripts::Update
- RubiGen::Source
- RubiGen::Spec
- RubiGen::UsageError
- Rubigen
- Rubigen::CLI
- Dir
- Object

No matching classes.

# RubiGen::Commands::Create

Create is the premier generator command. It copies files, creates directories, renders templates, and more.

### Constants

SYNONYM_LOOKUP_URI

### Public Instance Methods

class_collisions(*class_names) click to toggle source

Check whether the given class names are already taken. In the future, expand to check other namespaces such as the rest of the user's app.

    # File lib/rubigen/commands.rb, line 180
    def class_collisions(*class_names)
      class_names.flatten.each do |class_name|
        # Convert to string to allow symbol arguments.
        class_name = class_name.to_s

        # Skip empty strings.
        next if class_name.strip.empty?

        # Split the class from its module nesting.
        nesting = class_name.split('::')
        name = nesting.pop

        # Extract the last Module in the nesting.
        last = nesting.inject(Object) { |last, nest|
          break unless last.const_defined?(nest)
          last.const_get(nest)
        }

        # If the last Module exists, check whether the given
        # class exists and raise a collision if so.
        if last and last.const_defined?(name.camelize)
          raise_class_collision(class_name)
        end
      end
    end

complex_template(relative_source, relative_destination, template_options = {}) click to toggle source

    # File lib/rubigen/commands.rb, line 335
    def complex_template(relative_source, relative_destination, template_options = {})
      options = template_options.dup
      options[:assigns] ||= {}
      options[:assigns]['template_for_inclusion'] = render_template_part(template_options)
      template(relative_source, relative_destination, options)
    end

directory(relative_path) click to toggle source

Create a directory including any missing parent directories. Always skips directories which exist.

    # File lib/rubigen/commands.rb, line 344
    def directory(relative_path)
      path = destination_path(relative_path)
      if File.exist?(path)
        logger.exists relative_path
      else
        logger.create relative_path
        unless options[:pretend]
          FileUtils.mkdir_p(path)
          # git doesn't require adding the paths, adding the files later will
          # automatically do a path add.

          # Subversion doesn't do path adds, so we need to add
          # each directory individually.
          # So stack up the directory tree and add the paths to
          # subversion in order without recursion.
          if options[:svn]
            stack = [relative_path]
            until File.dirname(stack.last) == stack.last # dirname('.') == '.'
              stack.push File.dirname(stack.last)
            end
            stack.reverse_each do |rel_path|
              svn_path = destination_path(rel_path)
              system("svn add -N #{svn_path}") unless File.directory?(File.join(svn_path, '.svn'))
            end
          end
        end
      end
    end

file(relative_source, relative_destination, file_options = {}, &block) click to toggle source

Copy a file from source to destination with collision checking.

The file_options hash accepts :chmod and :shebang and :collision options. :chmod sets the permissions of the destination file:

    file 'config/empty.log', 'log/test.log', :chmod => 0664

:shebang sets the #!/usr/bin/ruby line for scripts

    file 'bin/generate.rb', 'script/generate', :chmod => 0755, :shebang => '/usr/bin/env ruby'

:collision sets the collision option only for the destination file:

    file 'settings/server.yml', 'config/server.yml', :collision => :skip

Collisions are handled by checking whether the destination file exists and either skipping the file, forcing overwrite, or asking the user what to do.

    # File lib/rubigen/commands.rb, line 219
    def file(relative_source, relative_destination, file_options = {}, &block)
      # Determine full paths for source and destination files.
      source              = source_path(relative_source)
      destination         = destination_path(relative_destination)
      destination_exists  = File.exist?(destination)

      # If source and destination are identical then we're done.
      if destination_exists and identical?(source, destination, &block)
        return logger.identical(relative_destination)
      end

      # Check for and resolve file collisions.
      if destination_exists

        # Make a choice whether to overwrite the file.  :force and
        # :skip already have their mind made up, but give :ask a shot.
        choice = case (file_options[:collision] || options[:collision]).to_sym #|| :ask
          when :ask   then force_file_collision?(relative_destination, source, destination, file_options, &block)
          when :force then :force
          when :skip  then :skip
          else raise "Invalid collision option: #{options[:collision].inspect}"
        end

        # Take action based on our choice.  Bail out if we chose to
        # skip the file; otherwise, log our transgression and continue.
        case choice
          when :force then logger.force(relative_destination)
          when :skip  then return(logger.skip(relative_destination))
          else raise "Invalid collision choice: #{choice}.inspect"
        end

      # File doesn't exist so log its unbesmirched creation.
      else
        logger.create relative_destination
      end

      # If we're pretending, back off now.
      return if options[:pretend]

      # Write destination file with optional shebang.  Yield for content
      # if block given so templaters may render the source file.  If a
      # shebang is requested, replace the existing shebang or insert a
      # new one.
      File.open(destination, 'wb') do |dest|
        dest.write render_file(source, file_options, &block)
      end

      # Optionally change permissions.
      if file_options[:chmod]
        FileUtils.chmod(file_options[:chmod], destination)
      end

      # Optionally add file to subversion or git
      system("svn add #{destination}") if options[:svn]
    end

file_copy_each(files, path=nil, options = {}) click to toggle source

    # File lib/rubigen/commands.rb, line 275
    def file_copy_each(files, path=nil, options = {})
      path = path ? "#{path}/" : ""
      files.each do |file_name|
        file "#{path}#{file_name}", "#{path}#{file_name}", options
      end
    end

folder(template_path, path=nil, options = {}) click to toggle source

    # File lib/rubigen/commands.rb, line 282
    def folder(template_path, path=nil, options = {})
      template_path = "/" if template_path.blank?
      source = source_path(template_path)
      files  = Dir[source + '/*'].select { |file| File.file? file }.map { |file| file.sub(/^#{source}/,"") }
      files.each do |file_name|
        file "#{template_path}#{file_name}", "#{path}#{file_name}", options
      end
      system("git add -v #{relative_destination}") if options[:git]
    end

identical?(source, destination, &block) click to toggle source

Checks if the source and the destination file are identical. If passed a block then the source file is a template that needs to first be evaluated before being compared to the destination.

    # File lib/rubigen/commands.rb, line 295
    def identical?(source, destination, &block)
      return false if File.directory? destination
      source      = block_given? ? File.open(source) {|sf| yield(sf)} : IO.read(source)
      destination = IO.read(destination)
      source == destination
    end

migration_template(relative_source, relative_destination, template_options = {}) click to toggle source

When creating a migration, it knows to find the first available file in db/migrate and use the migration.rb template.

    # File lib/rubigen/commands.rb, line 419
    def migration_template(relative_source, relative_destination, template_options = {})
      migration_directory relative_destination
      migration_file_name = template_options[:migration_file_name] || file_name
      raise "Another migration is already named #{migration_file_name}: #{existing_migrations(migration_file_name).first}" if migration_exists?(migration_file_name)
      template(relative_source, "#{relative_destination}/#{next_migration_string}_#{migration_file_name}.rb", template_options)
    end

readme(*relative_sources) click to toggle source

Display a README.

    # File lib/rubigen/commands.rb, line 374
    def readme(*relative_sources)
      relative_sources.flatten.each do |relative_source|
        logger.readme relative_source
        stdout.puts File.read(source_path(relative_source)) unless options[:pretend]
      end
    end

route_resources(*resources) click to toggle source

    # File lib/rubigen/commands.rb, line 426
    def route_resources(*resources)
      resource_list = resources.map { |r| r.to_sym.inspect }.join(', ')
      sentinel = 'ActionController::Routing::Routes.draw do |map|'

      logger.route "map.resources #{resource_list}"
      unless options[:pretend]
        gsub_file 'config/routes.rb', /(#{Regexp.escape(sentinel)})/i do |match|
          "#{match}\n  map.resources #{resource_list}\n"
        end
      end
    end

template(relative_source, relative_destination, template_options = {}) click to toggle source

Generate a file using an ERuby template. Looks up and evaluates a template by name and writes the result.

The ERB template uses explicit trim mode to best control the proliferation of whitespace in generated code. <%- trims leading whitespace; -%> trims trailing whitespace including one newline.

A hash of template options may be passed as the last argument. The options accepted by the file are accepted as well as :assigns, a hash of variable bindings. Example:

    template 'foo', 'bar', :assigns => { :action => 'view' }

Template is implemented in terms of file. It calls file with a block which takes a file handle and returns its rendered contents.

    # File lib/rubigen/commands.rb, line 316
    def template(relative_source, relative_destination, template_options = {})
      file(relative_source, relative_destination, template_options) do |file|
        # Evaluate any assignments in a temporary, throwaway binding.
        vars = template_options[:assigns] || {}
        b = binding
        vars.each { |k,v| eval "#{k} = vars[:#{k}] || vars['#{k}']", b }

        # Render the source file with the temporary binding.
        ERB.new(file.read, nil, '-').result(b)
      end
    end

template_copy_each(files, path = nil, options = {}) click to toggle source

    # File lib/rubigen/commands.rb, line 328
    def template_copy_each(files, path = nil, options = {})
      path = path ? "#{path}/" : ""
      files.each do |file_name|
        template "#{path}#{file_name}", "#{path}#{file_name.gsub(/\.erb$/,'')}", options
      end
    end

write_manifest(relative_destination) click to toggle source

    # File lib/rubigen/commands.rb, line 381
    def write_manifest(relative_destination)
      files = ([relative_destination] + Dir["#{destination_root}/**/*"])
      files.reject! { |file| File.directory?(file) }
      files.map! { |path| path.sub("#{destination_root}/","") }
      files = files.uniq.sort

      destination         = destination_path(relative_destination)
      destination_exists  = File.exists?(destination)

      # Check for and resolve file collisions.
      if destination_exists
        # Always recreate the Manifest (perhaps we need to give the option... like normal files)
        choice = :force
        logger.force(relative_destination)

      # File doesn't exist so log its unbesmirched creation.
      else
        logger.create relative_destination
      end

      # If we're pretending, back off now.
      return if options[:pretend]

      # Write destination file with optional shebang.  Yield for content
      # if block given so templaters may render the source file.  If a
      # shebang is requested, replace the existing shebang or insert a
      # new one.
      File.open(destination, 'wb') do |dest|
        dest.write files.join("\n")
        dest.write "\n"
      end

      # Optionally add file to subversion
      system("svn add #{destination}") if options[:svn]
    end

[Validate]

Generated with the Darkfish Rdoc Generator 2.