Created
October 30, 2009 03:09
-
-
Save bak/222079 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Set up git repository | |
git :init | |
# Copy database.yml for distribution use | |
run "cp config/database.yml config/database.yml.example" | |
# Set up .gitignore files | |
run %{find . -type d -empty | xargs -I xxx touch xxx/.gitignore} | |
file '.gitignore', <<-END | |
.DS_Store | |
coverage/* | |
log/*.log | |
db/*.db | |
db/*.sqlite3 | |
db/schema.rb | |
tmp/**/* | |
doc/api | |
doc/app | |
config/database.yml | |
coverage/* | |
END | |
# Install plugins | |
plugin 'exception_notifier', :git => 'git://github.com/rails/exception_notification.git' | |
plugin 'asset_packager', :git => 'git://github.com/sbecker/asset_packager.git' | |
plugin 'authlogic', :git => 'git://github.com/binarylogic/authlogic.git' | |
plugin 'rails-authorization-plugin', :git => 'git://github.com/DocSavage/rails-authorization-plugin.git' | |
plugin 'will_paginate', :git => 'git://github.com/mislav/will_paginate.git' | |
plugin 'shoulda', :git => 'git://github.com/thoughtbot/shoulda.git' | |
plugin 'factory_girl', :git => 'git://github.com/thoughtbot/factory_girl.git' | |
plugin 'paperclip', :git => 'git://github.com/thoughtbot/paperclip.git' | |
# Install all gems | |
gem 'ruby-debug' | |
gem 'rubypants' | |
rake('gems:install', :sudo => true) | |
rake('gems:unpack') | |
# Set up sessions, RSpec, user model, etc, and run migrations | |
rake('db:sessions:create') | |
generate("session", "user_session") | |
generate("controller", "user_sessions") | |
generate("model", "user") | |
run "rm db/migrate/*_create_users.rb" | |
file 'db/migrate/20090723072300_create_users.rb', | |
%q{class CreateUsers < ActiveRecord::Migration | |
def self.up | |
create_table :users do |t| | |
t.string :email | |
t.string :display_name | |
t.string :crypted_password | |
t.string :password_salt | |
t.string :persistence_token | |
t.string :single_access_token, :null => false # optional, see Authlogic::Session::Params | |
t.string :perishable_token, :null => false # optional, see Authlogic::Session::Perishability | |
t.integer :login_count, :null => false, :default => 0 # optional, see Authlogic::Session::MagicColumns | |
t.integer :failed_login_count, :null => false, :default => 0 # optional, see Authlogic::Session::MagicColumns | |
t.datetime :last_request_at # optional, see Authlogic::Session::MagicColumns | |
t.datetime :current_login_at # optional, see Authlogic::Session::MagicColumns | |
t.datetime :last_login_at # optional, see Authlogic::Session::MagicColumns | |
t.string :current_login_ip # optional, see Authlogic::Session::MagicColumns | |
t.string :last_login_ip # optional, see Authlogic::Session::MagicColumns | |
t.timestamps | |
end | |
add_index :users, :perishable_token | |
add_index :users, :email | |
end | |
def self.down | |
drop_table :users | |
end | |
end | |
} | |
generate("controller", "users") | |
generate("role_model", "Role") | |
rake('db:migrate') | |
rakefile "bootstrap.rake", <<HERE | |
namespace :app do | |
task :bootstrap => :environment do | |
admin_user = User.create(:email => "[email protected]", :password => "letmein", :password_confirmation => "letmein") | |
admin_role = Role.create(:name => "admin") | |
admin_user.roles << admin_role | |
end | |
task :seed do | |
end | |
end | |
HERE | |
#====================== | |
# APP | |
#---------------------- | |
# --- Password Resets --- | |
file 'app/controllers/password_resets_controller', | |
%q{class PasswordResetsController < ApplicationController | |
before_filter :load_user_using_perishable_token, :only => [:edit, :update] | |
before_filter :require_no_user | |
def new | |
render | |
end | |
def create | |
@user = User.find_by_email(params[:email]) | |
if @user | |
@user.deliver_password_reset_instructions! | |
flash[:notice] = "Instructions to reset your password have been emailed to you. " + | |
"Please check your email." | |
redirect_to root_url | |
else | |
flash[:notice] = "No user was found with that email address" | |
render :action => :new | |
end | |
end | |
def edit | |
render | |
end | |
def update | |
@user.password = params[:user][:password] | |
@user.password_confirmation = params[:user][: password_confirmation] | |
if @user.save | |
flash[:notice] = "Password successfully updated" | |
redirect_to account_url | |
else | |
render :action => :edit | |
end | |
end | |
private | |
def load_user_using_perishable_token | |
@user = User.find_using_perishable_token(params[:id]) | |
unless @user | |
flash[:notice] = "We're sorry, but we could not locate your account. " + | |
"If you are having issues try copying and pasting the URL " + | |
"from your email into your browser or restarting the " + | |
"reset password process." | |
redirect_to root_url | |
end | |
end | |
end | |
} | |
file 'app/views/password_resets/edit.html.erb', | |
%q{<% form_for @user, :url => password_reset_path, :method => :put do |f| %> | |
<%= f.error_messages %> | |
<fieldset> | |
<legend>Change My Password</legend> | |
<p> | |
<%= f.label :password %><br /> | |
<%= f.password_field :password %> | |
</p> | |
<p> | |
<%= f.label :password_confirmation %><br /> | |
<%= f.password_field :password_confirmation %> | |
</p> | |
</fieldset> | |
<%= f.submit "Update my password and log me in" %> | |
<% end %> | |
} | |
file 'app/views/password_resets/new.html.erb', | |
%q{<h1>Forgot Password</h1> | |
<p>Fill out the form below and instructions to reset your password will be emailed to you:</p> | |
<% form_tag password_resets_path do %> | |
<fieldset> | |
<p> | |
<label>Email:</label><br /> | |
<%= text_field_tag "email" %> | |
</p> | |
</fieldset> | |
<%= submit_tag "Reset my password" %> | |
<% end %> | |
} | |
# --- Routing --- | |
file 'config/routes.rb', | |
%q{ActionController::Routing::Routes.draw do |map| | |
map.resources :password_resets | |
map.resource :account, :controller => "users" | |
map.resources :users | |
map.resource :user_session | |
map.login 'login', :controller => 'user_sessions', :action => 'new' | |
map.logout 'logout', :controller => 'user_sessions', :action => 'destroy' | |
map.root :controller => 'application' | |
end | |
} | |
# --- Application Base --- | |
file 'app/helpers/application_helper.rb', | |
%q{module ApplicationHelper | |
def body_class | |
"#{controller.controller_name} #{controller.controller_name}-#{controller.action_name}" | |
end | |
# creates the navigation tabs, highlighting if we are in that part of the site | |
# "that part of the site," meaning a parent in a nested resource relationship | |
def nav_to(label, location) | |
if request.path == location # "/" or "/admin" | |
link_to(label, location, :class => "current") | |
elsif "/#{request.path.split('/')[1..2].join('/')}" == (location) # "/admin/entries" | |
link_to(label, location, :class => "current") | |
else | |
link_to(label, location) | |
end | |
end | |
end | |
} | |
file 'app/views/layouts/_flashes.html.erb', | |
%q{<div id="flash"> | |
<% flash.each do |key, value| -%> | |
<div id="flash_<%= key %>"><%=h value %></div> | |
<% end -%> | |
</div> | |
} | |
file 'app/views/shared/_navigation.html.erb', | |
%q{<div id="navigation"> | |
<ul> | |
<% navigation_items.each do |navigation_item| -%> | |
<li><%= nav_to navigation_item[0], navigation_item[1] %></li> | |
<% end -%> | |
</ul> | |
</div> | |
} | |
file 'app/views/application/index.html.erb', | |
%q{ | |
<h1>IT WORKS</h1> | |
} | |
file 'app/views/layouts/application.html.erb', | |
%q{<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" | |
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | |
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> | |
<head> | |
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/> | |
<title>New Project</title> | |
<%= stylesheet_link_tag 'screen', :media => 'all', :cache => true %> | |
<%= javascript_include_tag :defaults, :cache => true %> | |
</head> | |
<body class="<%= body_class %>"> | |
<%= render :partial => 'layouts/flashes' -%> | |
<%= render :partial => 'shared/navigation', :locals => {:navigation_items => @navigation_items} -%> | |
<%= yield %> | |
</body> | |
</html> | |
} | |
file 'app/controllers/application_controller.rb', | |
%q{class ApplicationController < ActionController::Base | |
before_filter :create_navigation | |
filter_parameter_logging :password, :password_confirmation | |
helper_method :current_user_session, :current_user | |
def index | |
end | |
private | |
def create_navigation | |
@navigation_items = [ | |
[ 'Home', root_path ] | |
] | |
end | |
def current_user_session | |
return @current_user_session if defined?(@current_user_session) | |
@current_user_session = UserSession.find | |
end | |
def current_user | |
return @current_user if defined?(@current_user) | |
@current_user = current_user_session && current_user_session.user | |
end | |
def require_user | |
unless current_user | |
store_location | |
flash[:notice] = "You must be logged in to access this page" | |
redirect_to new_user_session_url | |
return false | |
end | |
end | |
def require_no_user | |
if current_user | |
store_location | |
flash[:notice] = "You must be logged out to access this page" | |
redirect_to account_url | |
return false | |
end | |
end | |
def store_location | |
session[:return_to] = request.request_uri | |
end | |
def redirect_back_or_default(default) | |
redirect_to(session[:return_to] || default) | |
session[:return_to] = nil | |
end | |
def authenticate | |
unless current_user_session | |
redirect_to login_path | |
end | |
end | |
end | |
} | |
# -- User Sessions (logins) | |
file 'app/controllers/user_sessions_controller.rb', | |
%q{class UserSessionsController < ApplicationController | |
before_filter :require_no_user, :only => [:new, :create] | |
before_filter :require_user, :only => :destroy | |
def new | |
@user_session = UserSession.new | |
end | |
def create | |
@user_session = UserSession.new(params[:user_session]) | |
if @user_session.save | |
flash[:notice] = "Login successful!" | |
redirect_back_or_default account_url | |
else | |
render :action => :new | |
end | |
end | |
def destroy | |
current_user_session.destroy | |
flash[:notice] = "Logout successful!" | |
redirect_back_or_default new_user_session_url | |
end | |
end | |
} | |
file 'app/views/user_sessions/new.html.erb', | |
%q{<% form_for @user_session, :url => user_session_path do |f| %> | |
<fieldset> | |
<legend>Log In</legend> | |
<%= f.error_messages %> | |
<p> | |
<%= f.label :email %><br /> | |
<%= f.text_field :email %> | |
</p> | |
<p> | |
<%= f.label :password %><br /> | |
<%= f.password_field :password %> | |
</p> | |
<p><%= link_to "Forgot your password?", new_password_reset_path %></p> | |
<p><%= f.check_box :remember_me %><%= f.label :remember_me %></p> | |
</fieldset> | |
<p><%= f.submit "Login" %></p> | |
<% end %> | |
} | |
file 'app/controllers/users_controller.rb', | |
%q{class UsersController < ApplicationController | |
before_filter :require_no_user, :only => [:new, :create] | |
before_filter :require_user, :only => [:show, :edit, :update] | |
def new | |
@user = User.new | |
end | |
def create | |
@user = User.new(params[:user]) | |
if @user.save | |
flash[:notice] = "Account registered!" | |
redirect_back_or_default account_url | |
else | |
render :action => :new | |
end | |
end | |
def show | |
@user = @current_user | |
end | |
def edit | |
@user = @current_user | |
end | |
def update | |
@user = @current_user # makes our views "cleaner" and more consistent | |
if @user.update_attributes(params[:user]) | |
flash[:notice] = "Account updated!" | |
redirect_to account_url | |
else | |
render :action => :edit | |
end | |
end | |
end | |
} | |
# --- Users --- | |
file 'app/models/user.rb', | |
%q{class User < ActiveRecord::Base | |
acts_as_authentic | |
acts_as_authorized_user | |
acts_as_authorizable | |
def deliver_password_reset_instructions! | |
reset_perishable_token! | |
Notifier.deliver_password_reset_instructions(self) | |
end | |
end | |
} | |
file 'app/views/users/_form.html.erb', | |
%q{<% form_for @user, :url => account_path do |f| %> | |
<%= f.error_messages %> | |
<fieldset> | |
<p> | |
<%= f.label :display_name %><br /> | |
<%= f.text_field :display_name %> | |
</p> | |
<p> | |
<%= f.label :email %><br /> | |
<%= f.text_field :email %> | |
</p> | |
<p> | |
<%= f.label :password, form.object.new_record? ? nil : "Change password" %><br /> | |
<%= f.password_field :password %> | |
</p> | |
<p> | |
<%= f.label :password_confirmation %><br /> | |
<%= f.password_field :password_confirmation %> | |
</p> | |
<%= f.submit "Submit" %> | |
<% end -%> | |
} | |
file 'app/views/users/new.html.erb', | |
%q{<h1>Register</h1> | |
<%= render :partial => "form" %> | |
} | |
file 'app/views/users/edit.html.erb', | |
%q{<h1>Edit My Account</h1> | |
<%= render :partial => "form" %> | |
<p><%= link_to "My Profile", account_path %></p> | |
} | |
file 'app/views/users/show.html.erb', | |
%q{ | |
<h1> | |
<%=h @user.display_name %> | |
</h1> | |
<p> | |
<b>Login count:</b> | |
<%=h @user.login_count %> | |
</p> | |
<p> | |
<b>Last request at:</b> | |
<%=h @user.last_request_at %> | |
</p> | |
<p> | |
<b>Last login at:</b> | |
<%=h @user.last_login_at %> | |
</p> | |
<p> | |
<b>Current login at:</b> | |
<%=h @user.current_login_at %> | |
</p> | |
<p> | |
<b>Last login ip:</b> | |
<%=h @user.last_login_ip %> | |
</p> | |
<p> | |
<b>Current login ip:</b> | |
<%=h @user.current_login_ip %> | |
</p> | |
<%= link_to 'Edit', edit_account_path %> | |
} | |
# --- Mailers --- | |
file 'app/models/notifier.rb', | |
%q{class Notifier < ActionMailer::Base | |
default_url_options[:host] = "example.com" | |
def password_reset_instructions(user) | |
subject "Password Reset Instructions" | |
from "Example Notifier " | |
recipients user.email | |
sent_on Time.now | |
body :edit_password_reset_url => edit_password_reset_url(user.perishable_token) | |
end | |
end | |
} | |
file 'app/views/notifier/password_reset_instructions.erb', | |
%q{A request to reset your password has been made. | |
If you did not make this request, simply ignore this email. If you did make this request just click the link below: | |
<%= @edit_password_reset_url %> | |
If the above URL does not work try copying and pasting it into your browser. If you continue to have problem please feel free to contact us. | |
} | |
# this file is generated by the rails_authorization_plugin, but need to add the "help postgres" lines | |
file 'app/models/roles_user.rb', | |
%q{class RolesUser < ActiveRecord::Base | |
belongs_to :user | |
belongs_to :role | |
# help postgres | |
set_primary_key :user_id | |
set_primary_key :role_id | |
end | |
} | |
file 'public/stylesheets/screen.css', | |
%q{/* | |
Copyright | |
*/ | |
/*\*/ | |
@import url("reset.css"); | |
@import url("typography.css"); | |
/**/ | |
} | |
file 'public/stylesheets/typography.css', | |
%q{/* | |
Copyright | |
*/ | |
html { | |
font-size:100.01%; | |
} | |
body { | |
background:#FFF; | |
color:#333; | |
font-family:"helvetica neue",helvetica,arial,sans-serif; | |
font-size:0.96em; /* IE6 equiv to pixel setting below */ | |
line-height:1.4; | |
} | |
html>body { | |
font-size:18px; | |
} | |
a:link, | |
a:visited { | |
color:#333; | |
text-decoration:none; | |
} | |
a:hover { | |
color:#555; | |
text-decoration:none; | |
} | |
a:active { | |
color:#111; | |
text-decoration:none; | |
} | |
a.buttonish { | |
font-weight:bold; | |
font-size:80%; | |
padding:5px 10px; | |
-moz-border-radius: 10px; | |
-webkit-border-radius: 10px; | |
} | |
a.buttonish:link, | |
a.buttonish:visited { | |
color:#333; | |
background:#999; | |
} | |
a.buttonish:hover { | |
color:#DDD; | |
background:#555; | |
} | |
a.buttonish:active { | |
color:#DDD; | |
background:#333; | |
} | |
} | |
file 'public/stylesheets/reset.css', | |
%q{/* | |
Reset styles via http://meyerweb.com/eric/thoughts/2007/05/01/reset-reloaded/ | |
Copyright 1995-2007 Eric A. and Kathryn S. Meyer | |
*/ | |
html, body, div, span, applet, object, iframe, | |
h1, h2, h3, h4, h5, h6, p, blockquote, pre, | |
a, abbr, acronym, address, big, cite, code, | |
del, dfn, em, font, img, ins, kbd, q, s, samp, | |
small, strike, strong, sub, sup, tt, var, | |
dl, dt, dd, ol, ul, li, | |
fieldset, form, label, legend, | |
table, caption, tbody, tfoot, thead, tr, th, td { | |
margin: 0; | |
padding: 0; | |
border: 0; | |
outline: 0; | |
font-weight: inherit; | |
font-style: inherit; | |
font-size: 100%; | |
font-family: inherit; | |
vertical-align: baseline; | |
} | |
address { | |
font-style:normal; /* IE6 doesn't get the picture in the first rule */ | |
} | |
/* remember to define focus styles! */ | |
:focus { | |
outline: 0; | |
} | |
body { | |
line-height: 1; | |
color: black; | |
background: white; | |
} | |
ol, ul { | |
list-style: none; | |
} | |
/* tables still need 'cellspacing="0"' in the markup */ | |
table { | |
border-collapse: separate; | |
border-spacing: 0; | |
} | |
caption, th, td { | |
text-align: left; | |
font-weight: normal; | |
} | |
blockquote:before, blockquote:after, | |
q:before, q:after { | |
content: ""; | |
} | |
blockquote, q { | |
quotes: "" ""; | |
} | |
} | |
#====================== | |
# INITIALIZERS | |
#---------------------- | |
initializer 'action_mailer_configs.rb', | |
%q{#ActionMailer::Base.smtp_settings = { | |
# :address => "smtp.opb.org", | |
# :port => 25, | |
# :domain => "opb.org" | |
#} | |
} | |
initializer 'errors.rb', | |
%q{# Example: | |
# begin | |
# some http call | |
# rescue *HTTP_ERRORS => error | |
# notify_hoptoad error | |
# end | |
HTTP_ERRORS = [Timeout::Error, | |
Errno::EINVAL, | |
Errno::ECONNRESET, | |
EOFError, | |
Net::HTTPBadResponse, | |
Net::HTTPHeaderSyntaxError, | |
Net::ProtocolError] | |
# SMTP_SERVER_ERRORS = [TimeoutError, | |
# IOError, | |
# Net::SMTPUnknownError, | |
# Net::SMTPServerBusy, | |
# Net::SMTPAuthenticationError] | |
# | |
# SMTP_CLIENT_ERRORS = [Net::SMTPFatalError, | |
# Net::SMTPSyntaxError] | |
# | |
# SMTP_ERRORS = SMTP_SERVER_ERRORS + SMTP_CLIENT_ERRORS | |
} | |
initializer 'time_formats.rb', | |
%q{# Example time formats | |
{ :short_date => "%x", :long_date => "%a, %b %d, %Y" }.each do |k, v| | |
ActiveSupport::CoreExtensions::Time::Conversions::DATE_FORMATS.update(k => v) | |
end | |
} | |
#====================== | |
# TEST | |
#---------------------- | |
inside ('test') do | |
run "mkdir factories" | |
end | |
file 'test/shoulda_macros/forms.rb', | |
%q{class Test::Unit::TestCase | |
def self.should_have_form(opts) | |
model = self.name.gsub(/ControllerTest$/, '').singularize.downcase | |
model = model[model.rindex('::')+2..model.size] if model.include?('::') | |
http_method, hidden_http_method = form_http_method opts[:method] | |
should "have a #{model} form" do | |
assert_select "form[action=?][method=#{http_method}]", eval(opts[:action]) do | |
if hidden_http_method | |
assert_select "input[type=hidden][name=_method][value=#{hidden_http_method}]" | |
end | |
opts[:fields].each do |attribute, type| | |
attribute = attribute.is_a?(Symbol) ? "#{model}[#{attribute.to_s}]" : attribute | |
assert_select "input[type=#{type.to_s}][name=?]", attribute | |
end | |
assert_select "input[type=submit]" | |
end | |
end | |
end | |
def self.form_http_method(http_method) | |
http_method = http_method.nil? ? 'post' : http_method.to_s | |
if http_method == "post" || http_method == "get" | |
return http_method, nil | |
else | |
return "post", http_method | |
end | |
end | |
end | |
} | |
file 'test/shoulda_macros/pagination.rb', | |
%q{class Test::Unit::TestCase | |
# Example: | |
# context "a GET to index logged in as admin" do | |
# setup do | |
# login_as_admin | |
# get :index | |
# end | |
# should_paginate_collection :users | |
# should_display_pagination | |
# end | |
def self.should_paginate_collection(collection_name) | |
should "paginate #{collection_name}" do | |
assert collection = assigns(collection_name), | |
"Controller isn't assigning to @#{collection_name.to_s}." | |
assert_kind_of WillPaginate::Collection, collection, | |
"@#{collection_name.to_s} isn't a WillPaginate collection." | |
end | |
end | |
def self.should_display_pagination | |
should "display pagination" do | |
assert_select "div.pagination", { :minimum => 1 }, | |
"View isn't displaying pagination. Add <%= will_paginate @collection %>." | |
end | |
end | |
# Example: | |
# context "a GET to index not logged in as admin" do | |
# setup { get :index } | |
# should_not_paginate_collection :users | |
# should_not_display_pagination | |
# end | |
def self.should_not_paginate_collection(collection_name) | |
should "not paginate #{collection_name}" do | |
assert collection = assigns(collection_name), | |
"Controller isn't assigning to @#{collection_name.to_s}." | |
assert_not_equal WillPaginate::Collection, collection.class, | |
"@#{collection_name.to_s} is a WillPaginate collection." | |
end | |
end | |
def self.should_not_display_pagination | |
should "not display pagination" do | |
assert_select "div.pagination", { :count => 0 }, | |
"View is displaying pagination. Check your logic." | |
end | |
end | |
end | |
} | |
file 'test/test_helper.rb', | |
%q{ENV["RAILS_ENV"] = "test" | |
require File.expand_path(File.dirname(__FILE__) + "/../config/environment") | |
require 'test_help' | |
require 'action_view/test_case' | |
class Test::Unit::TestCase | |
self.use_transactional_fixtures = true | |
self.use_instantiated_fixtures = false | |
self.backtrace_silencers << :rails_vendor | |
self.backtrace_filters << :rails_root | |
end | |
class ActionView::TestCase | |
# Enable UrlWriter when testing helpers | |
include ActionController::UrlWriter | |
# Default host for helper tests | |
default_url_options[:host] = HOST | |
end | |
} | |
#====================== | |
# FINALIZE | |
#---------------------- | |
run "rm public/index.html" | |
run "rm public/images/rails.png" | |
run 'find . \( -type d -empty \) -and \( -not -regex ./\.git.* \) -exec touch {}/.gitignore \;' | |
git :add => "." | |
git :commit => "-a -m 'Initial project commit'" | |
puts "" | |
puts "# Add the following to the top of config/environment.rb:" | |
puts "# Authorization Plugin config" | |
puts "AUTHORIZATION_MIXIN = 'object roles'" | |
puts "LOGIN_REQUIRED_REDIRECTION = '/login'" | |
puts "PERMISSION_DENIED_REDIRECTION = '/'" | |
puts "STORE_LOCATION_METHOD = :store_location" | |
puts "" | |
puts "run `rake app:bootstrap` to create the admin user" | |
puts "login: [email protected]" | |
puts "passwd: letmein" | |
puts "" | |
puts "All done!" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment