Skip to content

Instantly share code, notes, and snippets.

@johnable
Created July 3, 2012 03:42
Show Gist options
  • Save johnable/3037460 to your computer and use it in GitHub Desktop.
Save johnable/3037460 to your computer and use it in GitHub Desktop.
web template(mongoid 3.0)
#https://raw.github.com/RailsApps/rails3-application-templates/master/rails3-mongoid-omniauth-template.rb
# >----------------------------[ Initial Setup ]------------------------------<
initializer 'generators.rb', <<-RUBY
Rails.application.config.generators do |g|
end
RUBY
@recipes = ["haml", "mongoid", "rspec", "guard", "omniauth", "home_page", "cleanup", "git"]
def recipes; @recipes end
def recipe?(name); @recipes.include?(name) end
def say_custom(tag, text); say "\033[1m\033[36m" + tag.to_s.rjust(10) + "\033[0m" + " #{text}" end
def say_recipe(name); say "\033[1m\033[36m" + "recipe".rjust(10) + "\033[0m" + " Running #{name} recipe..." end
def say_wizard(text); say_custom(@current_recipe || 'wizard', text) end
def ask_wizard(question)
ask "\033[1m\033[30m\033[46m" + (@current_recipe || "prompt").rjust(10) + "\033[0m\033[36m" + " #{question}\033[0m"
end
def yes_wizard?(question)
answer = ask_wizard(question + " \033[33m(y/n)\033[0m")
case answer.downcase
when "yes", "y"
true
when "no", "n"
false
else
yes_wizard?(question)
end
end
def no_wizard?(question); !yes_wizard?(question) end
def multiple_choice(question, choices)
say_custom('question', question)
values = {}
choices.each_with_index do |choice,i|
values[(i + 1).to_s] = choice[1]
say_custom (i + 1).to_s + ')', choice[0]
end
answer = ask_wizard("Enter your selection:") while !values.keys.include?(answer)
values[answer]
end
@current_recipe = nil
@configs = {}
@after_blocks = []
def after_bundler(&block); @after_blocks << [@current_recipe, block]; end
@after_everything_blocks = []
def after_everything(&block); @after_everything_blocks << [@current_recipe, block]; end
@before_configs = {}
def before_config(&block); @before_configs[@current_recipe] = block; end
# this application template only supports Rails version 3.1 and newer
case Rails::VERSION::MAJOR.to_s
when "3"
case Rails::VERSION::MINOR.to_s
when "2"
say_wizard "You are using Rails version #{Rails::VERSION::STRING}."
when "1"
say_wizard "You are using Rails version #{Rails::VERSION::STRING}."
when "0"
say_wizard "You are using Rails version #{Rails::VERSION::STRING} which is not supported. Try 3.1 or newer."
raise StandardError.new "Rails #{Rails::VERSION::STRING} is not supported. Try 3.1 or newer."
else
say_wizard "You are using Rails version #{Rails::VERSION::STRING}."
end
else
say_wizard "You are using Rails version #{Rails::VERSION::STRING} which is not supported. Try 3.1 or newer."
raise StandardError.new "Rails #{Rails::VERSION::STRING} is not supported. Try 3.1 or newer."
end
say_wizard "Checking configuration. Please confirm your preferences."
# >---------------------------[ Autoload Modules/Classes ]-----------------------------<
inject_into_file 'config/application.rb', :after => 'config.autoload_paths += %W(#{config.root}/extras)' do <<-'RUBY'
config.autoload_paths += %W(#{config.root}/lib)
RUBY
end
# >---------------------------------[ Recipes ]----------------------------------<
# >---------------------------------[ HAML ]----------------------------------<
@current_recipe = "haml"
@before_configs["haml"].call if @before_configs["haml"]
say_recipe 'HAML'
config = {}
config['haml'] = yes_wizard?("Would you like to use Haml instead of ERB?") if true && true unless config.key?('haml')
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/haml.rb
if config['haml']
gem 'haml', '>= 3.1.6'
gem 'haml-rails', '>= 0.3.4', :group => :development
else
recipes.delete('haml')
end
# >--------------------------------[ Mongoid ]--------------------------------<
@current_recipe = "mongoid"
@before_configs["mongoid"].call if @before_configs["mongoid"]
say_recipe 'Mongoid'
config = {}
config['mongoid'] = yes_wizard?("Would you like to use Mongoid to connect to a MongoDB database?") if true && true unless config.key?('mongoid')
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/mongoid.rb
if config['mongoid']
say_wizard "REMINDER: When creating a Rails app using Mongoid..."
say_wizard "you should add the '-O' flag to 'rails new'"
gem "mongoid", "~> 3.0.0.rc"
else
recipes.delete('mongoid')
end
if config['mongoid']
after_bundler do
say_wizard "Mongoid recipe running 'after bundler'"
# note: the mongoid generator automatically modifies the config/application.rb file
# to remove the ActiveRecord dependency by commenting out "require active_record/railtie'"
generate 'mongoid:config'
# remove the unnecessary 'config/database.yml' file
remove_file 'config/database.yml'
end
end
# >---------------------------------[ RSpec ]---------------------------------<
@current_recipe = "rspec"
@before_configs["rspec"].call if @before_configs["rspec"]
say_recipe 'RSpec'
config = {}
config['rspec'] = yes_wizard?("Would you like to use RSpec instead of TestUnit?") if true && true unless config.key?('rspec')
config['factory_girl'] = yes_wizard?("Would you like to use factory_girl for test fixtures with RSpec?") if true && true unless config.key?('factory_girl')
config['machinist'] = yes_wizard?("Would you like to use machinist for test fixtures with RSpec?") if true && true unless config.key?('machinist')
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/rspec.rb
if config['rspec']
gem 'rspec-rails', '>= 2.10.1', :group => [:development, :test]
if recipes.include? 'mongoid'
# use the database_cleaner gem to reset the test database
gem 'database_cleaner', '>= 0.8.0', :group => :test
# include RSpec matchers from the mongoid-rspec gem
gem 'mongoid-rspec', '>= 1.4.6', :group => :test
end
if config['machinist']
gem 'machinist', :group => :test
end
if config['factory_girl']
gem 'factory_girl_rails', '>= 3.3.0', :group => [:development, :test]
end
else
recipes.delete('rspec')
end
# note: there is no need to specify the RSpec generator in the config/application.rb file
if config['rspec']
after_bundler do
say_wizard "RSpec recipe running 'after bundler'"
generate 'rspec:install'
if config['machinist']
say_wizard "Generating blueprints file for Machinist"
generate 'machinist:install'
end
say_wizard "Removing test folder (not needed for RSpec)"
run 'rm -rf test/'
inject_into_file 'config/application.rb', :after => "Rails::Application\n" do <<-RUBY
# don't generate RSpec tests for views and helpers
config.generators do |g|
g.view_specs false
g.helper_specs false
g.template_engine :haml
g.test_framework :rspec
g.stylesheets false
g.assets false
#{"g.fixture_replacement :machinist" if config['machinist']}
end
RUBY
end
if recipes.include? 'mongoid'
# remove ActiveRecord artifacts
gsub_file 'spec/spec_helper.rb', /config.fixture_path/, '# config.fixture_path'
gsub_file 'spec/spec_helper.rb', /config.use_transactional_fixtures/, '# config.use_transactional_fixtures'
# reset your application database to a pristine state during testing
inject_into_file 'spec/spec_helper.rb', :before => "\nend" do
<<-RUBY
\n
# Clean up the database
require 'database_cleaner'
config.before(:suite) do
DatabaseCleaner.strategy = :truncation
DatabaseCleaner.orm = "mongoid"
end
config.before(:each) do
DatabaseCleaner.clean
end
RUBY
end
# remove either possible occurrence of "require rails/test_unit/railtie"
gsub_file 'config/application.rb', /require 'rails\/test_unit\/railtie'/, '# require "rails/test_unit/railtie"'
gsub_file 'config/application.rb', /require "rails\/test_unit\/railtie"/, '# require "rails/test_unit/railtie"'
# configure RSpec to use matchers from the mongoid-rspec gem
create_file 'spec/support/mongoid.rb' do
<<-RUBY
RSpec.configure do |config|
config.include Mongoid::Matchers
end
RUBY
end
end
if recipes.include? 'devise'
# add Devise test helpers
create_file 'spec/support/devise.rb' do
<<-RUBY
RSpec.configure do |config|
config.include Devise::TestHelpers, :type => :controller
end
RUBY
end
end
end
end
# >---------------------------------[ guard ]---------------------------------<
@current_recipe = "guard"
@before_configs["guard"].call if @before_configs["guard"]
say_recipe 'guard'
config = {}
config['guard'] = multiple_choice("Would you like to use Guard to automate your workflow?", [["No", false], ["Guard default configuration", "standard"], ["Guard with LiveReload", "LiveReload"]]) if true && true unless config.key?('guard')
@configs[@current_recipe] = config
case config['guard']
when 'no'
recipes.delete('guard')
say_wizard "Guard recipe skipped."
when 'standard'
# do nothing
when 'LiveReload'
recipes << 'guard-LiveReload'
else
recipes.delete('guard')
say_wizard "Guard recipe skipped."
end
if recipes.include? 'guard'
gem 'guard', '>= 0.6.2', :group => :development
prepend_file 'Gemfile' do <<-RUBY
require 'rbconfig'
HOST_OS = RbConfig::CONFIG['host_os']
RUBY
end
append_file 'Gemfile' do <<-RUBY
# need newline here!
case HOST_OS
when /darwin/i
gem 'rb-fsevent', :group => :development
gem 'growl', :group => :development
when /linux/i
gem 'libnotify', :group => :development
gem 'rb-inotify', :group => :development
when /mswin|windows/i
gem 'rb-fchange', :group => :development
gem 'win32console', :group => :development
gem 'rb-notifu', :group => :development
end
RUBY
end
def guards
@guards ||= []
end
def guard(name, version = nil)
args = []
if version
args << version
end
args << { :group => :development }
gem "guard-#{name}", *args
guards << name
end
guard 'bundler', '>= 0.1.3'
guard 'pow', '>= 1.0.0'
if recipes.include? 'guard-LiveReload'
guard 'livereload', '>= 0.3.0'
end
if recipes.include? 'rspec'
guard 'rspec', '>= 0.4.3'
end
if recipes.include? 'cucumber'
guard 'cucumber', '>= 0.6.1'
end
after_bundler do
guards.each do |name|
run "guard init #{name}"
end
end
else
recipes.delete 'guard'
end
# >-------------------------------[ OmniAuth ]--------------------------------<
@current_recipe = "omniauth"
@before_configs["omniauth"].call if @before_configs["omniauth"]
say_recipe 'OmniAuth'
config = {}
config['omniauth'] = yes_wizard?("Would you like to use OmniAuth for authentication?") if true && true unless config.key?('omniauth')
#config['provider'] = multiple_choice("Which service provider will you use?", [["Twitter", "twitter"], ["Facebook", "facebook"], ["Weibo", "weibo"], ["Google", "google"], ["QQ", "qq_connect"]]) if true && true unless config.key?('provider')
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/omniauth.rb
if config['omniauth']
gem 'omniauth', '>= 1.1.0'
gem 'omniauth-twitter'
gem 'omniauth-facebook'
gem 'omniauth-weibo-oauth2'
gem 'omniauth-google-oauth2'
gem 'omniauth-qq-connect'
else
recipes.delete('omniauth')
end
if config['omniauth']
after_bundler do
say_wizard "OmniAuth recipe running 'after bundler'"
# Don't use single-quote-style-heredoc: we want interpolation.
create_file 'config/initializers/omniauth.rb' do <<-RUBY
Rails.application.config.middleware.use OmniAuth::Builder do
provider :qq_connect, "key", "secret"
provider :twitter, "key", "secret"
provider :facebook, "key", "secret"
provider :weibo, "key", "secret"
provider :google_oauth2, "key", "secret"
end
RUBY
end
# add routes
route "match '/auth/failure' => 'sessions#failure'"
route "match '/signout' => 'sessions#destroy', :as => :signout"
route "match '/signin' => 'sessions#new', :as => :signin"
route "match '/auth/:provider/callback' => 'sessions#create'"
route "resources :users, :only => [ :show, :edit, :update ]"
# add a user model (unless another recipe did so already)
unless recipes.include? 'add_user'
generate(:model, "user provider:string uid:string name:string email:string")
gsub_file 'app/models/user.rb', /\bend\s*\Z/ do
<<-RUBY
attr_accessible :provider, :uid, :name, :email
end
RUBY
end
end
# modify the user model
inject_into_file 'app/models/user.rb', :before => 'end' do <<-RUBY
def self.create_with_omniauth(auth)
create! do |user|
user.provider = auth['provider']
user.uid = auth['uid']
if auth['info']
user.name = auth['info']['name'] || ""
user.email = auth['info']['email'] || ""
end
end
end
RUBY
end
# We have to use single-quote-style-heredoc to avoid interpolation.
create_file 'app/controllers/sessions_controller.rb' do <<-'RUBY'
class SessionsController < ApplicationController
def create
auth = request.env["omniauth.auth"]
user = User.where(:provider => auth['provider'],
:uid => auth['uid']).first || User.create_with_omniauth(auth)
session[:user_id] = user.id
redirect_to root_url, :notice => 'Signed in!'
end
def destroy
reset_session
redirect_to root_url, :notice => 'Signed out!'
end
def failure
redirect_to root_url, :alert => "Authentication error: #{params[:message].humanize}"
end
end
RUBY
end
# Don't use single-quote-style-heredoc: we want interpolation.
inject_into_class 'app/controllers/sessions_controller.rb', 'SessionsController' do <<-RUBY
def new
redirect_to '/auth/#{config['provider']}'
end
RUBY
end
inject_into_file 'app/controllers/application_controller.rb', :before => 'end' do <<-RUBY
helper_method :current_user
helper_method :user_signed_in?
helper_method :correct_user?
private
def current_user
begin
@current_user ||= User.find(session[:user_id]) if session[:user_id]
rescue Mongoid::Errors::DocumentNotFound
nil
end
end
def user_signed_in?
return true if current_user
end
def correct_user?
@user = User.find(params[:id])
unless current_user == @user
redirect_to root_url, :alert => "Access denied."
end
end
def authenticate_user!
if !current_user
redirect_to root_url, :alert => 'You need to sign in for access to this page.'
end
end
RUBY
end
end
after_everything do
say_wizard "OmniAuth recipe running 'after everything'"
if recipes.include? 'rspec'
say_wizard "Copying RSpec files from the rails3-mongoid-omniauth examples"
begin
# copy all the RSpec specs files from the rails3-mongoid-omniauth example app
# spec_helper
remove_file 'spec/spec_helper.rb'
create_file 'spec/spec_helper.rb' do
<<-RUBY
ENV["RAILS_ENV"] ||= 'test'
require File.expand_path("../../config/environment", __FILE__)
require 'rspec/rails'
require 'rspec/autorun'
require 'factory_girl'
Dir[Rails.root.join("spec/support/**/*.rb")].each {|f| require f}
RSpec.configure do |config|
config.include FactoryGirl::Syntax::Methods
config.infer_base_class_for_anonymous_controllers = false
end
RUBY
end
empty_directory 'spec/routing'
# factories
remove_file 'spec/factories/users.rb'
# controllers
remove_file 'spec/controllers/home_controller_spec.rb'
remove_file 'spec/controllers/users_controller_spec.rb'
# models
remove_file 'spec/models/user_spec.rb'
get 'https://raw.github.com/RailsApps/rails3-mongoid-omniauth/master/spec/models/user_spec.rb', 'spec/models/user_spec.rb'
rescue OpenURI::HTTPError
say_wizard "Unable to obtain RSpec example files from the repo"
end
end
end
end
# >-------------------------------[ HomePage ]--------------------------------<
@current_recipe = "home_page"
@before_configs["home_page"].call if @before_configs["home_page"]
say_recipe 'HomePage'
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/home_page.rb
after_bundler do
say_wizard "HomePage recipe running 'after bundler'"
# remove the default home page
remove_file 'public/index.html'
# create a home controller and view
generate(:controller, "home index")
# set up a simple home page (with placeholder content)
if recipes.include? 'haml'
remove_file 'app/views/home/index.html.haml'
# There is Haml code in this script. Changing the indentation is perilous between HAMLs.
# We have to use single-quote-style-heredoc to avoid interpolation.
create_file 'app/views/home/index.html.haml' do
<<-'HAML'
%h3 Home
HAML
end
elsif recipes.include? 'slim'
# skip
else
remove_file 'app/views/home/index.html.erb'
create_file 'app/views/home/index.html.erb' do
<<-ERB
<h3>Home</h3>
ERB
end
end
# set routes
gsub_file 'config/routes.rb', /get \"home\/index\"/, 'root :to => "home#index"'
if recipes.include? 'devise'
inject_into_file 'config/routes.rb', :before => " root :to" do
<<-RUBY
authenticated :user do
root :to => 'home#index'
end
\n
RUBY
end
end
end
# >--------------------------------[ Cleanup ]--------------------------------<
@current_recipe = "cleanup"
@before_configs["cleanup"].call if @before_configs["cleanup"]
say_recipe 'Cleanup'
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/cleanup.rb
after_bundler do
say_wizard "Cleanup recipe running 'after bundler'"
# remove unnecessary files
%w{
README.rdoc
doc/README_FOR_APP
public/index.html
app/assets/images/rails.png
}.each { |file| remove_file file }
# remove commented lines and multiple blank lines from Gemfile
# thanks to https://github.com/perfectline/template-bucket/blob/master/cleanup.rb
gsub_file 'Gemfile', /#.*\n/, "\n"
gsub_file 'Gemfile', /\n^\s*\n/, "\n"
# remove commented lines and multiple blank lines from config/routes.rb
gsub_file 'config/routes.rb', / #.*\n/, "\n"
gsub_file 'config/routes.rb', /\n^\s*\n/, "\n"
# add locate info into application.rb
inject_into_file 'config/application.rb', :after => "Rails::Application\n" do
<<-RUBY
config.time_zone = 'Beijing'
config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**' ,'*.{rb,yml}').to_s]
config.i18n.default_locale = "zh-CN"
Time::DATE_FORMATS.merge!(:default => "%Y/%m/%d %H:%M:%S", :ymd => "%Y/%m/%d")
\n
RUBY
end
# add localize file
get "https://raw.github.com/svenfuchs/rails-i18n/master/rails/locale/zh-CN.yml", "config/locales/zh-CN.yml"
end
# >----------------------------------[ Git ]----------------------------------<
@current_recipe = "git"
@before_configs["git"].call if @before_configs["git"]
say_recipe 'Git'
@configs[@current_recipe] = config
# Application template recipe for the rails_apps_composer. Check for a newer version here:
# https://github.com/RailsApps/rails_apps_composer/blob/master/recipes/git.rb
after_everything do
say_wizard "Git recipe running 'after everything'"
# Git should ignore some files
remove_file '.gitignore'
get "https://raw.github.com/RailsApps/rails3-application-templates/master/files/gitignore.txt", ".gitignore"
if recipes.include? 'omniauth'
append_file '.gitignore' do <<-TXT
# keep OmniAuth service provider secrets out of the Git repo
config/initializers/omniauth.rb
TXT
end
end
# Initialize new Git repo
git :init
git :add => '.'
git :commit => "-aqm 'new Rails app generated by Rails Apps Composer gem'"
# Create a git branch
git :checkout => ' -b working_branch'
git :add => '.'
git :commit => "-m 'Initial commit of working_branch'"
git :checkout => 'master'
end
@current_recipe = nil
# >-----------------------------[ Run Bundler ]-------------------------------<
say_wizard "Running 'bundle install'. This will take a while."
run 'bundle install'
run 'bundle update'
say_wizard "Running 'after bundler' callbacks."
require 'bundler/setup'
@after_blocks.each{|b| config = @configs[b[0]] || {}; @current_recipe = b[0]; b[1].call}
@current_recipe = nil
say_wizard "Running 'after everything' callbacks."
@after_everything_blocks.each{|b| config = @configs[b[0]] || {}; @current_recipe = b[0]; b[1].call}
@current_recipe = nil
say_wizard "Finished running the rails_apps_composer app template."
say_wizard "Your new Rails app is ready."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment