Archive for the ‘Ruby and Rails’ Category

Rails3 中 ActiveRecord API 的变化

Friday, May 14th, 2010

Rails3 中 ActiveRecord API 的变化从书写上看已经是翻天覆地了,过去查询条件都是用 hash 的方式写到 finder 里面,现在全部转化成了 method 调用的串联。

比如过去的:

Post.find(:all, :condition => “user_id = 1″, :order => “id desc”, :limit => 10, :include => :replies)

在 rails3 中要写成:

Post.where(”user_id=1″).order(”id desc”).limit(10).includes(:replies)

看上去好似 named_scope

完全正确,rails3 针对 AR API 改写的目标就是:Everything is named_scope.

rails3 中对 ActiveRecord 的 API 改写成了完全符合 ActiveModel API 的样子。而 ActiveModel 相当于 ORM 这一层的接口,ActiveRecord 是一种具体实现,当其他的 ORM(如 DataMapper)都复合 ActiveModel 这样的接口时,针对 model 部分的插件(如 will_paginate)就可以通用了。

自动服务器文件备份到S3

Thursday, May 13th, 2010

服务器上有很多用户上传的文件,需要定时备份。从安全角度讲一定要做到物理分离,如果有两台服务器在同一个内网,自然 rsync 就搞定了。

可怜资源有限,只有一个VPS,硬盘也紧张。于是乎想备份到 S3,云存储,可靠性好。而且用于备份,主要是存储产生的费用,流量费用很低,总体下来不会太贵。

用镜像的方式备份到 S3 上,可以用 CNAME 的方式直接将 static.yourdomain.com 指到 S3 上,替换本地存储系统,这也是一大好处。

找到一个 s3sync,ruby 写的,本地测试OK,即日放到服务器上检验一下。

用法很简单,下载后将 s3config.yml.example 改为 s3config.yml,并在里面填上你的 aws_access_key_id 和 aws_secret_access_key。如果上传的内容不是非常敏感,可以将 ssl_cert 那行去掉。

默认的 s3config.yml 比较让人纠结,竟然不在当前路径下查找,我改了一下 s3config.rb

confpath = ["#{ENV['S3CONF']}”, “#{ENV['HOME']}/.s3conf”, “/etc/s3conf”]

改为

confpath = [".", "#{ENV['S3CONF']}”, “#{ENV['HOME']}/.s3conf”, “/etc/s3conf”]

小问题:s3sync 工作的时候看不到进度,不好 debug。不过在生产服务器上用 cron 跑的话进度也确实没用。

另外还有一个方案,有兴趣的同学可以试试

Missing the Rails 2.3.4 gem

Tuesday, March 30th, 2010

本地的开发环境突然报错

Missing the Rails 2.3.4 gem. Please `gem install -v=2.3.4 rails`,
update your RAILS_GEM_VERSION setting in config/environment.rb for
the Rails version you do have installed, or comment out RAILS_GEM_VERSION
to use the latest version installed.

同事说从 passenger 2.2.11 退回到 2.2.8 就可以了,退回去问题依旧。

也 Google 到类似问题1问题2

我本地的情况是:
Ruby 1.8.6
Passenger 2.2.11

有遇到类似情况,有解决办法的朋友请帮忙,不胜感激!

Update: 问题出在我装了 rack 1.1.0,一定要退回到 rack 1.0.1 才行,现在问题已解决

use current_user in Model

Friday, July 10th, 2009

我所有的项目几乎都用 restful_authentication 做了用户管理这部分,应用中经常要在 model 中调用 current_user,而这个是 session 相关的信息,在 Model 中不应直接读到,Google 到一个比较不错的办法,是 Beast 的作者提供的。

首先在 User Model 中加入一个类变量:

class User < ActiveRecord::Base
  cattr_accessor :current_user
  ...
end

之后在 ApplicationController 中用 before_filter 给刚才的类变量赋值:

class ApplicationController < ActionController::Base
  include AuthenticatedSystem
  before_filter { |c| User.current_user = c.current_user }
end

看似完美,测试报错,说 current_user 方法是 protected,不能调用。看看 lib/authenticated_system.rb,果然 current_user 方法是 protected,为了不破坏 restful_authenticated plugin 的结构,对 controller 里面的方法做个修改:

class ApplicationController < ActionController::Base
  include AuthenticatedSystem
  before_filter :set_current_user

  protected
  def set_current_user
    User.current_user = self.current_user
  end
end

–EOF–

acts_as_taggable_on_steroids 与 will_paginate 的整合

Friday, May 8th, 2009

使用 acts_as_taggable_on_steroids 之后经常找有某个 tag 的 item:

@items = Item.find_tagged_with(”tag”)

找到很多需要分页显示,于是顺利成章的在后面加上:

@items = Item.find_tagged_with(”tag”).paginate :page => paramsp[:page] || 1, :per_page => 20

发现无效!原因是 find_tagged_with 返回的是 Array,will_paginate 强大的分页功能瞬时歇菜。

于是乎整合一下两者:

module ActiveRecord
module Acts #:nodoc:
module Taggable #:nodoc:
module SingletonMethods

def count_tagged_with(*args)
options = find_options_for_find_tagged_with(*args)
options.blank? ? 0 : count(”#{table_name}.id”, options.merge(:select => nil, :distinct => true))
end

def _paginate_tagged_with(tags, options = {})
page, per_page = wp_parse_options!(options)
offset = (page.to_i - 1) * per_page
count = count_tagged_with(tags, options)
options.merge!(:offset => offset, :limit => per_page.to_i)
items = find_tagged_with(tags, options)
returning WillPaginate::Collection.new(page, per_page, count) do |p|
p.replace items
end
end

end
end
end
end

之后调用

@items = Item.paginate_tagged_with tag, :page => paramsp[:page] || 1, :per_page => 20

restful_authentication plugin 在IE上弹出登录窗口的问题

Sunday, May 3rd, 2009

我在做过的 Rails 项目中一直使用 restful_authentication plugin,前一段有个别人向我反应用IE访问 1KG.org,点击一些需要登录后才能用的功能时,不能跳转到登录界面,而是弹出一个窗口提示输入 username & password,起初我在 VMWare 虚拟的XP中拿IE6测了一下,没有这样的情况,又拿周围一两台机器试了试,也没发现问题,于是想当然的以为是那哥们的机器中了流氓插件,导致IE不正常。

这两天配合易助网的 Boyu 同学在 1KG.org 上添加 Google AdWords Tracking code 时,他说自己身边的 IE 都有真个问题,我才意识到问题可能具有普遍性!

老婆电脑上有IE7,测试一下,也有弹窗的问题!

Google 一番,发现问题是 IE 发送不太合格的 Accepts,导致 rails 不能正确识别请求的类型造成的弹窗。

整个问题在一个 ticket 中讲的很详细

我用的解决办法是将 format.any 改成 format.any(:js, :xml):

def access_denied
    respond_to do |format|
      format.html do
        store_location
        redirect_to new_session_path
      end
      format.any(:js, :xml) do
        request_http_basic_authentication 'Web Password'
      end
    end
  end

欢迎各位用 IE 到 1KG.org 上测试一下。