前些天看到社区中一篇 @beiersi 写的 《写一点 CanCan 结合数据库使用的简单实现》 。觉得不错,但是少了自动同步到数据库的一些实现。 后来参考了 cancan 的 wiki 《Abilities in Database》 ,写成任务来执行同步,在 jruby171 下面能用,应该 mri193 也没问题。
desc "Synchronize controllers' actions as permissions to database"
task :sync_perm => :environment do
synchornize_controllers_actions_as_permissions_to_db
end
def synchornize_controllers_actions_as_permissions_to_db
write_permission(:action => "manage", :subject => "all", :action_description => "All operations", :subject_description => "Everything")
Dir.new("#{Rails.root}/app/controllers").entries.each do |controller|
controller.camelize.gsub(".rb","").constantize.new if controller =~ /_controller/
end
ApplicationController.subclasses.each do |controller|
clazz = controller.name.gsub("Controller","").singularize.understore
actions = controller.action_methods.reject{|action| action.to_s.index("_callback")}
write_permission(:action => "manage", :subject => clazz, :action_description => "All operations", :subject_description => clazz.camelize, :alias_actions => actions.join(","))
actions.each do |action|
cancan_action, action_description = eval_cancan_action(action)
write_permission(:action => cancan_action, :subject => clazz, :action_description => action.camelize, :subject_description => clazz.camelize, :alias_actions => action)
end
end
end
def eval_cancan_action(action)
case action.to_s
when "index", "show", "search"
cancan_action = "read"
action_desc = I18n.t :read
when "create", "new"
cancan_action = "create"
action_desc = I18n.t :create
when "edit", "update"
cancan_action = "update"
action_desc = I18n.t :edit
when "delete", "destroy"
cancan_action = "delete"
action_desc = I18n.t :delete
else
cancan_action = action.to_s
action_desc = "Other: " << cancan_action
end
return cancan_action, action_desc
end
def write_permission(options={})
options = {:action => "", :subject => "", :action_description => "", :subject_description => "", :alias_actions => ""}.merge options
permission = Permission.where(:subject => options[:subject], :action => options[:action]).first || Permission.new
options[:alias_actions] = Set.new((permission.alias_actions||"").split(",")|(options[:alias_actions]||"").split(",")).delete_if(&:empty?).to_a.sort.join(",")
permission.update_attributes(options)
end