require 'pp'
def print_class_counts
c = Hash.new 0
ObjectSpace.each_object(Object) do |o|
c[o.class] += 1
end
pp c.sort_by{|k,v|v}.reverse
end
Reveal More
require 'pp'
def print_class_counts
c = Hash.new 0
ObjectSpace.each_object(Object) do |o|
c[o.class] += 1
end
pp c.sort_by{|k,v|v}.reverse
end
# Invalid page numbers (e.g. "abc" or "0") will redirect to the home page
# You might also consider serving a 404
before do
redirect '/', 302 if params[:page] && params[:page].to_i == 0 # refuse bogus page #s
end
# config.ru at the old domain
run lambda {|env| [301, {'Content-Type'=>'text/html', 'Location'=>"http://newdomain.com#{env['PATH_INFO']}"}, ['Redirecting...']]}
class Hello
extend ActionView::Helpers::TagHelper
extend ActionView::Helpers::TextHelper
def world(text)
simple_format(text) # simple_format is made available via "extend"
end
end
You can use the console and run system commands to get version info:
To get the version of Bundler:
heroku console %x{bundle -v}
To get the version of imagemagick:
heroku console %x{identify -version}
...etc...
Annoyingly, postgres makes is very annoying to pass in your password when using pg_dump. There's a way around it, though...
PGPASSWORD=YOUR_PASS pg_dump -Fc --username=YOUR_USER --host=YOUR_HOST YOUR_DB_NAME > YOUR_BACKUP_FILE
# /etc/init/couchdb-lucene.conf
description "CouchDB-Lucene server"
script
cd /PATH/TO/couchdb_lucene
exec sudo -u couchdb ./bin/run
end script
post-start script
# hack to create a pid file
CDB_PID=`status couchdb-lucene |egrep -oi '([0-9]+)$' |head -n1`
echo $CDB_PID >/var/run/couchdb-lucene.pid
end script
# monit
check process couchdb_lucene with pidfile /var/run/couchdb-lucene.pid
group database
start program = start couchdb-lucene
stop program = stop couchdb-lucene
if failed host 127.0.0.1 port 5985 then restart
if cpu is greater than 40% for 2 cycles then alert
if cpu > 60% for 5 cycles then restart
if 10 restarts within 10 cycles then timeout
depends on couchdb
# The Sinatra app behind http://clickthatbutton.com/ running on http://heroku.com
# I can't figure out how to increment the "clicks" counter and get the db to return
# the new total without doing another request... holler if you know how...
# I tried to use Sequel and ended up getting pissed off somehow, so reverted to
# using Active Record and laying in the hammock.
require 'rubygems'
require 'sinatra'
require 'erb'
require 'active_record'
dbconfig = YAML.load(File.read('config/database.yml'))
ActiveRecord::Base.establish_connection dbconfig['production']
class CreateClicks < ActiveRecord::Migration
def self.up
create_table :clicks do |t|
t.integer :clicks, :default => 0, :null => false
end
Click.create!(:clicks => 0)
end
end
class Click < ActiveRecord::Base
end
get '/' do
response.set_cookie('click', 0) if request.cookies['click'].nil?
@clicks_total = Click.first.clicks
erb :index
end
post '/' do
Click.first.increment!(:clicks)
Click.first.clicks.to_s
end
class VotesController < ApplicationController
def create
@video = Video.find(params[:id])
@voted_for = cookies[:voted_for] ? cookies[:voted_for].split(",") : []
if @voted_for.include?(@video.id.to_s)
render :text => "You already voted for #{@video}!"
else
render :text => "Thanks for voting for #{@video}!"
cookies[:voted_for] ||= []
cookies[:voted_for] = cookies[:voted_for] << "#{@video.id},"
Video.increment_counter(:votes, @video.id)
end
end
end
# I'm not sure if there's a better way to do this, but it works...
# The tests look like:
test "deals with dupe slugs automatically" do
v1 = Video.make(:name => "Nick Vegas")
v2 = Video.make(:name => "Nick Vegas")
v3 = Video.make(:name => "Nick Vegas")
assert_equal "nickvegas", v1.slug
assert_equal "nickvegas2", v2.slug
assert_equal "nickvegas3", v3.slug
end
# The model and relevant code looks like:
class Video < ActiveRecord::Base
before_validation :generate_slug
validates_presence_of :slug
validates_uniqueness_of :slug
def generate_slug
slug = name.parameterize.gsub('-', '')
if Video.find_by_slug(slug)
counter = 2
until Video.find_by_slug("#{slug}#{counter}").nil?
counter += 1
end
slug = "#{slug}#{counter}"
end
self.slug = slug
rescue
# use validations to catch errors
end
end
# http://github.com/crafterm/sprinkle
# http://couchdb.apache.org/
# http://wiki.apache.org/couchdb/API_Cheatsheet
# Requires the rubygems: rubygems right_aws right_http_connection json
package :couchdb_compaction do
config_file = '/etc/cron.weekly/couchdb_compaction'
config_text = %q[
#!/usr/bin/ruby
%w(rubygems right_aws right_http_connection json).each { |f| require f }
dbs = JSON.parse %x(curl -sS 'http://localhost:5984/_all_dbs')
dbs.each do |db|
%x(curl -X POST -sS 'http://localhost:5984/#{db}/_compact')
%x(curl -X POST -sS 'http://localhost:5984/#{db}/_view_cleanup')
design_docs = JSON.parse %x(curl -sS 'http://localhost:5984/#{db}/_all_docs?startkey=%22_design%2F%22&endkey=%22_design0%22')
design_docs.each do |doc|
name = doc[1][0]['id'].gsub('_design/', '') rescue nil
%x(curl -X POST -sS 'http://localhost:5984/#{db}/_compact/#{name}') if name
end
end
].lstrip
push_text config_text, config_file do
pre :install, "touch #{config_file}"
post :install, "chmod 0755 #{config_file}"
end
verify do
has_file config_file
end
end
Place the following in your ~/.ssh/config:
StrictHostKeyChecking no
UserKnownHostsFile /dev/null
# Modified from the original to store the regexp in a constant, to simplify
# the removable of the trailing slash, and to utilize Rack to rebuild the URL.
module Rack
class TrailingSlash
HAS_TRAILING_SLASH = %r{^/(.*)/$}
def initialize(app)
@app = app
end
def call(env)
if env['PATH_INFO'] =~ HAS_TRAILING_SLASH
env['PATH_INFO'].chomp!('/')
[301, {"Location" => Rack::Request.new(env).url}, []]
else
@app.call(env)
end
end
end
end
# NOTE: real-world experience shows this may not work if used behind Varnish,
# because the port will be changed due to the proxy_pass...
# Websites should have a canonical address. This address shouldn’t begin with “www” because
# it’s unnecessary and wasteful. See http://no-www.org/ for details. This middleware catches
# requests that begin with “www” and redirects them to the more reasonable non-www address.
# Rails Usage
# Put this file in lib/, and then add the following to config/environment.rb:
# Rails::Initializer.run do |config|
# config.middleware.use “NoWWW” if RAILS_ENV == ‘production’
# end
class NoWWW
STARTS_WITH_WWW = /^www\./i
def initialize(app)
@app = app
end
def call(env)
if env['HTTP_HOST'] =~ STARTS_WITH_WWW
[301, { 'Location' => Rack::Request.new(env).url.sub(/www\./i, '') }, ['Redirecting...']]
else
@app.call(env)
end
end
end
# Thanks for the tip! I had to do the following for this app, but it works much better now - much, much faster!
class User < TwitterAuth::GenericUser
def twitter_following_ids # ids of users followed on twitter
twitter.get("/friends/ids").collect! { |id| id.to_s }
rescue
nil
end
end
Flowcoder.on_heroku? # => true
require 'net/http'
require 'uri'
class Post < ActiveRecord::Base
before_save :pygmentize_body
def pygmentize_body
self.pygmentized_body = Net::HTTP.post_form(URI.parse('http://pygments.appspot.com/'), {'lang'=>language, 'code'=>body}).body
end
end
# Then you can call @post.pygmentized_body to get the stored HTML with syntax highlighting without doing another request
# Flowcoder is now using http://pygments.appspot.com/ to get pygments code syntax highlighting
require 'net/http'
require 'uri'
lang = 'python'
code = 'print "Hello World"'
request = Net::HTTP.post_form(URI.parse('http://pygments.appspot.com/'), {'lang'=>lang, 'code'=>code})
puts request.body
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Label</key>
<string>nginx</string>
<key>Program</key>
<string>/opt/nginx/sbin/nginx</string>
<key>KeepAlive</key>
<true/>
<key>NetworkState</key>
<true/>
<key>StandardErrorPath</key>
<string>/opt/nginx/logs/error.log</string>
<key>LaunchOnlyOnce</key>
<true/>
</dict>
</plist>
alias herokubackup='cd ~/code/backups &&
heroku db:pull sqlite://my_app.db --app my_app &&
heroku db:pull sqlite://my_other_app.db --app my_other_app &&
DATE=`date +%Y-%m-%d` &&
mkdir $DATE &&
mv *.db $DATE'