Skip to content

Commit

Permalink
Added 'rails plugin new' generator which generates gem plugin skeleton.
Browse files Browse the repository at this point in the history
This command is based on enginex gem by José Valim. It generates gem structure
and ads dummy application into test/dummy. This can be used to start developing
any kind of extension for rails 3.
  • Loading branch information
drogus committed Nov 2, 2010
1 parent d446392 commit cfcea1d
Show file tree
Hide file tree
Showing 21 changed files with 607 additions and 1 deletion.
7 changes: 6 additions & 1 deletion railties/lib/rails/cli.rb
Expand Up @@ -11,4 +11,9 @@
require 'rails/ruby_version_check' require 'rails/ruby_version_check'
Signal.trap("INT") { puts; exit } Signal.trap("INT") { puts; exit }


require 'rails/commands/application' if ARGV.first == 'plugin'
ARGV.shift
require 'rails/commands/plugin_new'
else
require 'rails/commands/application'
end
16 changes: 16 additions & 0 deletions railties/lib/rails/commands/plugin_new.rb
@@ -0,0 +1,16 @@
require 'rails/version'
if %w(--version -v).include? ARGV.first
puts "Rails #{Rails::VERSION::STRING}"
exit(0)
end

if ARGV.first != "new"
ARGV[0] = "--help"
else
ARGV.shift
end

require 'rails/generators'
require 'rails/generators/rails/plugin_new/plugin_new_generator'

Rails::Generators::PluginNewGenerator.start
225 changes: 225 additions & 0 deletions railties/lib/rails/generators/rails/plugin_new/plugin_new_generator.rb
@@ -0,0 +1,225 @@
require "rails/generators/rails/app/app_generator"

module Rails
class PluginBuilder
def rakefile
template "Rakefile"
end

def readme
copy_file "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
directory "lib"
end

def test
directory "test"
end

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

def test_dummy_config
store_application_definition!
template "rails/boot.rb", "#{dummy_path}/config/boot.rb", :force => true
template "rails/application.rb", "#{dummy_path}/config/application.rb", :force => true
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 script
directory "script" do |content|
"#{shebang}\n" + content
end
chmod "script", 0755, :verbose => false
end
end

module Generators
class PluginNewGenerator < Base
attr_accessor :rails_template

add_shebang_option!

argument :plugin_path, :type => :string

class_option :builder, :type => :string, :aliases => "-b",
:desc => "Path to a plugin builder (can be a filesystem path or URL)"

class_option :skip_gemfile, :type => :boolean, :default => false,
:desc => "Don't create a Gemfile"

class_option :skip_git, :type => :boolean, :aliases => "-G", :default => false,
:desc => "Skip Git ignores and keeps"

class_option :help, :type => :boolean, :aliases => "-h", :group => :rails,
:desc => "Show this help message and quit"

def self.say_step(message)
@step = (@step || 0) + 1
class_eval <<-METHOD, __FILE__, __LINE__ + 1
def step_#{@step}
#{"puts" if @step > 1}
say_status "STEP #{@step}", #{message.inspect}
end
METHOD
end

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

@original_wd = Dir.pwd

super
end

say_step "Creating gem skeleton"

def create_root
self.destination_root = File.expand_path(plugin_path, destination_root)
valid_plugin_const?

empty_directory '.'
FileUtils.cd(destination_root) unless options[:pretend]
end

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

def create_config_files
build(:config)
end

def create_lib_files
build(:lib)
end

def create_script_files
build(:script)
end

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

say_step "Vendoring Rails application at test/dummy"

def create_test_dummy_files
build(:test_dummy)
end

say_step "Configuring Rails application"

def change_config_files
build(:test_dummy_config)
end

say_step "Removing unneeded files"

def remove_uneeded_rails_files
build(:test_dummy_clean)
end

protected

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

def builder
@builder ||= begin
if path = options[:builder]
if URI(path).is_a?(URI::HTTP)
contents = open(path, "Accept" => "application/x-thor-template") {|io| io.read }
else
contents = open(File.expand_path(path, @original_wd)) {|io| io.read }
end

prok = eval("proc { #{contents} }", TOPLEVEL_BINDING, path, 1)
instance_eval(&prok)
end

builder_class = defined?(::PluginBuilder) ? ::PluginBuilder : Rails::PluginBuilder
builder_class.send(:include, ActionMethods)
builder_class.new(self)
end
end

def build(meth, *args)
builder.send(meth, *args) if builder.respond_to?(meth)
end

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

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

def valid_plugin_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 dummy_path
"test/dummy"
end

def application_definition
@application_definition ||= begin
unless options[:pretend]
contents = File.read(File.expand_path("#{dummy_path}/config/application.rb", destination_root))
contents[(contents.index("module Dummy"))..-1]
end
end
end
alias :store_application_definition! :application_definition
end
end
end
@@ -0,0 +1,9 @@
# Provide a simple gemspec so you can easily use your
# project in your rails apps through git.
Gem::Specification.new do |s|
s.name = "<%= name %>"
s.summary = "Insert <%= camelized %> summary."
s.description = "Insert <%= camelized %> description."
s.files = Dir["lib/**/*"] + ["MIT-LICENSE", "Rakefile", "README.rdoc"]
s.version = "0.0.1"
end
11 changes: 11 additions & 0 deletions railties/lib/rails/generators/rails/plugin_new/templates/Gemfile
@@ -0,0 +1,11 @@
source "http://rubygems.org"

gem "rails", :git => "http://github.com/rails/rails.git"
gem "arel" , :git => "http://github.com/rails/arel.git"
gem "rack" , :git => "http://github.com/rack/rack.git"
gem "capybara", ">= 0.3.9"
gem "sqlite3-ruby", :require => "sqlite3"

if RUBY_VERSION < '1.9'
gem "ruby-debug", ">= 0.10.3"
end
@@ -0,0 +1,20 @@
Copyright <%= Date.today.year %> YOURNAME

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be
included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,3 @@
= <%= camelized %>

This project rocks and uses MIT-LICENSE.
46 changes: 46 additions & 0 deletions railties/lib/rails/generators/rails/plugin_new/templates/Rakefile
@@ -0,0 +1,46 @@
# encoding: UTF-8
require 'rubygems'
begin
require 'bundler/setup'
rescue LoadError
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
end

require 'rake'
require 'rake/rdoctask'
require 'rake/gempackagetask'

require 'rake/testtask'

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

task :default => :test

Rake::RDocTask.new(:rdoc) do |rdoc|
rdoc.rdoc_dir = 'rdoc'
rdoc.title = '<%= camelized %>'
rdoc.options << '--line-numbers' << '--inline-source'
rdoc.rdoc_files.include('README.rdoc')
rdoc.rdoc_files.include('lib/**/*.rb')
end

spec = Gem::Specification.new do |s|
s.name = "<%= name %>"
s.summary = "Insert <%= camelized %> summary."
s.description = "Insert <%= camelized %> description."
s.files = FileList["[A-Z]*", "lib/**/*"]
s.version = "0.0.1"
end

Rake::GemPackageTask.new(spec) do |pkg|
end

desc "Install the gem #{spec.name}-#{spec.version}.gem"
task :install do
system("gem install pkg/#{spec.name}-#{spec.version}.gem --no-ri --no-rdoc")
end
@@ -0,0 +1,6 @@
.bundle/
log/*.log
pkg/
test/dummy/db/*.sqlite3
test/dummy/log/*.log
test/dummy/tmp/
@@ -0,0 +1,2 @@
module <%= camelized %>
end
@@ -0,0 +1,12 @@
require File.expand_path('../boot', __FILE__)

require "active_model/railtie"
require "active_record/railtie"
require "action_controller/railtie"
require "action_view/railtie"
require "action_mailer/railtie"

Bundler.require
require "<%= name %>"

<%= application_definition %>
@@ -0,0 +1,10 @@
require 'rubygems'
gemfile = File.expand_path('../../../../Gemfile', __FILE__)

if File.exist?(gemfile)
ENV['BUNDLE_GEMFILE'] = gemfile
require 'bundler'
Bundler.setup
end

$:.unshift File.expand_path('../../../../lib', __FILE__)
@@ -0,0 +1,5 @@
#!/usr/bin/env ruby
# This command will automatically be run when you run "rails" with Rails 3 gems installed from the root of your application.

ENGINE_PATH = File.expand_path('../..', __FILE__)
load File.expand_path('../../test/dummy/script/rails', __FILE__)
@@ -0,0 +1,7 @@
require 'test_helper'

class <%= camelized %>Test < ActiveSupport::TestCase
test "truth" do
assert_kind_of Module, <%= camelized %>
end
end

0 comments on commit cfcea1d

Please sign in to comment.