Skip to content

Instantly share code, notes, and snippets.

@jeriko
Created February 19, 2012 21:37
Show Gist options
  • Save jeriko/1865932 to your computer and use it in GitHub Desktop.
Save jeriko/1865932 to your computer and use it in GitHub Desktop.
KICKSTART v1
class AppBuilder < Rails::AppBuilder
include Thor::Actions
include Thor::Shell
# Express app templating for Rails
# ------------------------------------
# USAGE:
# 1. Add gems to `gem_dependencies`
# 2. Methods listed in SCRIPTS will be run after bundling, so make sure they each have a declaration
# 3. run: `rails new app_name --builder=path/to/builder.rb` (URI's work here too)
# 4. ???
# 5. PROFIT!
# This method will be run as soon as the builder takes control
def init
cute_monkey = false
say 'Code monkey ready to work!', :green
say 'Thin is apparently faster than webrick', :red if cute_monkey
@use_thin = yes?('Use thin-rails server?')
say 'Carpal tunnel sucks, and slim works great with twitter_bootstrap', :red if cute_monkey
@use_slim = yes?('Swap out ERB with SLIM?')
say 'Bootstrap will make you happy.', :red if cute_monkey
if(@use_bootstrap = yes?('Install twitter_bootstrap?'))
@use_bootstrap_responsive = yes?('Install responsive twitter_bootstrap?')
end
say 'Chosen is an awesome dropdown-select UI tool', :red if cute_monkey
@use_chosen = yes?('Install jQuery-chosen?')
end
# Add your gem dependencies here
def gem_dependencies
# thin
@generator.gem 'thin-rails' if @use_thin
# slim
@generator.gem 'slim-rails' if @use_slim
# inherited_resources
@generator.gem 'inherited_resources'
# simple_form
@generator.gem 'simple_form', git: 'git://github.com/plataformatec/simple_form.git'
@generator.gem 'country_select'
# compass-sass + bootstrap
@generator.gem_group :assets do
gem 'therubyracer'
gem 'compass-rails'
gem 'compass_twitter_bootstrap' if @use_bootstrap
end
# test framework
@generator.gem_group :test, :development do
gem 'rspec-rails'
gem 'factory_girl_rails'
# TODO the rest
end
# chosen
@generator.gem 'chosen-rails' if @use_chosen
end
# Add any script declarations here, and make sure you build their corresponding methods
SCRIPTS = [
:spec, :sass, :coffeescript,
:bootstrap, :chosen, :css_utils, # asset plugins
:simple_form, :app_index_slim, # views
:rvm_gemset, # rvm
:file_cleanup, # general
:git_init # git
]
def spec
generate 'rspec:install'
end
def sass
# sets up app/assets/stylesheets/application.css.sass as required, with hooks for `manifest` and `import`s
css_asset_path = File.join %w(app assets stylesheets application.css)
@generator.remove_file(css_asset_path)
@sass_asset_path = File.join %w(app assets stylesheets application.css.sass)
@generator.create_file @sass_asset_path, <<-SASS
// MANIFEST: start
// MANIFEST: end
// IMPORTS: start
// IMPORTS: end
SASS
sass_add_manifest 'require_self'
sass_add_import 'compass'
end
def coffeescript
# sets up app/assets/javascripts/application.js.coffee as required, with hooks for `manifest` and `jquery onready`
js_asset_path = File.join %w(app assets javascripts application.js)
@generator.remove_file(js_asset_path)
@coffee_asset_path = File.join %w(app assets javascripts application.js.coffee)
@generator.create_file @coffee_asset_path, <<-COFFEE
// MANIFEST: start
// MANIFEST: end
$(document).ready ->
# ONREADY: start
# ONREADY: end
COFFEE
coffee_add_manifest require: 'jquery'
coffee_add_manifest require: 'jquery_ujs'
coffee_add_manifest 'require_tree .'
end
def bootstrap
return unless @use_bootstrap
sass_add_import 'compass_twitter_bootstrap'
sass_add_import 'compass_twitter_bootstrap_responsive'
# TODO bootstrap js imports...
end
def chosen
return unless @use_chosen
sass_add_manifest require: 'chosen'
coffee_add_manifest require: 'chosen-jquery'
coffee_add_ready "$('.chzn-select').chosen();"
end
def css_utils
# TODO sticky_footer etc.
end
def simple_form
generate "simple_form:install #{'--bootstrap' if @use_bootstrap}"
end
def app_index_slim
return unless @use_slim
# sets up app/views/layouts/index.html.slim as required
erb_index_path = File.join %w(app views layouts application.html.erb)
@generator.remove_file(erb_index_path)
slim_index_path = File.join %w(app views layouts application.html.slim)
@generator.create_file slim_index_path,
<<-SLIM
doctype 5
html
head
title #{app_name}
= stylesheet_link_tag 'application', :media => 'all'
= javascript_include_tag 'application'
= csrf_meta_tags
body class='\#{controller_name}'
= yield
SLIM
end
# TODO nifty generators
# TODO nifty config
# TODO carrierwave
# TODO airbrake
# TODO rails-best-practices (and the other outputter gem for development)
# TODO newrelic etc.
def rvm_gemset
# TODO
end
def file_cleanup
@generator.remove_file File.join %w(public index.html)
@generator.remove_file File.join %w(app assets images rails.png)
@generator.remove_file File.join %w(README.rdoc)
# remove the finder-tags in application.js.coffee
@generator.gsub_file(@coffee_asset_path, '// MANIFEST: start', '')
@generator.gsub_file(@coffee_asset_path, '// MANIFEST: end', '')
@generator.gsub_file(@coffee_asset_path, ' # ONREADY: start', '')
@generator.gsub_file(@coffee_asset_path, ' # ONREADY: end', '')
# remove the finder-tags in application.css.sass
@generator.gsub_file(@sass_asset_path, '// MANIFEST: start', '')
@generator.gsub_file(@sass_asset_path, '// MANIFEST: end', '')
@generator.gsub_file(@sass_asset_path, '// IMPORTS: start', '')
@generator.gsub_file(@sass_asset_path, '// IMPORTS: end', '')
end
def git_init
git :init
git add: '.'
git commit: "-m \"AppBuilder: #{app_name}\""
end
# ---------------------------------------------------
# - v You can safely ignore below this line v -
# ---------------------------------------------------
def gemfile
# `gemfile` is the first method called on Rails::AppBuilder, so let's hook into the process for config
init
# invoke default behaviour via `super`
# alternatively, use `template 'Gemfile'`, but let's not step on toes
super
# add dependencies to Gemfile
say 'Adding gem dependencies to Gemfile', :yellow
gem_dependencies
# we need dependencies installed right away, so their generators can be run BEFORE
# the scheduled run of bundler (at end of app generation)
# This dirty hack will have to do until I can figure out how to hook in commands AFTER bundler actually runs
say 'Running bundler', :yellow
run_bundle
# stop bundler running in future:
@generator.options = @generator.options.dup
@generator.options[:skip_bundle] = true
@generator.options.freeze
end
def test
return
# TODO
# skips test framework, but we can probably just bastardize the options in the same way as with :skip_bundle
# either make `test` build the actual directories etc., or use a script
# either way, this method is stupid.
end
def leftovers
SCRIPTS.each { |g|
say "Script: #{g}", :red
send(g)
}
say "Finished generating #{app_name}!", :green
say 'Saving Daniel time testing...', :blue
generate "scaffold people name dob:date"
rake "db:migrate"
say "She's all yours, sparky!\n\n", :green
end
# ASSET PIPELINE HELPERS:
def add_manifest(path, directive)
r = directive.is_a?(String) ? directive : "require #{directive.delete(:require)}"
@generator.inject_into_file path, before: '// MANIFEST: end' do
"//= #{r}\n"
end
end
def sass_add_manifest(directive)
add_manifest(@sass_asset_path, directive)
end
def coffee_add_manifest(directive)
add_manifest(@coffee_asset_path, directive)
end
def sass_add_import(i)
@generator.inject_into_file @sass_asset_path, before: '// IMPORTS: end' do
"@import '#{i}'\n"
end
end
def coffee_add_ready(js)
@generator.inject_into_file @coffee_asset_path, before: ' # ONREADY: end' do
" #{js}\n"
end
end
end
# TODO
# ** see: https://gist.github.com/32e0c32677055ea94361
# 1. init git repo
# git :init
# git :add => "."
# git :commit => "-a -m 'blank rails app'"
# # TODO add remotes?
#
# 2. create gemset / set up environment
# current_ruby = %x{rvm list}.match(/^=>\s+(.*)\s\[/)[1].strip
# run "rvm gemset create #{app_name}"
# run "rvm #{current_ruby}@#{app_name} gem install bundler"
# run "rvm #{current_ruby}@#{app_name} -S bundle install"
# create_file ".rvmrc", "rvm use #{current_ruby}@#{app_name} --create"
# --- or use RVM::Environment.new... etc.
#
# 3. get choices of what to install.
# # TODO
#
# 3. get keys for APIs (fog, hoptoad etc.)
# # TODO
#
# 4. install required gems
# # TODO add all gems to Gemfile
# run 'bundle install'
#
# 4. app config
# inject_into_file 'config/application.rb', after: 'config.filter_parameters += [:password]' do
# <<-eos
# config.generators do |g|
# g.stylesheets false
# g.form_builder :simple_form
# g.fixture_replacement :factory_girl, :dir => 'spec/factories'
# end
# eos
# end
#
# # TODO? run "echo '--format documentation' >> .rspec"
#
# 5. create database
# rake 'db:create', env: 'development'
# rake 'db:create', env: 'test'
# # or rake 'db:create:all?'
#
# 6. set up each app-facet
# db/
# - use postgres
# - generate config.yml & .example | .gitignore
#
# app/views
# - use slim
# - use simple_form + nested + country_select
# - install simple_form [--bootstrap?]
# - init application layout (using css_snippets...)
#
# app/assets
#
# /stylesheets
# - use the_ruby_racer
# - use compass
# - use twitter_bootstrap
# - install css_snippets (e.g. sticky_footer)
# - init application.css.scss [manifest, body]
#
# /javascripts
# - use coffescript
# - use twitter_bootstrap_responsive
# - ...
# - init application.js.coffee [manifest, body]
#
# app/uploaders
# ...
#
# app/controllers
# - use inherited_resources
# - use (scopes, pagination etc.)
# - generate sessions controllers
# - generate application_controller.rb (with relevant before_filters)
#
#
# spec/
# ...
#
# 7. rails cleanup
# remove_file 'public/index.html'
# remove_file 'rm app/assets/images/rails.png'
# remove_file 'app/views/layouts/application.html.erb'
# # TODO what else needs to be removed?
# remove_file 'README'
#
# 8. migrate database
# rake 'db:migrate', env: 'development'
# rake 'db:test:clone'
#
# 9. git housekeeping
# create_file 'log/.gitkeep'
# create_file 'tmp/.gitkeep'
#
# append_file '.gitignore', <<-GIT
# config/database.yml
# public/stylesheets/*.css
# public/javascripts/application.js
# tmp/**/*
# GIT
#
# # TODO .gitignores?
#
# 10. git final commit
# git add: '.'
# git commit: '-m "Platform45:Kickstart (codemonkey) for Rails 3'
#
#
#
# LATER
# ------------------------------------
#
# rails g barista:install
# compass init rails . -r html5-boilerplate -u html5-boilerplate --force
# TODO
# ------------------------------------------------------
# TODO generate your own layouts & shared files
# TODO jquery UI (gem? themed?)
# TODO google fonts (gem?)
# TO LOOK AT
#gem 'html5-boilerplate'
#gem 'barista'
#gem 'seed-fu'
# ---------------------------------------------------------------
# run "cp config/database.yml config/database.yml.example"
# run "echo 'config/database.yml' >> .gitignore"
#
# gem 'sorcery'
# # init files
# end
#
# facet authorization: 'cancan' do
# gem 'cancan'
# # generate "cancan:ability"
# end
#
#
# facet database: 'seed-fu' do
# gem 'seed-fu'
# file "lib/tasks/test_seed_data.rake", <<-END
# namespace :db do
# namespace :test do
# task :prepare => :environment do
# Rake::Task["db:seed_fu"].invoke
# end
# end
# end
# END
# # actually run at some point...
# end
#
# feature config: 'nifty' do
# #gem 'nifty-generators'
# # generate 'nifty:layout --haml' # necessary?
# # generate 'nifty:config'
# end
#
#
# facet uploads: 'carrierwave' do
# # TODO mkdir /public/uploads
# # TODO install gem
# end
#
# feature 'capistrano', :optional do
# gems << 'capistrano', group: :development
# # make Capfile
# end
#
#
# option testing: 'blah' do
# #gem "rails3-generators", :group => [ :development ]
# #gem "rspec-rails", :group => [ :development, :test ]
# #gem "factory_girl_rails", :group => [ :development, :test ]
# #gem "webrat", :group => :test
# #gem "ffaker", :group => :test
# #gem "autotest", :group => :test
# #gem 'shoulda', :group => :test
# #gem 'capybara', :group => :test
#
# # generate 'rspec:install'
# # inject_into_file 'spec/spec_helper.rb', "\nrequire 'factory_girl'", :after => "require 'rspec/rails'"
#
# # what else?
# end
#
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment