aboutsummaryrefslogblamecommitdiffstats
path: root/railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
blob: 5b4687ce64a3310bdbf60579095453cad36ae0a2 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
                                            
                                                  
              






                         
           




                                                                                  

       
              
                            


















                                         
                              
                                            


                                       

       
              
                                          

       
            

                                    




                                    

                                                      
         

       
                                          
                                                                                                 
                          
 
                                             
                                                                


                         

                                                                                            


                                                                                    

















                                             












                                                                                                                                       
                                              








                                                                                                             

                                                      






                                             
                                      
                                     
 
                                          
 

                                                                                     
 

                                                                                           
 




                                                                                      
 
                           
                                                                                                                            
 


             
                              



                           
                                                       




                                                       



                          







                             







                                         







                                                    
                                 
                                          
                        

         



                         
                                                               
 
             



                             


                                      





                                          

                                                          

           
 
               




                                             

         



                                                                             







                                                                 
                      








                                                                                                                                      

                                         
 


                                                                                                            




                                                                  



                                                                          
 














                                  
                                           
         



                          


       
require 'active_support/core_ext/hash/slice'
require "rails/generators/rails/app/app_generator"
require 'date'

module Rails
  class PluginBuilder
    def rakefile
      template "Rakefile"
    end

    def app
      if options[:mountable]
        directory "app"
        template "#{app_templates_dir}/app/views/layouts/application.html.erb.tt",
                 "app/views/layouts/#{name}/application.html.erb"
      end
    end

    def readme
      template "README.rdoc"
    end

    def gemfile
      template "Gemfile"
    end

    def license
      template "MIT-LICENSE"
    end

    def gemspec
      template "%name%.gemspec"
    end

    def gitignore
      copy_file "gitignore", ".gitignore"
    end

    def lib
      template "lib/%name%.rb"
      template "lib/tasks/%name%_tasks.rake"
      if full?
        template "lib/%name%/engine.rb"
      end
    end

    def config
      template "config/routes.rb" if full?
    end

    def test
      template "test/test_helper.rb"
      template "test/%name%_test.rb"
      append_file "Rakefile", <<-EOF
#{rakefile_test_tasks}

