Skip to content

Instantly share code, notes, and snippets.

@LeFnord
Created November 12, 2010 18:24
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save LeFnord/674468 to your computer and use it in GitHub Desktop.
Save LeFnord/674468 to your computer and use it in GitHub Desktop.
An application template for Rails 3 including: authlogic, haml, rspec, compass-susy, jquery ... go running ;)
# An application template for Rails 3
gem "factory_girl_rails", :group => [:development, :test]
gem "factory_girl_generator", :group => [:development, :test]
gem "rspec", :group => [:development, :test]
gem "rspec-rails", :group => [:development, :test]
gem "haml"
gem "haml-rails"
gem "authlogic", :git => "git://github.com/odorcicd/authlogic.git", :branch => "rails3"
begin
require 'bundler'
rescue Bundler::GemNotFound => e
STDERR.puts e.message
exit!
end
compass = ask("would you use 'compass'? [Yn]")
plugin = "4"
if compass == "Y"
gem "compass"
plugin = ask("which plugin do you want to use? susy[1], tfg[2], 960[3], blueprint[4]")
case plugin
when "1"
gem "compass-susy-plugin"
when "2"
gem "compass-tfg-plugin"
when "3"
gem "compass-960-plugin"
end
end
run 'bundle install'
run 'rails g rspec:install'
generators = <<-GENERATORS
config.generators do |g|
g.test_framework :rspec, :fixture => true, :views => false
g.integration_tool :rspec, :fixture => true, :views => true
g.template_engine :haml
end
GENERATORS
application generators
if !options["skip_prototype"]
# removing prototype files
remove_file "public/javascripts/controls.js"
remove_file "public/javascripts/dragdrop.js"
remove_file "public/javascripts/effects.js"
remove_file "public/javascripts/prototype.js"
remove_file "public/javascripts/jrails.js"
end
# getting jquery and rails.js for jquery
get "http://code.jquery.com/jquery-1.4.4.min.js", "public/javascripts/jquery.js"
get "https://github.com/rails/jquery-ujs/raw/master/src/rails.js", "public/javascripts/rails.js"
# ... and use it!
gsub_file 'config/application.rb', 'config.action_view.javascript_expansions[:defaults] = %w()', 'config.action_view.javascript_expansions[:defaults] = %w(jquery rails application)'
# describing of layout application
layout = <<-LAYOUT
!!!
%html
%head
%title= h(yield(:title) || "Untitled")
= stylesheet_link_tag :all
= javascript_include_tag :defaults
= csrf_meta_tag
= yield(:head)
%body
#container
- flash.each do |name, msg|
= content_tag :div, msg, :id => "flash_\#\{name\}", :class => 'flash'
%nav
= link_to "Home", root_url
- if current_user
= link_to "Sign out", logout_path
%header
- if show_title?
%h1=h yield(:title)
%article
= yield
%footer
LAYOUT
# ... and a layout helper
layout_helper = <<-LAYOUTHELPER
# These helper methods can be called in your template to set variables to be used in the layout
# This module should be included in all views globally,
# to do so you may need to add this line to your ApplicationController
# helper :layout
module LayoutHelper
def title(page_title, show_title = true)
content_for(:title) { page_title.to_s }
@show_title = show_title
end
def show_title?
@show_title
end
def stylesheet(*args)
content_for(:head) { stylesheet_link_tag(*args) }
end
def javascript(*args)
content_for(:head) { javascript_include_tag(*args) }
end
end
LAYOUTHELPER
# removing unused files
remove_file "README"
remove_file "public/index.html"
remove_file "public/images/rails.png"
remove_file "app/views/layouts/application.html.erb"
# creating the new ones
create_file 'README'
create_file "app/views/layouts/application.html.haml", layout
create_file "app/helpers/layout_helper.rb", layout_helper
# make authlogic session available
run "rails g authlogic:session user_session"
# fix it for running with rails3
inject_into_file "app/models/user_session.rb", "\n\tdef to_key\n\t\tnew_record? ? nil : [ self.send(self.class.primary_key) ]\n\tend", :after => "class UserSession < Authlogic::Session::Base"
# creating user model
foo = run "rails g model User"
match = foo.match(/db\/migrate\/.+/)
# change migration for usage with authlogic,
# uncomment magic fields for your needs
user_migration = <<-MIGRATION
class CreateUsers < ActiveRecord::Migration
def self.up
create_table :users do |t|
t.string :login, :null => false
t.string :email, :null => false
t.string :crypted_password, :null => false
t.string :password_salt, :null => false
t.string :persistence_token, :null => false
#t.string :single_access_token, :null => false # optional, see Authlogic::Session::Params
#t.string :perishable_token, :null => false # optional, see Authlogic::Session::Perishability
# magic fields (all optional, see Authlogic::Session::MagicColumns)
# t.integer :login_count, :null => false, :default => 0
# t.integer :failed_login_count, :null => false, :default => 0
# t.datetime :last_request_at
# t.datetime :current_login_at
# t.datetime :last_login_at
# t.string :current_login_ip
# t.string :last_login_ip
t.timestamps
end
add_index :users, [:login], :name => "index_users_on_login", :unique => true
add_index :users, [:email], :name => "index_users_on_email", :unique => true
add_index :users, [:persistence_token], :name => "index_users_on_persistence_token", :unique => true
end
def self.down
drop_table :users
end
end
MIGRATION
# removing and creating the edited user migration, simpler as injection
remove_file match[0]
create_file match[0], user_migration
# now make it act_as_authentic, using authlogic
inject_into_file "app/models/user.rb", "\n\tacts_as_authentic", :after => "class User < ActiveRecord::Base"
# build database from realy from scratch
run "rake db:drop:all"
run "rake db:create"
run "rake db:migrate"
# user related stuff
# scaffolding the user
run "rails g scaffold_controller User"
# adding filter for authentication
inject_into_file "app/controllers/users_controller.rb", "\n\tbefore_filter :require_no_user, :only => [:new, :create]\n\tbefore_filter :require_user, :except => [:new, :create]", :after => "class UsersController < ApplicationController"
# changing the redirect url in destroy action of user
gsub_file "app/controllers/users_controller.rb", "format.html { redirect_to(users_url) }", "format.html { redirect_to(root_path, :notice => 'User was successfully destroyed.') }"
# templates for user views
user_form = <<-USERFORM
= form_for @user do |f|
-if @user.errors.any?
#error_explanation
%h2= "\#\{pluralize(@user.errors.count, "error")\} prohibited this user from being saved:"
%ul
- @user.errors.full_messages.each do |msg|
%li= msg
%p
= f.label :login
%br
= f.text_field :login
%p
= f.label :email
%br
= f.text_field :email
%p
= f.label :password
%br
= f.password_field :password
%p
= f.label :password_confirmation
%br
= f.password_field :password_confirmation
.actions
= f.submit 'Save'
USERFORM
user_edit = <<-USEREDIT
-title "Editing user"
= render 'form'
= link_to 'Show', @user
\|
= link_to 'Back', users_path
USEREDIT
user_index = <<-USERINDEX
-title "Listing users"
%table
%tr
%th Login
%th Email
%th Actions
- @users.each do |user|
%tr
%td= user.login
%td= user.email
%td.actions
= link_to 'Edit', edit_user_path(user)
= link_to 'Show', user
%br
= link_to 'New User', new_user_path
USERINDEX
user_new = <<-USERNEW
-title "New user"
= render 'form'
= link_to 'Back', users_path
USERNEW
user_show = <<-USERSHOW
- title "Show User"
Login
= @user.login
%br
Email
= @user.email
= link_to 'Edit', edit_user_path(@user)
\|
= link_to 'Back', users_path
- if current_user == @user
|
= link_to 'Destroy', user_destroy_path(@user), :confirm => 'Are you sure?', :method => :delete
USERSHOW
# removing the scaffolded user views
remove_file "app/views/users/_form.html.haml"
remove_file "app/views/users/edit.html.haml"
remove_file "app/views/users/index.html.haml"
remove_file "app/views/users/new.html.haml"
remove_file "app/views/users/show.html.haml"
# ... replac by your own
create_file "app/views/users/_form.html.haml", user_form
create_file "app/views/users/edit.html.haml", user_edit
create_file "app/views/users/index.html.haml", user_index
create_file "app/views/users/new.html.haml", user_new
create_file "app/views/users/show.html.haml", user_show
# more general stuff for authentication
# add helper methods for authentication to app controller
application_controller = <<-AUTHHELPER
helper :all
helper_method :current_user_session, :current_user
private
def current_user_session
logger.debug "ApplicationController::current_user_session"
return @current_user_session if defined?(@current_user_session)
@current_user_session = UserSession.find
end
def current_user
logger.debug "ApplicationController::current_user"
return @current_user if defined?(@current_user)
@current_user = current_user_session && current_user_session.user
end
def require_user
logger.debug "ApplicationController::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
logger.debug "ApplicationController::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
AUTHHELPER
# ... and inject there
inject_into_file "app/controllers/application_controller.rb", "\n\n#{application_controller}", :after => "protect_from_forgery"
# creating user session controller
run "rails g controller UserSessions new"
# add new, create destroy actions in session controller
session_controller =<<-SESSION
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 users_url
else
flash[:error] = "Something was wrong!"
render :action => :new
end
end
def destroy
current_user_session.destroy
flash[:notice] = "Logout successful!"
redirect_back_or_default root_url
end
SESSION
# ... and inject there
inject_into_file "app/controllers/user_sessions_controller.rb", "\n#{session_controller}", :after => "class UserSessionsController < ApplicationController"
# template for new user session
new_user = <<-NEWUSER
- title "Login"
= form_for :user_session, :url => {:action => "create"} do |f|
%div
= f.label :login
= f.text_field :login
%div
= f.label :password
= f.password_field :password
%div
= f.check_box :remember_me
= f.label :remember_me
%div
= f.submit "Login"
NEWUSER
# removing old one
remove_file "app/views/user_sessions/new.html.haml"
# and creating from template
create_file "app/views/user_sessions/new.html.haml", new_user
# at last creating welcom controller
run "rails g controller Welcome index"
welcome_index = <<-WELCOME
-title "Welcome#index"
#user_nav
- if !current_user
= link_to "Sign in", login_path
or
= link_to "New User", new_user_path
WELCOME
# change the index view
remove_file "app/views/welcome/index.html.haml"
create_file "app/views/welcome/index.html.haml", welcome_index
# adding correct routes
new_routes = <<-ROUTES
match 'login' => "user_sessions#new", :as => :login
match 'logout' => "user_sessions#destroy", :as => :logout
resources :user_sessions
resources :users
match "user/destroy/:id" => "users#destroy", :as => :user_destroy, :method => :delete
root :to => 'welcome#index'
ROUTES
# ... inject there
inject_into_file "config/routes.rb", "\n#{new_routes}", :after => "#{app_name.classify}::Application.routes.draw do"
if compass == "Y"
# at last initialising the rails project for compass with susy plugin
case plugin
when "1"
run "compass init rails . -x scss -r susy --using susy/project --sass-dir public/stylesheets/sass --css-dir public/stylesheets"
when "2"
run "compass init rails . -x scss -r compass-tfg --sass-dir public/stylesheets/sass --css-dir public/stylesheets"
when "3"
run "compass init rails . -x scss -r ninesixty --using 960 --sass-dir public/stylesheets/sass --css-dir public/stylesheets"
when "4"
run "compass init rails . -x scss --using blueprint/semantic --sass-dir public/stylesheets/sass --css-dir public/stylesheets"
end
# adding some defaults for susy [my opinion]
if plugin == "1"
susy_screen =<<-SUSYSCREEN
h1,h2,h3,h4,h5 {
text-shadow: 2px 1px 2px #aaa;
color: $alt;
}
a {
@include sans-family;
@include adjust-font-size-to(13px);
padding: 1px;
color: #413630;
&:link, &:visited {
color: $alt;
}
&:focus, &:hover, &:active {
color: darken($base,5);
text-decoration: none;
}
img {
border: none;
}
}
/* Header --------------------------------------------------------------*/
/* others --------------------------------------------------------------*/
.flash {
@include sans-family;
@include adjust-font-size-to(13px);
text-align: center;
visibility: visible;
overflow: visible;
z-index: 1000;
}
#flash_notice {
background-color: #ccffcc;
border: solid 1px #66cc66; }
#flash_error {
background-color: #ffcccc;
border: solid 1px #cc6666; }
.active {
color: red;
}
SUSYSCREEN
susy_app = <<-SUSYAPP
= stylesheet_link_tag 'screen.css', :media => 'screen, projection'
= stylesheet_link_tag 'print.css', :media => 'print'
= stylesheet_link_tag 'ie.css', :media => 'screen, projection'
SUSYAPP
# and inject there
inject_into_file "public/stylesheets/sass/screen.scss", "\n#{susy_screen}", :after => "/* Styles -------------------------------------------------------------- */"
gsub_file "app/views/layouts/application.html.haml", "= stylesheet_link_tag :all", "#{susy_app}"
gsub_file "public/stylesheets/sass/screen.scss", ".container {", "#container {"
end
end
docs = <<-DOCS
Run the following commands to complete the setup of #{app_name.humanize}:
gemset create #{app_name}
% go to directory and let rails go ;)"
cd #{app_name}
rails s"
DOCS
log docs
@LeFnord
Copy link
Author

LeFnord commented Nov 18, 2010

a template for rapid starting a rails3 app, includes

  • authlogic, rails3 branch
  • jquery instead of protoype
  • haml, and if you want compass with 960/tfg/susy plugon (default: blueprint)
  • for testing it would be used rspec, factory-girl

to use it, run:

rails new -m /template/path -d <yourdatabase> -J

that's all, you have now a rails3 app up and running ;)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment