`
yangtao309
  • 浏览: 64871 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

应用Rails+Ext开发企业级权限平台

阅读更多
  应用Rails+Ext开发企业级权限平台
一般说来做企业级权限平台都是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======================================== 下面后续的说明其整个项目组织结构和开发中遇到的问题
  • 大小: 80.7 KB
  • 大小: 82.5 KB
  • 大小: 91.5 KB
  • 大小: 105.7 KB
  • 大小: 94.6 KB
  • 大小: 91.9 KB
  • 大小: 89.7 KB
  • 大小: 99.4 KB
  • 大小: 107.1 KB
  • 大小: 77 KB
  • 大小: 80.4 KB
  • 大小: 81.4 KB
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics