Showing posts with label rails. Show all posts
Showing posts with label rails. Show all posts

Monday, October 27, 2008

从Mephisto迁移到wordpress

原先blog用的mephisto,最近出现spam,索性关了comments,决定换回wordpress。今天抽个空闲,终于是转换了过来。

幸好Caleb Jaffa因为有同样的需求写了转换脚本

下载 wordpress 2.5.1,安装,运行,运行转换脚本,更新 wordpress 2.6.1,设定 permalink,原先的 feed archinves url 转换设定,磕磕碰碰遇到点小问题,半个小时之内还是搞定了。

买了 linode 的 VPS,用debian的image,安装mysql编译apache、php,一切顺利,总算可以对备案说 fu**k you了,:-p

Update:

Wednesday, June 18, 2008

在 lenny 上降级 ruby 解决 rails 2.0 不兼容 ruby 1.8.7 问题

production 系统用的是 lenny,前两天 upgrade 了一把,ruby 1.8.7,当时并未在意,直到今天 cap deploy 后,部分页面出错,检查了一把,代码没问题,看来应该是升级到 1.8.7 后出现的问题了。google 了一番,的确如此:

Debian bug#484351 中有人指出最近的 rails 2.1.0 修正了1.8.7 兼容问题,事实上官方下载页面明确指出了 rails 还不兼容 ruby 1.8.7,看来升级到 rails 2.1.0 并不能解决这个问题,只能降级 ruby 了。

好在 debian 中还有 ruby 1.8.6 的 source,自己动手 build 吧。

wget http://debian.cn99.com/debian/pool/main/r/ruby1.8/ruby1.8_1.8.6.114-2.diff.gz
wget http://debian.cn99.com/debian/pool/main/r/ruby1.8/ruby1.8_1.8.6.114.orig.tar.gz
tar zxvf ruby1.8_1.8.6.114.orig.tar.gz
gzip -d ruby1.8_1.8.6.114-2.diff.gz
cd ruby-1.8.6-p114
aptitude build-dep ruby
dpkg-buildpackage
cd ../
dpkg -i --force-all irb1.8_1.8.6.114-2_all.deb libopenssl-ruby1.8_1.8.6.114-2_amd64.deb libreadline-ruby1.8_1.8.6.114-2_amd64.deb libruby1.8_1.8.6.114-2_amd64.deb rdoc1.8_1.8.6.114-2_all.deb ruby1.8_1.8.6.114-2_amd64.deb ruby1.8-dev_1.8.6.114-2_amd64.deb ruby1.8-elisp_1.8.6.114-2_all.deb
降级到 ruby 1.8.6 后 mongrel 的依赖出现问题,同样需要 rebuild,好在这个时候重启 mongrel,问题已经解决了。 如果希望能够解决 mongrel 的依赖问题的话:
apt-get source libsetup-ruby
cd libsetup-ruby-3.4.1
dpkg-buildpackage
cd ../
dpkg -i libsetup-ruby1.8_3.4.1-4_all.deb
apt-get source ruby-pkg-tools
cd ruby-pkg-tools-0.13
dpkg-buildpackage
cd ../
dpkg -i  ruby-pkg-tools_0.13_all.deb
rebuild 需要满足 rdoc 包,rebuild rdoc 的话需要一堆的依赖,我偷懒了一把
ln -s /usr/bin/rdoc1.8 /usr/bin/rdoc
apt-get source mongrel
cd mongrel-1.1.5
dpkg-buildpackage
cd ../
dpkg -i  mongrel_1.1.5-2_amd64.deb
依赖解决后,需要 hold ruby 1.8.6 的包,防止 upgrade 的时候再次升级。
aptitude hold irb1.8 libopenssl-ruby1.8 libreadline-ruby1.8 libruby1.8 mongrel rdoc1.8 ruby1.8 ruby1.8-dev ruby1.8-elisp

Friday, June 13, 2008

rails tips: 动态载入 JavaScript 文件

rails 中一般的 JavaScript 机制在 layout 中用 javascript_include_tag 载入需要的脚本文件,对默认整站需要的脚本文件来说很方便,但实际情况是我们经常需要在某些页面动态载入需要的脚本文件来避免调用过多外部文件影响页面载入速度。rails 提供了 javascript_include_tag 和 register_javascript_include_default 都可以用来载入脚本文件,register_javascript_include_default 每次调用都会增加一项到 @@javascript_default_sources,会导致重复载入同一文件,文档中已说明 register_javascript_include_default 用来在 plugin 载入时更改默认载入脚本。所以正确的方法应该是 javascript_include_tag。

javascript_include_tag 后调用直接输出 html script 标记,意味着脚本在 body 解释时才会载入,而我希望的结果是放置到 head 标记内。第一反应是搜索文档看是否存在 response 动态增加载入 javascript 的方法,rails 并没有提供此方法。正觉得无奈的时候忽然想到 rails layout 中用到了 yield,这里不是可以用 yield 达到同样的结果吗。 layouts/application.thml.erb

<%= javascript_include_tag :defaults %>
<%= yield :javascript_files %>
在需要载入的模板文件中:
<% content_for :javascript_files do -%>
<%= javascript_include_tag("some_file_to_load_on_demand.js") -%>
<% end -%>

Tuesday, June 03, 2008

用 monit 自动启动 mongrel 和 backgroundrb 服务

Capistrano 部署 Rails 项目速记中解决了代码更新时候 mongrel/backgroundrb 重启等问题,还需要保证系统重启时服务能够自动启动。

mongrel cluster 自带了 mongrel-cluster 启动管理脚本,Debian 系统的话链接 mongrel_cluster.yml 到 /etc/mongrel-cluster/sites-enabled/ 目录,系统启动的时候 /etc/init.d/mongrel-cluster 会自动启动 mongrel daemon,然而 backgroundrb 的启动问题还是没有解决,需要手工写启动脚本,google 了一番之后,找到 Monit 这个小工具:

# 摘自 monit deb package description.
A utility for monitoring and managing daemons or similar programs
 monit is a utility for monitoring and managing daemons or similar
 programs running on a Unix system. It will start specified programs
 if they are not running and restart programs not responding.
 .
 monit supports:
  * Daemon mode - poll programs at a specified interval
  * Monitoring modes - active, passive or manual
  * Start, stop and restart of programs
是否可以用 Monit 来启动 mongrel 和 backgroundrb 呢,答案是肯定的,事实上这也应该是推荐方式。

安装 Monit

$sudo aptitude install monit
修改 /etc/default/monit 配置:
startup=1
CHECK_INTERVALS=30 # monit 监控检测时间价格,推荐设置成 30 秒
配置 monit
$sudo grep '^[^#]' /etc/monit/monitrc
set daemon  30
set logfile syslog facility log_daemon
set httpd port 2812 and
     use address localhost  # only accept connection from localhost
     allow localhost        # allow localhost to connect to the server and
