Archive for the ‘Ruby and Rails’ Category

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 上测试一下。

FCKEditor里面添加链接默认在新窗口打开

Monday, April 27th, 2009

1KG.org 上添加 FCKEditor 之后用户添加链接, 需要自己设置链接的打开方式, 但是对用户来说多了两三步操作, 不爽!

今天搜索了一下解决, 比想象的简单, 山寨方式搞定之:

  1. 打开 fckeditor\editor\dialog\fck_link.html
  2. 查找 id=”cmbTarget” 的 select 标签, 添加 selected=”selected” 属性
  3. 查找 id=”txtTargetFrame” 的 input 标签, 添加 value=”_blank” 属性

完成!

gem Browser

Friday, April 3rd, 2009

看 gem 文档除了 gem_server 发现了一个 bdoc, 还不错.

安装简单:

git clone github.com/manalang/bdoc.git
gem build bdoc.gemspec
gem install bdoc-0.2.0.gem

完成

使用只要在 term 里执行 bdoc 即可

validates_uniqueness_of 对中文验证无效

Thursday, March 19th, 2009

用 restful_authutication 遇到一个奇怪的问题, validates_uniqueness_of 对中文验证无效, 搜索一下发现有人报告过, 看上去已经解决了, 但是在 2.2.2 中仍然不行, patch 中修改的是

--- a/activerecord/lib/active_record/validations.rb
+++ b/activerecord/lib/active_record/validations.rb
@@ -664,7 +664,7 @@ module ActiveRecord
             condition_params = [value]
           else
             condition_sql = "LOWER(#{sql_attribute}) #{comparison_operator}"
-            condition_params = [value.downcase]
+            condition_params = [value.chars.downcase]
           end

但是 2.2.2 中看到的代码是 condition_params = [value.mb_chars.downcase]

没仔细研究失效的原因, 自己加了点代码解决:

validates_uniqueness_of   :login,    :if => Proc.new {|user| !user.login.is_utf8?}

当 login 是 utf-8 的时候直接跳过这步, 接下来自己再验证一下:

def validate
  user = User.find(:first, :conditions => ["login=?", self.login])
  if !user || user != self
    self.errors.add :login, "用户名已被注册"
  end
end

问题解决了, 但不一定是最好的办法, 有人也遇到同样的问题么?