Skip to content

Instantly share code, notes, and snippets.

@mindreframer
Created December 24, 2009 18:07
Show Gist options
  • Save mindreframer/263288 to your computer and use it in GitHub Desktop.
Save mindreframer/263288 to your computer and use it in GitHub Desktop.
# mongo_template.rb
# fork of Ben Scofield's Rails MongoMapper Template (http://gist.github.com/181842)
#
# To use:
# rails project_name -m http://gist.github.com/gists/219223.txt
# remove unneeded defaults
run "rm public/index.html"
run "rm public/images/rails.png"
run "rm public/javascripts/controls.js"
run "rm public/javascripts/dragdrop.js"
run "rm public/javascripts/effects.js"
run "rm public/javascripts/prototype.js"
# add basic layout to start
file 'app/views/layouts/application.html.erb', <<-HTML
!!! Strict
%html{ "xml:lang" => "en", :lang => "en", :xmlns => "http://www.w3.org/1999/xhtml" }
%head
%title
Kitsune CMS
= javascript_include_tag 'http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js','application'
= stylesheet_link_tag 'application'
= yield :head
%body
#content
#header
%h1
#flash_messages
- [:notice,:error].each do |flash_type|
- if flash[flash_type]
%div{ :class => "flash_#\{flash_type\}" }
- unless flash[flash_type].is_a? Validatable::Errors
= flash[flash_type]
- else
- flash[flash_type].each do |n,msg|
= "#\{n\} #\{msg\}"
.main
= yield
HTML
# MongoDB FTW!
db_name = ask('What should I call the database? ')
initializer 'database.rb', <<-CODE
logger = Logger.new("log/mongo-#\{Rails.env\}.log")
MongoMapper.connection = Mongo::Connection.new('127.0.0.1',27017,:logger=>logger)
MongoMapper.database = "#{db_name}-#\{Rails.env\}"
if defined?(PhusionPassenger)
PhusionPassenger.on_event(:starting_worker_process) do |forked|
MongoMapper.database.connect_to_master if forked
end
end
CODE
file 'config/database.yml', <<-CODE
# Using MongoDB
CODE
# Don't need ActiveRecord
environment 'config.frameworks -= [:active_record]'
# MongoMapper
gem 'mongo_mapper'
# Testing Helper
file 'test/test_helper.rb', <<-CODE
ENV['RAILS_ENV'] = 'test'
require File.expand_path(File.dirname(__FILE__) + '/../config/environment')
require 'test_help'
require 'shoulda'
require 'mocha'
require 'factory_girl'
class ActiveSupport::TestCase
# Drop all columns after each test case.
def teardown
MongoMapper.database.collections.each do |coll|
coll.remove
end
end
# Make sure that each test case has a teardown
# method to clear the db after each test.
def inherited(base)
base.define_method teardown do
super
end
end
end
CODE
file 'lib/metaid.rb', %q{
class Object
# The hidden singleton lurks behind everyone
def metaclass; class << self; self; end; end
alias_method :singleton_class, :metaclass
def meta_eval(&blk)
metaclass.instance_eval &blk
end
def meta_class_eval(code=nil, &blk)
if code.nil?
metaclass.class_eval &blk
else
metaclass.class_eval code, &blk
end
end
# Adds methods to a metaclass
def meta_def name, &blk
meta_eval { define_method name, &blk }
end
# Defines an instance method within a class
def class_def name, &blk
class_eval { define_method name, &blk }
end
end
}
file 'lib/authentication.rb', <<-HTML
# include this in application controller
module Authentication
protected
# Inclusion hook to make #current_user and #signed_in?
# available as ActionView helper methods.
def self.included(base)
base.send :helper_method, :current_user, :signed_in?, :authorized? if base.respond_to? :helper_method
end
# Returns true or false if the user is signed in.
# Preloads @current_user with the user model if they're signed in.
def signed_in?
!!current_user
end
# Accesses the current user from the session.
# Future calls avoid the database because nil is not equal to false.
def current_user
@current_user ||= (sign_in_from_session || sign_in_from_basic_auth) unless @current_user == false
end
# Store the given user id in the session.
def current_user=(new_user)
session[:user_id] = new_user ? new_user.id : nil
@current_user = new_user || false
end
# Check if the user is authorized
#
# Override this method in your controllers if you want to restrict access
# to only a few actions or if you want to check if the user
# has the correct rights.
#
# Example:
#
# # only allow nonbobs
# def authorized?
# current_user.name != "bob"
# end
#
def authorized?(action=nil, resource=nil, *args)
signed_in?
end
# Filter method to enforce a sign_in requirement.
#
# To require sign_ins for all actions, use this in your controllers:
#
# before_filter :sign_in_required
#
# To require sign_ins for specific actions, use this in your controllers:
#
# before_filter :sign_in_required, :only => [ :edit, :update ]
#
# To skip this in a subclassed controller:
#
# skip_before_filter :sign_in_required
#
def authenticate
authorized? || access_denied
end
# Redirect as appropriate when an access request fails.
#
# The default action is to redirect to the sign_in screen.
#
# Override this method in your controllers if you want to have special
# behavior in case the user is not authorized
# to access the requested action. For example, a popup window might
# simply close itself.
def access_denied
respond_to do |format|
format.html do
store_location
flash[:error] = "You must be logged in to do that."
redirect_to new_session_path
end
# format.any doesn't work in rails version < http://dev.rubyonrails.org/changeset/8987
# you may want to change format.any to e.g. format.any(:js, :xml)
format.any do
request_http_basic_authentication 'Web Password'
end
end
end
# Store the URI of the current request in the session.
#
# We can return to this location by calling #redirect_back_or_default.
def store_location
session[:return_to] = request.request_uri
end
# Redirect to the URI stored by the most recent store_location call or
# to the passed default. Set an appropriately modified
# after_filter :store_location, :only => [:index, :new, :show, :edit]
# for any controller you want to be bounce-backable.
def redirect_back_or_default(default)
redirect_to(session[:return_to] || default)
session[:return_to] = nil
end
# Called from #current_user. First attempt to sign_in by the user id stored in the session.
def sign_in_from_session
if session[:user_id]
self.current_user = User.find_by_id(session[:user_id])
end
end
# Called from #current_user. Now, attempt to sign_in by basic authentication information.
def sign_in_from_basic_auth
authenticate_with_http_basic do |email, password|
self.current_user = User.authenticate(email, password)
end
end
# This is ususally what you want; resetting the session willy-nilly wreaks
# havoc with forgery protection, and is only strictly necessary on sign_in.
# However, **all session state variables should be unset here**.
def sign_out_keeping_session!
# Kill server-side auth cookie
@current_user = false # not signed in, and don't do it for me
session[:user_id] = nil # keeps the session but kill our variable
# explicitly kill any other session variables you set
end
# The session should only be reset at the tail end of a form POST --
# otherwise the request forgery protection fails. It's only really necessary
# when you cross quarantine (signed-out to signed-in).
def sign_out_killing_session!
sign_out_keeping_session!
reset_session
end
end
HTML
file 'app/models/user.rb', %q{require 'digest/sha1'
require 'bcrypt'
class User
include MongoMapper::Document
include Roleful
key :username, String, :required => true
key :email, String, :required => true
key :crypted_password, String
key :reset_password_code, String
key :reset_password_code_until, Time
key :role, String
# roleful
role :admin do
can :edit_content
can :edit_categories
end
role :publisher do
can :edit_content
end
RegEmailName = '[\w\.%\+\-]+'
RegDomainHead = '(?:[A-Z0-9\-]+\.)+'
RegDomainTLD = '(?:[A-Z]{2}|com|org|net|gov|mil|biz|info|mobi|name|aero|jobs|museum)'
RegEmailOk = /\A#{RegEmailName}@#{RegDomainHead}#{RegDomainTLD}\z/i
def self.authenticate(email, secret)
u = User.first(:conditions => {:email => email.downcase})
u && u.authenticated?(secret) ? u : nil
end
validates_length_of :username, :within => 6..15
validates_length_of :email, :within => 6..100, :allow_blank => true
validates_format_of :email, :with => RegEmailOk, :allow_blank => true
PasswordRequired = Proc.new { |u| u.password_required? }
validates_presence_of :password, :if => PasswordRequired
validates_confirmation_of :password, :if => PasswordRequired, :allow_nil => true
validates_length_of :password, :minimum => 6, :if => PasswordRequired, :allow_nil => true
def authenticated?(secret)
password == secret ? true : false
end
def password
if crypted_password.present?
@password ||= BCrypt::Password.new(crypted_password)
else
nil
end
end
def password=(value)
if value.present?
@password = value
self.crypted_password = BCrypt::Password.create(value)
end
end
def email=(new_email)
new_email.downcase! unless new_email.nil?
write_attribute(:email, new_email)
end
def password_required?
crypted_password.blank? || !password.blank?
end
def set_password_code!
seed = "#{email}#{Time.now.to_s.split(//).sort_by {rand}.join}"
self.reset_password_code_until = 1.day.from_now
self.reset_password_code = Digest::SHA1.hexdigest(seed)
save!
end
end
}
file 'app/controllers/application_controller.rb', %q{class ApplicationController < ActionController::Base
include Authentication
helper :all # include all helpers, all the time
protect_from_forgery
before_filter :store_location
filter_parameter_logging :password
protected
def login_required
if !current_user
flash[:notice] = "Please log in."
redirect_to signin_url
else
return true
end
end
end
}
# Testing tools
gem 'redgreen'
gem 'factory_girl'
gem 'haml'
gem 'will_paginate'
gem 'cucumber'
gem 'webrat'
gem 'rails-footnotes'
# for inherited_resources
gem "responders"
gem "has_scope"
gem 'mongo_mapper'
####### plugins
plugin "attribute-mapper", :git => "git://github.com/therealadam/attribute_mapper.git"
plugin "compass", :git => "git://github.com/chriseppstein/compass.git"
plugin "inherited_resources", :git => "git://github.com/josevalim/inherited_resources.git"
plugin "roleful", :git => "git://github.com/nakajima/roleful.git"
plugin "paperclip", :git => "git://github.com/thoughtbot/paperclip.git"
if yes?("Do you want to use RSpec?")
plugin "rspec", :git => "git://github.com/dchelimsky/rspec.git"
plugin "rspec-rails", :git => "git://github.com/dchelimsky/rspec-rails.git"
plugin "single_test", :git => "git://github.com/grosser/single_test.git"
generate :rspec
file 'spec/spec.opts', %q{
--colour
--format progress
--loadby mtime
--reverse
--drb
--backtrace
}
file 'spec/spec_helper.rb', %q{
# This file is copied to ~/spec when you run 'ruby script/generate rspec'
# from the project root directory.
ENV["RAILS_ENV"] ||= 'test'
require 'spork'
require 'spec/spork_hack'
Spork.prefork do
require File.expand_path(File.join(File.dirname(__FILE__),'..','config','environment'))
require 'spec/autorun'
require 'spec/rails'
# Uncomment the next line to use webrat's matchers
#require 'webrat/integrations/rspec-rails'
# Requires supporting files with custom matchers and macros, etc
Dir[File.expand_path(File.join(File.dirname(__FILE__),'support','**','*.rb'))].each {|f| require f}
Spec::Runner.configure do |config|
# == Mock Framework
config.mock_with :mocha
# config.mock_with :flexmock
# config.mock_with :rr
end
end
}
file 'spec/spork_hack.rb', %q{
begin
require 'spork/app_framework/rails'
module Spork::AppFramework::Rails::NinjaPatcher
# views are preloaded <-> spork must be restarted for view changes
def delay_eager_view_loading
puts "removed because i am too slow..."
end
# do not preload application files <-> fast test start
# not needed when config.cache_classes = false
# def delay_app_preload
# ::Rails::Initializer.send(:define_method, :load_application_classes) do
# end
# end
end
rescue
end
}
else
gem 'shoulda'
end
generate :haml, '--rails'
generate :cucumber
# Gem management
rake 'gems:install'
rake 'gems:unpack'
#rake 'rails:freeze:gems'
# source control
file '.gitignore', <<-FILES
.DS_Store
**/.DS_Store
log/*
tmp/*
tmp/**/*
config/database.yml
coverage/*
coverage/**/*
FILES
git :init
git :add => '.'
git :commit => '-a -m "Initial commit"'
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment