本文章所处环境为rails1.2.3,mysql 5,数据库编码使用utf8。

 

首先第一步请参照《【转载】Rails使用gb2312/gbk与utf8共存的解决方案

 

第二步,修改web前端,在action执行前对params中的中文字符进行gbk转码。主要工作在app/controller/application.rb中。

代码:


 encode_request_params
  if request.env["HTTP_CONTENT_TYPE"]=~/UTF-8/
    encode_hash(params)
  end
end

# 遍历params,将所有的字符串参数进行GBK转码
def encode_hash(hash)
  hash.each do 
|k,v|
    logger.info v.
class
    
if v.instance_of? HashWithIndifferentAccess
      encode_hash(v)
    elsif v.instance_of? String
      hash[k] 
= gbk(v)
    end
  end

  hash
end


第三步,修改ActionView::Helpers::InstanceTag,改变to_input_field_tag方法输出input的默认行为。这里很奇怪的是,为什么使用value_before_type_cast方法呢?完全可以使用value方法啊。看过ActiveRecord中的实现,对string和text类型,type_cast操作也是一个空操作,没有做任何改变。

代码:

 

 ActionView::Helpers::InstanceTag

  alias :original_to_input_field_tag :to_input_field_tag

  def to_input_field_tag(field_type, options = {})
    options[
"value"||= value(object) unless field_type == "file"
    original_to_input_field_tag(field_type, options)
  end

end

 

 第四步,修改ActiveRecord::Base和ActiveRecord::ConnectionAdapters::Column,在每次赋值和取值的时候自动进行编码转换。至于为什么这样做,请仔细研读相关代码,我也是费了好大劲才找到方案的。

代码:

 

 ActiveRecord::Base

  alias :original_write_attribute :write_attribute

private
  def write_attribute(attr_name, value)
    
#logger.info "write_attribute(#{attr_name}, #{value})"
    if text_column?(attr_name)
      value 
= utf8(value)
      
#logger.info "change value to #{value}"
    end
    original_write_attribute(attr_name, value)
  end
      
public
  
def text_column?(attr_name)
    col 
= column_for_attribute(attr_name)
    
if (!col.nil? && (col.type==:string || col.type==:text))
      true
    
else
      false
    end 
  end
  
end 

class ActiveRecord::ConnectionAdapters::Column
      
  alias :original_type_cast_code :type_cast_code
    
  
def type_cast_code(var_name)
    case type
      when :string    then 
"gbk(#{var_name})"
      when :text      then 
"gbk(#{var_name})"
      
else original_type_cast_code(var_name)
    end
  end

end

 

 第五步,修改object基类,增加gbk和utf8两个方法。 可以看到,在第四步中的使用了gbk,utf8等方法,这些都是增加到object上的方法。

代码:

 Object
    def gbk(str)
    
if str.blank?
      
''
    elsif ! Kconv.isutf8(str)
      str
    
else
      Iconv.conv(
'gb2312//IGNORE','utf-8//IGNORE',str)
    end
  end

  
def unicode_to_gbk(str)
    Iconv.conv(
'gb2312//IGNORE','unicode//IGNORE',str)
  end

  
# 将 GB2312 编码的字符串转换为 UTF-8 编码的字符串
  def utf8(str)
    
if str.blank?
      
''
      
# isutf8并不能很好来判定编码。比如“状态”这个词就会被误认为utf8
      #elsif Kconv.isutf8(str)
      #str
    else
      Iconv.conv(
'utf-8//IGNORE','gb2312//IGNORE',str)
    end
  end
end

 

 这些代码放在哪里,怎么才能生效呢?我的做法是,编写一个或多个rb,放在lib中,然后在config/enviroments.rb文件的末尾使用require加载。

 

大功告成!

 

相关文章:

  • 2022-12-23
  • 2021-08-21
  • 2021-08-17
  • 2022-03-05
  • 2021-10-13
  • 2022-02-02
猜你喜欢
  • 2022-01-31
  • 2021-08-24
  • 2021-12-10
  • 2021-05-16
  • 2022-12-23
  • 2021-08-31
  • 2021-12-10
相关资源
相似解决方案