#coding: utf-8 =begin 字段映射,业务字段-数据库字段对应 =end require 'fileutils' module FieldMapping def self.included(base) base.extend(ClassMethods) end def as_json(options={}) self.class.buz_hashize(self.attributes) end def update_from_buz(params={}) update_attributes(self.class.db_hashize(params)) end module ClassMethods #Fix a bug on 20111117 by shang def __model_clazz_name self.name.underscore end def model_key "#{__model_clazz_name}_fields" end def mapping GlobalConst.send(model_key) end def get_map_value(k, value) #raise "Not implemented!" #提供默认处理 #TODO 根据数据类型做些更好的转换 case k when :created_at, :updated_at value.try(:to_s, :db) else value end end def dump_new(force=true) if defined?(Rails) file = "#{Rails.root}/data/#{model_key}_#{Time.now.to_i}.yml" path = File.dirname(file) FileUtils.mkpath(path) unless File.directory?(path) existed = File.exists?(file) if existed puts "Warning: #{file} has existed! check it! Default override it!" end if !existed || force File.open(file, 'w+') do |f| f.puts YAML.dump(buz_hashize) end end end end #辅助方法 def new_from_buz(params = {}) new(db_hashize(params)) end def create_from_buz(params = {}) create(db_hashize(params)) end #生成field mapping,dump到指定的yaml文件中 def dump_mapping(attr_prefix = nil, force = true) if defined?(Rails) file = "#{Rails.root}/#{GlobalConst::APP_CODE_HASHES}fields/#{model_key}_#{Time.now.to_i}.yml" path = File.dirname(file) FileUtils.mkpath(path) unless File.directory?(path) existed = File.exists?(file) if existed puts "Warning: #{file} has existed! check it! Default override it!" end if !existed || force #获取数据库字段列表,屏蔽掉自动维护的created_at/updated_at,也可在生成的文件中配上 keys = new.attributes.symbolize_keys.keys.delete_if{|k| k =~ /^created_at|updated_at$/} h = keys.inject({}) do |r, k| #移除掉表前缀 rm_prefix = attr_prefix.nil? ? "#{__model_clazz_name}_" : attr_prefix new_key = k.to_s.sub(rm_prefix, '').to_sym r[new_key] = k r end FileUtils.rm_f(file) if existed File.open(file, 'w+') do |f| f.puts YAML.dump(model_key.to_sym=>h) end puts "==>gen new file #{file} ..." end end end #TODO def dump_field_map(force=true) puts "==Warning: please use dump_mapping instead, this will be removed..." dump_mapping(nil, true) end #业务层到数据层字段参数转换并做一定值处理 def db_hashize(params = {}) new_params = params.symbolize_keys common_keys = new_params.keys & mapping.keys common_keys.inject({}) do |result, key| result[mapping[key]] = get_map_value(key, new_params[key]) result end end #将数据层表示转成业务层表示 def buz_hashize(attrs = {}) #return {} if attrs.blank? #获取默认初始值 attrs = new.attributes if attrs.blank? new_attrs = attrs.symbolize_keys invert_maps = mapping.invert_data common_db_attrs = new_attrs.keys & invert_maps.keys common_db_attrs.inject({}) do |result, attr| buz_field = invert_maps[attr] result[buz_field] = get_map_value(buz_field, new_attrs[attr]) result end end end end