【原创】改造rails使支持gb2312编码

本文提供了一种在 Rails 1.2.3 版本下实现 gb2312/gbk 与 utf8 编码共存的方法。通过修改控制器、视图、模型等多个层面的代码,确保了应用可以正确处理不同编码的中文字符。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

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

 

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

代码:


ContractedBlock.gif ExpandedBlockStart.gif Code
before_filter :encode_request_params

# 如果参数采用的是UTF8编码,则对参数进行GBK转码
def 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操作也是一个空操作,没有做任何改变。

代码:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
class 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,在每次赋值和取值的时候自动进行编码转换。至于为什么这样做,请仔细研读相关代码,我也是费了好大劲才找到方案的。

代码:

 

ContractedBlock.gif ExpandedBlockStart.gif Code
class 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上的方法。

代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
class 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加载。

 

大功告成!

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值