task :default => :test
      EOF
      if full?
        template "test/integration/navigation_test.rb"
      end
    end

    def generate_test_dummy(force = false)
      opts = (options || {}).slice(:skip_active_record, :skip_javascript, :database, :javascript)
      opts[:force] = force

      invoke Rails::Generators::AppGenerator,
        [ File.expand_path(dummy_path, destination_root) ], opts
    end

    def test_dummy_config
      template "rails/boot.rb", "#{dummy_path}/config/boot.rb", :force => true
      template "rails/application.rb", "#{dummy_path}/config/application.rb", :force => true
      if mountable?
        template "rails/routes.rb", "#{dummy_path}/config/routes.rb", :force => true
      end
    end

    def test_dummy_clean
      inside dummy_path do
        remove_file ".gitignore"
        remove_file "db/seeds.rb"
        remove_file "doc"
        remove_file "Gemfile"
        remove_file "lib/tasks"
        remove_file "public/images/rails.png"
        remove_file "public/index.html"
        remove_file "public/robots.txt"
        remove_file "README"
        remove_file "test"
        remove_file "vendor"
      end
    end

    def stylesheets
      empty_directory_with_gitkeep "public/stylesheets" if options[:mountable]
    end

    def javascripts
      return unless options[:mountable]

      empty_directory "#{app_templates_dir}/public/javascripts"

      unless options[:skip_javascript]
        copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}.js", "public/javascripts/#{options[:javascript]}.js"
        copy_file "#{app_templates_dir}/public/javascripts/#{options[:javascript]}_ujs.js", "public/javascripts/rails.js"

        if options[:javascript] == "prototype"
          copy_file "#{app_templates_dir}/public/javascripts/controls.js", "public/javascripts/controls.js"
          copy_file "#{app_templates_dir}/public/javascripts/dragdrop.js", "public/javascripts/dragdrop.js"
          copy_file "#{app_templates_dir}/public/javascripts/effects.js", "public/javascripts/effects.js"
        end
      end

      copy_file "#{app_templates_dir}/public/javascripts/application.js", "public/javascripts/application.js"
    end

    def script(force = false)
      directory "script", :force => force do |content|
        "#{shebang}\n" + content
      end
      chmod "script", 0755, :verbose => false
    end
  end

  module Generators
    class PluginNewGenerator < AppBase
      add_shared_options_for "plugin"

      alias_method :plugin_path, :app_path

      class_option :dummy_path,     :type => :string, :default => "test/dummy",
                                    :desc => "Create dummy application at given path"

      class_option :full,           :type => :boolean, :default => false,
                                    :desc => "Generate rails engine with integration tests"

      class_option :mountable,      :type => :boolean, :default => false,
                                    :desc => "Generate mountable isolated application"

      class_option :skip_gemspec,   :type => :boolean, :default => false,
                                    :desc => "Skip gemspec file"

      def initialize(*args)
        raise Error, "Options should be given after the plugin name. For details run: rails plugin --help" if args[0].blank?

        super
      end

      public_task :create_root

      def create_root_files
        build(:readme)
        build(:rakefile)
        build(:gemspec)   unless options[:skip_gemspec]
        build(:license)
        build(:gitignore) unless options[:skip_git]
        build(:gemfile)   unless options[:skip_gemfile]
      end

      def create_app_files
        build(:app)
      end

      def create_config_files
        build(:config)
      end

      def create_lib_files
        build(:lib)
      end

      def create_public_stylesheets_files
        build(:stylesheets)
      end

      def create_javascript_files
        build(:javascripts)
      end

      def create_script_files
        build(:script)
      end

      def create_test_files
        build(:test) unless options[:skip_test_unit]
      end

      def create_test_dummy_files
        return if options[:skip_test_unit]
        create_dummy_app
      end

      def finish_template
        build(:leftovers)
      end

      public_task :apply_rails_template, :bundle_if_dev_or_edge

    protected
      def app_templates_dir
        "../../app/templates"
      end

      def create_dummy_app(path = nil)
        dummy_path(path) if path

        say_status :vendor_app, dummy_path
        mute do
          build(:generate_test_dummy)
          store_application_definition!
          build(:test_dummy_config)
          build(:test_dummy_clean)
          # ensure that script/rails has proper dummy_path
          build(:script, true)
        end
      end

      def full?
        options[:full] || options[:mountable]
      end

      def mountable?
        options[:mountable]
      end

      def self.banner
        "rails plugin new #{self.arguments.map(&:usage).join(' ')} [options]"
      end

      def name
        @name ||= File.basename(destination_root)
      end

      def camelized
        @camelized ||= name.gsub(/\W/, '_').squeeze('_').camelize
      end

      def valid_const?
        if camelized =~ /^\d/
          raise Error, "Invalid plugin name #{name}. Please give a name which does not start with numbers."
        elsif RESERVED_NAMES.include?(name)
          raise Error, "Invalid plugin name #{name}. Please give a name which does not match one of the reserved rails words."
        elsif Object.const_defined?(camelized)
          raise Error, "Invalid plugin name #{name}, constant #{camelized} is already in use. Please choose another application name."
        end
      end

      def application_definition
        @application_definition ||= begin

          dummy_application_path = File.expand_path("#{dummy_path}/config/application.rb", destination_root)
          unless options[:pretend] || !File.exists?(dummy_application_path)
            contents = File.read(dummy_application_path)
            contents[(contents.index("module Dummy"))..-1]
          end
        end
      end
      alias :store_application_definition! :application_definition

      def get_builder_class
        defined?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder
      end

      def rakefile_test_tasks
        <<-RUBY
require 'rake/testtask'

Rake::TestTask.new(:test) do |t|
  t.libs << 'lib'
  t.libs << 'test'
  t.pattern = 'test/**/*_test.rb'
  t.verbose = false
end
        RUBY
      end

      def dummy_path(path = nil)
        @dummy_path = path if path
        @dummy_path || options[:dummy_path]
      end

      def mute(&block)
        shell.mute(&block)
      end
    end
  end
end