include /etc/monit/conf.d/*
$sudo mkdir /etc/monit/conf.d

配置 Daemon 项

$cat 001_neo_mongrel.conf
check process mongrel_neo_8000
  with pidfile /project/code/path/shared/pids/mongrel.8000.pid
  start program = "/usr/bin/mongrel_rails cluster::start -C /project/code/path/current/config/mongrel_cluster.yml --clean --only 8000"
  stop program = "/usr/bin/mongrel_rails cluster::stop -C /project/code/path/current/config/mongrel_cluster.yml --only 8000"
  if totalmem is greater than 110.0 MB for 4 cycles then restart
  if cpu is greater than 80% for 4 cycles then restart
  if 20 restarts within 20 cycles then timeout
  group neo

check process mongrel_neo_8001
  with pidfile /project/code/path/shared/pids/mongrel.8001.pid
  start program = "/usr/bin/mongrel_rails cluster::start -C /project/code/path/current/config/mongrel_cluster.yml --clean --only 8001"
  stop program = "/usr/bin/mongrel_rails cluster::stop -C /project/code/path/current/config/mongrel_cluster.yml --only 8001"
  if totalmem is greater than 110.0 MB for 4 cycles then restart
  if cpu is greater than 80% for 4 cycles then restart
  if 20 restarts within 20 cycles then timeout
  group neo

check process mongrel_neo_8002
  with pidfile /project/code/path/shared/pids/mongrel.8002.pid
  start program = "/usr/bin/mongrel_rails cluster::start -C /project/code/path/current/config/mongrel_cluster.yml --clean --only 8002"
  stop program = "/usr/bin/mongrel_rails cluster::stop -C /project/code/path/current/config/mongrel_cluster.yml --only 8002"
  if totalmem is greater than 110.0 MB for 4 cycles then restart
  if cpu is greater than 80% for 4 cycles then restart
  if 20 restarts within 20 cycles then timeout
  group neo
$ cat 003_neo_brb.conf
check process brb_imigu_11006
  with pidfile /project/code/path/shared/pids/backgroundrb_11006.pid
  start program = "/bin/su -c 'cd  /project/code/pathcurrent && RAILS_ENV=production nohup ./script/backgroundrb start > /dev/null 2>&1' josh"
  stop program = "/bin/su -c 'cd /home/josh/www/imigu/current && RAILS_ENV=production && ./script/backgroundrb stop' josh"
  group neo

启动 Monit 和监测

$sudo /etc/init.d/monit restart
$sudo monit -c /etc/monit/monitrc status #查看系统状态
通过 monit 已经可以自动启动管理 mongrel 和 backgroundrb,那么谁来保证 monit 的稳定运行呢,答案是 linux 系统 init。 编辑 /etc/inittab 加入:
# Run monit in standard run-levels
mo:2345:respawn:/usr/sbin/monit -Ic /etc/monit/monitrc
mo:06:wait:/usr/sbin/monit -Ic /etc/monit/monitrc stop all
重启 monit
$sudo /etc/init.d/monit stop
$sudo telinit q

参考:

  • Monit man page
  • 2008, Ezra Zygmuntowicz and Bruce Tate, Deploying Rails Applications

Friday, May 30, 2008

Capistrano 部署 Rails 项目速记

项目快上线了,以前一直采用传统的方式进行部署,从最早的 FTP 到后来的 SVN+SSH,既然现在是 Rails 项目,当然试一把 Capistrano。

安装

使用 Capistrano 进行部署只需要在本地机器安装 Capistrano 即可,Capistrano 通过 SSH 与服务器端进行交互。

gem install -y capistrano
当前最新版本是 2.3.0。

配置

Ubuntu 8.0.4 上 gem 包相关的 bin 目录并不在系统路径中,需要手工加入gem bin 路径:

$cat "export PATH=$PATH:/var/lib/gems/1.8/bin" >> .~/bashrc
$source ~/.bashrc

生成基础配置文件:

$cd RAILS_APP_DIR
$capify .

调整 config/deploy.rb 中相关配置项,并加入一行:

set :runner, "ACCOUNT_NAME"
用你服务器端的登录用户名取代 ACCOUNT_NAME,如果不设置此行,默认用户为 app,会导致设置失败。

初始化服务器端目录:

$cap deploy:setup
Capistrano > 2.3.0 开始默认启用 sudo,所以,服务器需要支持 sudo 支持,将 ACOUNT_NAME 加入到 sudo group, 并确认 /etc/sudoers 中设置:
# Uncomment to allow members of group sudo to not need a password
 %sudo ALL= ( ALL ) NOPASSWD: ALL

SSH 自动登录:

$ssh-keygen -t dsa
$chmod 700 ~/.ssh
$scp ~/.ssh/id_dsa.pub USER_NAME@REMOTE_SERVER
在服务器:
$cat id_dsa.pub >> ~/.ssh/authorized_keys
$rm -f id_dsa.pub

运行设定和依赖检查:

set :deploy_via, :remote_cache
set :runner, "josh"
depend :remote, :gem, "chronic", ">= 0.2.3"
depend :remote, :gem, "packet", ">= 0.1.5"
depend :remote, :command, "gnuplot"
depend :remote, :command, "svn"
depend :remote, :command, "mongrel_cluster_ctl" # make sure /usr/sbin in the $PATH
需要注意的是 debian 中的 mongrel_cluster_ctl 脚本在 /usr/sbin 下,而通过 ssh 获得的系统 $PATH 并没有包含 /usr/sbin 目录,需要修改 .ssh/environment 和 ssh 的相关配置加入 /usr/sbin 目录。 Mongrel && backgroundrb 启动配置
rails_env = "production"
set :mongrel_environment, "production"
set :mongrel_conf, "#{deploy_to}/current/config/mongrel_cluster.yml"

namespace :deploy do
  
  desc "Restart the Mongrel cluster and backgroundrb"
  task :restart, :roles => :app do
    stop
    start
  end
  desc "Start the mongrel cluster and backgroundrb"
  task :start, :roles => :app do
    mongrel.cluster.start
    start_backgroundrb
  end
  desc "Stop the mongrel cluster and backgroundrb"
  task :stop, :roles => :app do
    mongrel.cluster.stop
    stop_backgroundrb
  end

  desc "Start the backgroundrb server"
  task :start_backgroundrb , :roles => :app do
    begin
      puts "starting brb in folder #{current_path}"
      run "cd #{current_path} && RAILS_ENV=#{rails_env} nohup ./script/backgroundrb start > /dev/null 2>&1"
    rescue RuntimeError => e
      puts e
      puts "Problems starting backgroundrb – running already?"
    end
  end
  desc "Stop the backgroundrb server"
  task :stop_backgroundrb , :roles => :app do
    begin
      puts "stopping brb in folder #{current_path}"
      run "cd #{current_path} && ./script/backgroundrb stop"
    rescue RuntimeError => e
      puts e
      puts "Backgroundrb appears to be down already."
    end
  end
end

需要注意的是 Capistrano 每次 deploy 的时候会重新检出代码,用户上传文件需要单独做 link:
namespace :assets do
  task :symlink, :roles => :app do
    run <<-CMD
rm -rf #{release_path}/assets &&
ln -nfs #{shared_path}/assets #{release_path}/assets
CMD
  end
  after "deploy:update_code" , "assets:symlink"
  
  task :create_dirs, :roles => :app do
    %w(assets).each do |name|
      run "mkdir -p #{shared_path}/#{name}"
    end
  end
  after "deploy:setup", "assets:create_dirs"
end

参考文档:

Friday, March 14, 2008

ruby block 局部变量

今天遇到的问题,在 block 中定义的变量为局部变量,无法在 block 外以及下一次迭代中使用,必须定义在 block 开始之前。

Wednesday, March 12, 2008

flymake 运行 rails scripts/runner 脚本文件

写了几个脚本,用到了 rails script/runner: {{{ #!/usr/bin/env /project_path/script/runner }}} 结果发现 emacs flymake mode 执行了这个文件,而不是默认的 c (check) 语法检查。 去官方看了一下 bug,原来已经有人报告过了, 修改为 {{{ #!/usr/bin/ruby /project_path/script/runner }}} 问题修正。反正系统只会是 linux,没有这烦人的问题就成。

Tuesday, February 26, 2008

rails tips

随手记录开发中遇到的小问题,备忘。

install plugins

undefined method `paginate' for
安装 plugin 后,需要重启 web server。

radio for boolean field

<%= f.radio_button :direction, "true" %>
<%= f.radio_button :direction, "false" %>

selected for options key value pairs array

it didn't well documented, here is the example:
	  <%= select_tag(
	      :sector_id,
	      options_for_select(
	        [["--请选择--", ""]].concat(Sector.get_for_list.collect {|o| [ o.name, o.id ] }), 
	        [@sector.id, @sector.name])
	      )
	  %>

Friday, November 30, 2007

从头搭建 rails on emacs 开发环境

最近准备用 rails 做新的产品,没有熟悉的 ruby 开发环境,索性这次狠下心来,用 emacs。

安装设定 emacs

Ubuntu gusty 下安装 emacs

sudo aptitude install emacs

安装 ruby mode

sudo aptitude install ruby-elisp

安装 emacs-rails

mkdir ~/.emacs.d/
cd  ~/.emacs.d/
svn co svn://rubyforge.org/var/svn/emacs-rails/trunk rails

下载需要的库文件

cd  ~/.emacs.d/
mkdir libs
cd libs
wget http://www.kazmier.com/computer/snippet.el
wget -O find-recursive.el http://www.webweavertech.com/ovidiu/emacs/find-recursive.txt
snapshot设定代码到 ~/.emacs
; rails mode
(setq load-path (cons "~/.emacs.d/rails" load-path))
(setq load-path (cons "~/.emacs.d/libs" load-path))
(require 'rails)
(require 'find-recursive)
(require 'snippet)

几个有用的 mode

sudo aptitude install ecb
sudo aptitude install emacs-goodies-el

设定 emacs 颜色方案 ubuntu 的 emacs-goodies-el 包已经提供了 60 多种颜色方案,不过都不是很能让我满意,-__- 这里用了 hober2 的颜色方案。

cd ~/.emacs.d/
mkdir color-scheme
cd color-scheme
wget http://edward.oconnor.cx/elisp/color-theme-hober2.el
增加设定代码到 ~/.emacs
; theme
(setq load-path (cons "~/.emacs.d/color-themes" load-path))
(require 'color-theme-hober2)
(color-theme-hober2)

OK, rails on emacs 环境已经完成,进入 rails project 目录,打开一个文件试试,rails mode 已经默认加载了。唯一不还不满意的是字体,看了一把 emacs 文档 Defining fontset 节,发现 emacs 2.2 包括之前的版本字体设定通过 ~/.Xresource 文件,并不支持 Xft freetype,好在 SVN 的 emacs 已经支持 unicode 和 Xft freetype,并 有人为 ubuntu 打了包。 添加下面的设定到 /etc/apt/source.list

# emacs snapshot
deb http://ppa.launchpad.net/avassalotti/ubuntu gutsy main
sudo apt-get update
sudo aptitude install emacs-snapshot-gtk
注意,PPA 仓库中的 deb 包密钥并未包含在 ubutnu keyring 中,安装的时候需要手工确认。 增加设定代码到 ~/.emacs
(set-default-font "DejaVu Sans Mono-10")
(set-fontset-font (frame-parameter nil 'font)
         'unicode
         '("DejaVu Sans Mono-10" . "unicode-bmp"))
(set-fontset-font (frame-parameter nil 'font)
             'han
         '("SimSun" . "unicode-bmp"))

参考资料: