浏览 2564 次
锁定老帖子 主题:应用Rails+Ext开发企业级权限平台
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
|
|
---|---|
作者 | 正文 |
发表时间:2008-12-05
最后修改:2008-12-08
一般说来做企业级权限平台都是java的天下,我也不得不认同java这方面的能力。本文介绍的Ext + Rails 开发的企业级权限平台也是在原先用java实现的一套改写而成,保证了基本功能的一致性,UI界面的一致性。这样就充分说明了富客户端框架(或者说RIA)的应用广泛性,能够和多种服务器端语言组合开发应用系统平台。 该平台是基于角色的权限管理后台.集中了一般企业应用所必需包含的必须模块,包括用户维护、模块维护、角色管理、权限管理、数据字典以及统一的页面风格等.由于该开发平台的存在,大大提高了开发人员的开发效率,特别是单表操作,仅仅只需要在范例模块的基础之上进行少量修改即可达到目的.平台架构设计本着追求层次间的低耦合,层次明显分开,TDD开发模式原则进行. 下面有实现的图样~~ (貌似有蛮多 呵呵) 整个开发中没什么新颖的东西 就如同java一般从数据库中去数字组装成符合要求的json字符串输出渲染页面让Ext来显示数据和如何组织项目的结构。 数据库表结构db/schema.rb # This file is auto-generated from the current state of the database. Instead of editing this file, # please use the migrations feature of ActiveRecord to incrementally modify your database, and # then regenerate this schema definition. # # Note that this schema.rb definition is the authoritative source for your database schema. If you need # to create the application database on another system, you should be using db:schema:load, not running # all the migrations from scratch. The latter is a flawed and unsustainable approach (the more migrations # you'll amass, the slower it'll run and the greater likelihood for issues). # # It's strongly recommended to check this file into your version control system. ActiveRecord::Schema.define(:version => 15) do create_table "catalogs", :force => true do |t| t.string "catalogname", :limit => 32 t.text "remark" t.integer "sortno" t.integer "parent_id" end create_table "dicts", :force => true do |t| t.string "key", :limit => 32, :default => "", :null => false t.string "value", :limit => 32 t.text "remark" t.integer "sortno" t.integer "catalog_id" end create_table "groups", :force => true do |t| t.string "createby", :limit => 32 t.string "name", :limit => 50, :default => "", :null => false t.text "remark" t.integer "sortno" t.integer "parent_id" end create_table "logs", :force => true do |t| t.text "log", :default => "", :null => false t.string "type", :limit => 32, :default => "", :null => false t.string "personloginname", :limit => 32 t.string "personname", :limit => 32 t.datetime "dt" end create_table "mods", :force => true do |t| t.text "link" t.string "type", :limit => 32 t.text "icon" end create_table "operations", :force => true do |t| t.string "sn", :limit => 32 t.string "icon", :limit => 32 t.string "tip", :limit => 32 t.boolean "show_text" t.boolean "admin_op" end create_table "people", :force => true do |t| t.string "login_name", :limit => 32 t.string "status", :limit => 32 t.string "hased_password" t.string "salt" t.string "name", :limit => 32 t.string "sex", :limit => 10 t.date "birthday" t.integer "sortno" t.text "config" t.string "creator", :limit => 32 t.date "createdt" end create_table "person2groups", :force => true do |t| t.integer "person_id" t.integer "group_id" t.boolean "isadmin" t.string "indicator", :limit => 32 end create_table "person2resources", :force => true do |t| t.integer "resource_id" t.integer "person_id" t.string "indicator", :limit => 32 end create_table "person2roles", :force => true do |t| t.string "indicator", :limit => 32 t.integer "person_id" t.integer "role_id" end create_table "resources", :force => true do |t| t.string "name", :limit => 32 t.integer "sortno" t.boolean "visiabled" t.text "remark" t.integer "parent_id" t.integer "ph_id" t.string "ph_type" end create_table "role2resources", :force => true do |t| t.integer "role_id" t.integer "resource_id" t.boolean "communicable" t.boolean "inherit" end create_table "roles", :force => true do |t| t.string "creator", :limit => 32 t.boolean "inheritable" t.string "name", :limit => 32 t.text "remark" t.integer "sortno" t.integer "parent_id" end create_table "sessions", :force => true do |t| t.string "session_id", :default => "", :null => false t.text "data" t.datetime "created_at" t.datetime "updated_at" end add_index "sessions", ["session_id"], :name => "index_sessions_on_session_id" add_index "sessions", ["updated_at"], :name => "index_sessions_on_updated_at" end 字典类型对象和字典对象一对多关系 model/catalog.rb class Catalog < ActiveRecord::Base acts_as_tree :order => "catalogname" has_many :dicts, :dependent => :destroy def expanded true end alias_attribute :text, :catalogname alias_attribute :catalogName, :catalogname alias_attribute :sortNo, :sortno #以下省略..... end 字典对象 model/dict class Dict < ActiveRecord::Base belongs_to :catalog alias_attribute :sortNo, :sortno end 组织对象,组织和人员是多对多关系. model/group.rb class Group < ActiveRecord::Base acts_as_tree :order => "name" has_many :person2groups, :dependent => :destroy has_many :people, :through => :person2groups alias_attribute :sortNo, :sortno alias_attribute :groupName, :name #以下省略..... end 日志对象 model/log.rb class Log < ActiveRecord::Base end 模块对象 模块对象和操作对象都属于资源对象 model/mod.rb class Mod < ActiveRecord::Base has_one :resource ,:as => :ph end 操作对象 模块对象和操作对象都属于资源对象 model/operation.rb class Operation < ActiveRecord::Base has_one :resource ,:as => :ph end 人员组织中间表model model/person2group.rb class Person2group < ActiveRecord::Base belongs_to :person belongs_to :group alias_attribute :admin, :isadmin #以下方法省略...... end 人员资源中间model model/person2resource.rb class Person2resource < ActiveRecord::Base belongs_to :person belongs_to :resource #以下方法省略...... end 人员角色中间model model/person2role.rb class Person2role < ActiveRecord::Base belongs_to :person belongs_to :role #以下方法省略...... end 人员对象 和组织 角色 资源等关联 model/person.rb require 'digest/sha1' class Person < ActiveRecord::Base has_many :person2groups, :dependent => :destroy has_many :groups, :through => :person2groups has_many :person2roles, :dependent => :destroy has_many :roles, :through => :person2roles has_many :person2resources, :dependent => :destroy has_many :resources, :through => :person2resources #以下方法省略...... end 资源对象 包含两种资源 操作和模块 model/resource.rb class Resource < ActiveRecord::Base #2008-6-12资源属性相关-多关联 belongs_to :ph, :polymorphic => true acts_as_tree :order => "name" has_many :person2resources, :dependent => :destroy has_many :people, :through => :person2resources has_many :role2resources, :dependent => :destroy has_many :roles, :through => :role2resources alias_attribute :sortNo, :sortno alias_attribute :text, :name alias_attribute :resName, :name alias_attribute :childRes, :children RES_TYPE_OPERATION = "Operation" RES_TYPE_MODULE = "Mod" #以下方法省略...... end 角色和资源的关联的中间model model/role2resource.rb class Role2resource < ActiveRecord::Base belongs_to :role belongs_to :resource alias_attribute :resourceId, :resource_id #以下方法省略...... end 角色对象 和人员 资源关联 model/role.rb class Role < ActiveRecord::Base acts_as_tree :order => "name" has_many :person2roles, :dependent => :destroy has_many :people ,:through => :person2roles has_many :role2resources, :dependent => :destroy has_many :resources, :through => :role2resources #下面是为了便于JSON化数据 alias_attribute :sortNo, :sortno alias_attribute :text, :name alias_attribute :rolename, :name #以下方法省略...... end 下面是自己改写过的生成json的插件jsonifier 用于把对象和对象集合转换成符合EXT接受的单个对象的json格式和多个树形结构的json格式 module Jsonifier #:nodoc: module JsonEncoding def to_json(options = {}) hashifier = JsonHashifier.new(self, options) hashifier.to_hash.to_json end class JsonHashifier #:nodoc: attr_reader :options def initialize(record, options = {}) @record, @options = record, options.dup filter_attributes end # Outputs AR record instance method as a hash that can be easily # encoded as JSON. def to_hash hash = {} hash.merge!(simple_attributes) hash.merge!(method_attributes) hash.merge!(astract_attributes) hash.merge!(checked_attributes) hash.merge!(association_attributes) hash.merge!(self_children_attributes) hash.merge!(parent_object_attributes) hash.merge!(contain_association_attributes) hash end # Returns 1st level attributes as a hash. def simple_attributes attribute_names = @record.attribute_names if options[:only] options.delete(:except) attribute_names = attribute_names & Array(options[:only]).collect(&:to_s) else options[:except] = Array(options[:except]) | Array(@record.class.inheritance_column) attribute_names = attribute_names - options[:except].collect(&:to_s) end attribute_names.reject! { |n| binary_attribute?(n) } # Don't JSON-ify binary fields! @record.attributes(:only => attribute_names) end # Returns 1st level methods as a hash. def method_attributes Array(options[:methods]).inject({}) do |method_attributes, name| method_attributes.merge!({ name.to_s => @record.send(name.to_s) }) if @record.respond_to?(name.to_s) method_attributes end end # Returns 1st level methods as a hash. #ext:=> options[:astract].is_a?(Hash) #:astract => {:id => :resource_id} def astract_attributes hash = {} if options[:astract] && options[:astract].is_a?(Hash) options[:astract].keys.each do |key| name = options[:astract][key] hash.merge!({ key.to_s => @record.send(name.to_s) }) if @record.respond_to?(name.to_s) hash end end hash end # Returns 1st level methods as a hash. #ext:=> options[:checked].is_a?(Hash) #:checked => obj #but the obj.is_a?(Hash) #using for role_is_checked and group_is_checked #2008-06-30 def checked_attributes hash = {} if options[:checked] && options[:checked].is_a?(Hash) if options[:checked].values.include?(@record.send(:id)) hash.merge!(:checked => true) else hash.merge!(:checked => false) end hash end hash end #2008-06-13 by ytok # Returns 1st level methods as a hash. def filter_attributes filter_object = options[:filter] if filter_object && filter_object.is_a?(Hash) filter_object.keys.each do |key| value = filter_object[key] if value.is_a?(Hash) value.keys.each do |class_name| add_method = value[class_name] if @record.instance_of?(key.class) if @record.ph.instance_of?(class_name.class) options[:methods].concat(add_method) end end end end end end end # Returns 1st level associations as a hash. Recursively "hashifies" # associations so that nth level associations are converted to JSON as well. def association_attributes hash = {} if include_associations = options.delete(:include) base_only_or_except = { :except => options[:except], :only => options[:only] } include_has_options = include_associations.is_a?(Hash) for association in include_has_options ? include_associations.keys : Array(include_associations) association_options = include_has_options ? include_associations[association] : base_only_or_except opts = options.merge(association_options) case @record.class.reflect_on_association(association).macro when :has_many, :has_and_belongs_to_many records = @record.send(association).to_a unless records.empty? hash[association] = records.collect { |r| JsonHashifier.new(r, opts).to_hash } end when :has_one, :belongs_to if record = @record.send(association) hash[association] = JsonHashifier.new(record, opts).to_hash end end end options[:include] = include_associations end hash end #2008-06-07 by ytok # Returns more 1st level associations as a hash. Recursively "hashifies" # associations so that nth level associations are converted to JSON as well. def self_children_attributes hash = {} if include_associations = options[:self] base_only_or_except = { :except => options[:except], :only => options[:only] } include_has_options = include_associations.is_a?(Hash) for association in include_has_options ? include_associations.keys : Array(include_associations) association_options = include_has_options ? include_associations[association] : base_only_or_except opts = options.merge(association_options) case @record.class.reflect_on_association(association).macro when :has_many, :has_and_belongs_to_many records = @record.send(association).to_a unless records.empty? hash[association] = records.collect { |r| JsonHashifier.new(r, opts).to_hash } else hash[association] = Array.new end when :has_one, :belongs_to if record = @record.send(association) hash[association] = JsonHashifier.new(record, opts).to_hash end end end options[:self] = include_associations end hash end #2008-06-09 by ytok # Returns more 1st level associations as a hash. Recursively "hashifies" # associations so that nth level associations are converted to JSON as well. def parent_object_attributes hash = {} if include_associations = options[:parent_object] base_only_or_except = { :except => options[:except], :only => options[:only] } include_has_options = include_associations.is_a?(Hash) association = include_has_options ? include_associations.keys : Array.new association.each do |associ| association_options = include_has_options ? base_only_or_except : include_associations[associ] opts = options.merge(association_options) case @record.class.reflect_on_association(associ).macro when :has_many, :has_and_belongs_to_many records = @record.send(associ).to_a unless records.empty? hash[include_associations[associ]] = records.collect { |r| JsonHashifier.new(r, opts).to_hash } else hash[include_associations[associ]] = Array.new end when :has_one, :belongs_to if record = @record.send(associ) hash[include_associations[associ]] = JsonHashifier.new(record, opts).to_hash else hash[include_associations[associ]] = Array.new end end end options[:parent_object] = include_associations end hash end #2008-06-10 by ytok # Returns more 1st level associations as a hash. Recursively "hashifies" # associations so that nth level associations are converted to JSON as well. def contain_association_attributes hash = {} if include_associations = options[:contains] if include_associations.is_a?(Hash) include_associations.keys.each do |contain_key| contain_value = include_associations[contain_key] attr_name = contain_key.to_sym hash = component_association_transact(attr_name, contain_value) end else attr_name = include_associations.to_sym hash = component_association_transact(attr_name, nil) end end hash end protected def binary_attribute?(name) !@record.class.serialized_attributes.has_key?(name) && @record.class.columns_hash[name].type == :binary end #2008-06-13 by ytok #核心处理关联关系部分 def component_association_transact(attr_name, attr_value = nil) hash = {} include_associations = options[:contains] base_only_or_except = { :except => options[:except], :only => options[:only] } association_options = base_only_or_except #处理待过滤属性 dispose_filter_attribute opts = options.merge(association_options) unless attr_value hash = dispose_association_attribute(attr_name, opts, attr_name, nil) else if attr_value.is_a?(Hash) attr_value.keys.each do |associations_method| ass_value = attr_value[associations_method] #nothing to do end elsif attr_value.is_a?(Symbol) hash = dispose_association_attribute(attr_value, opts, attr_name, nil) else hash = dispose_association_attribute(attr_name, opts, attr_name, attr_value) end end options[:contains] = include_associations hash end #2008-06-13 by ytok #处理关联关系核心 def dispose_association_attribute(association, opts, association_value, astract_value = nil) hash = {} case @record.class.reflect_on_association(association).macro when :has_many, :has_and_belongs_to_many records = @record.send(association).to_a unless records.empty? hash[association_value] = records.collect { |r| unless astract_value && r.ph.instance_of?(astract_value.class) JsonHashifier.new(r, opts).to_hash end } #处理掉空元素 temp = Array.new hash[association_value].each do |item| unless !item temp << item end end hash[association_value] = temp else hash[association_value] = Array.new end when :has_one, :belongs_to if record = @record.send(association) unless astract_value && record.ph.instance_of?(astract_value.class) hash[association_value] = JsonHashifier.new(record, opts).to_hash else hash[association_value] = Array.new end else hash[association_value] = Array.new end end hash end #处理待过滤属性 def dispose_filter_attribute filter_attr_name = Array.new filter_object = options[:filter] if filter_object && filter_object.is_a?(Hash) filter_object.keys.each do |key| filter_object[key].values.each do |value| value.each do |item| filter_attr_name << item end end end end filter_attr_name.each do |item| options[:methods].delete(item) end end end end end ActiveRecord::Base.send(:include, Jsonifier::JsonEncoding) ps======================================== 下面后续的说明其整个项目组织结构和开发中遇到的问题 声明:ITeye文章版权属于作者,受法律保护。没有作者书面许可不得转载。
推荐链接
|
|
返回顶楼 | |