通过Capistrano部署Rails App到Hostmonster

贴贴我通过Capistrano自动发布到Hostmonster的deploy.rb文件吧

set :application, "huangzhimin.com"
set :repository,  "GIT_REPOSITORY"
set :user, "huangzhi"
set :scm, :git
set :deploy_to, "DEPLOY_DIRECTORY"

role :app, "www.huangzhimin.com"
role :web, "www.huangzhimin.com"
role :db,  "www.huangzhimin.com", :primary => true

set :use_sudo, false
set :run_method, :run

namespace(:deploy) do
  task :after_update_code, :roles => :app do
    run "ln -s #{shared_path}/config/database.yml #{current_release}/config/database.yml"
    run "cp #{shared_path}/config/environment.rb #{current_release}/config/"
    run "chmod -R u+rwX,go-w #{current_release}/public #{current_release}/log"
  end

  task :restart do
    web.disable
    migrate
    cleanup
    web.enable
  end
end

namespace :web do
  desc "Serve up a custom maintenance page."
  task :disable, :roles => :web do
    require 'erb'
    on_rollback {run "rm #{shared_path}/system/maintenance.html"}
    reason = ENV['REASON']
    deadline = ENV['UNTIL']
    template = File.read("#{current_release}/app/views/maintenance/index.html.erb")
    page = ERB.new(template).result(binding)
    put page, "#{shared_path}/system/maintenance.html", :mode => 0644
  end
end

将GIT_REPOSITORY和DEPLOY_DIRECTORY分别替换为你自己的git repository地址,和rails app发布到的目录。我是自己在Hostmonster上面建了一个git server,然后设置好公私密钥,这样省去了每次都输入密码的烦恼。

第四行将scm设为git,默认是svn的,所以要显示设置一下。

15-19行,定义在部署之后要做的操作:

  1. 为config/database.yml做一个软链接,因为database.yml文件是被git ignore的。
  2. 复制config/environment.rb文件,因为需要加入ENV['RAILS_ENV'] ||= 'production'这句话,强制使用production环境。
  3. 设置public和log的目录权限为755,因为在hostmonster上面public的目录对其它用户必须是不可写的,而capistrano默认是设置为775的。

31-39行,则是在部署的时候生成一个maintenance.html文件,表示系统正在维护,等部署完毕之后再删除,提供给用户一个比较友好的错误页面。

本来restart的task是用./script/process/reaper --action=restart --dispatcher=dispatch.fcgi命令的,不过rails2.3.2中已经没有process目录了,只得作罢。

Posted in  capistrano rails hostmonster


Rspec测试render :nothing => true

对于controller render/redirect的测试,一般对应以下的测试方法

render :action => :index
response.should render_template('index')

render :partial => 'post'
response.should render_template('_post')

redirect_to login_path
response.should redirect_to(login_path)

但是对于render :nothing = true来说,并没有相应的方法来测试,也无法用render_template来解决,只能是判断返回的response的内容是不是为空了。

response.should have_text(' ')

注意是 ,不是,至于为什么有个空格?我也没有仔细研究

Posted in  rails rspec


ActiveRecord Without Rails

前几天写了个小程序,帮我选号买彩票。主要是去网上抓取历次的开奖号码,存到数据库,然后再做统计分析。

因为程序很小,所以实在不想把Java这个大胖子叫出来,就简单地在vi下写了几十行的ruby代码。由于要用到数据库,自然想到了ActiveRecord,平时都是在Rails环境下用的,现在却是要让它脱离出来,闹独立。

首先是在mysql中新建数据库:

mysqladmin -uroot create caipiao

接着当然应该是定义database.yml

adapter: mysql
encoding: utf8
database: caipiao
username: root
password:
socket: /var/run/mysqld/mysqld.sock

定义migration,新建db/migrate目录,新建migration文件,注意前面加上数字前缀,001_xxx, 002_yyy,migration文件内容就和rails中的一模一样。

class CreateRedBlueBalls < ActiveRecord::Migration
  def self.up
    create_table :red_blue_balls do |t|
      t.integer :number
    end
  end

  def self.down
    drop_table :red_blue_balls
  end
end

最关键的是Rakefile文件

require 'active_record'
require 'yaml'

task :default => :migrate

task :migrate => :environment do
  ActiveRecord::Migrator.migrate('db/migrate', ENV["VERSION"] ? ENV["VERSION"].to_i : nil )
end

task :environment do
  ActiveRecord::Base.establish_connection(YAML::load(File.open('database.yml')))
end

在environment任务中读取database.yml配置文件,在migrate任务中,根据VERSION定义数据库。

剩下的就是定义好model文件了:

require 'rubygems'
require 'active_record'
require 'yaml'

dbconfig = YAML::load(File.open('database.yml'))
ActiveRecord::Base.establish_connection(dbconfig)

class RedBlueBall < ActiveRecord::Base
  has_many :red_balls
  has_one :blue_ball

  validates_uniqueness_of :number
end

最后你只需要在命令行输入rake即可运行migration,RedBlueBall就可以像在Rails中一样来使用了。

可以看到,Rails的约定帮我们做了很多事情,定义好了Rakefile,所有的model都会自动require相应的gems,读取database.yml配置文件。

Posted in  ruby activerecord rails


买彩票

上个月小笨蛋说要去买彩票,不过因为忙,也因为不懂规则,所以一直没买。

正好趁着端午有空,写了个程序,把历次双色球的中奖号码都记录下来,然后统计一下选号,今天买了2注,一注是历次出现概率最高的数字,一注是历次出现概率最低的数字。

之所以这样买,第一注嘛,按正常人思维都会这样买吧,第二注嘛,因为理论上所有的号码出现的概率应该是一样的,所以之前出现次数越少,之后出现的概率应该更高才对。

aaron之前说过,世上有三种谎言,一是好的谎言,二是坏的谎言,三是概率。想想蛮有道理的,不过作为理性的程序员,既然没有更好的算法,就只有按照概率的算法来选号。

Posted in  life


解决rubygems冲突的问题

在hostmonster上面手动编译了ruby和rubygems,不过今天在尝试rake gems:unpack的时候报错,说是调用了nil.version,一跟踪,原来是找不到gem的spec。不过明明是装好没问题的呀,奇怪了。于是去irb中尝试:

require 'rubygems'
=> true
require 'spec'
=> no such file to load -- spec

看来是rubygems路径的问题。可能是和hostmonster默认的rubygems路径冲突了,于是在.bashrc中显示指定GEM_PATH

export GEM_HOME=$HOME/ruby/gems
export GEM_PATH=$GEM_HOME:/usr/lib/ruby/gems/1.8

重新在irb中执行require 'spec'返回true,执行rake gems:unpack也OK了!

Posted in  ruby hostmonster


Fork me on GitHub