2

一点背景:

我的应用程序toolspermission_levels. 有些User's 对某些人有授权,而对其tools他人则没有。管理面板是使用rails_admin gem构建的。

如果管理员正在编辑 aUser并且User有权访问tools管理员没有的权限,则这些工具不会显示在编辑视图中(这是需要的)。但是,当管理员更新 时UserUser会丢失与未显示的tools关联permission_levels

为了解决这个问题,我覆盖了#editRailsAdmin 中的操作。生成的代码有点乱,我想通过将相关代码提取到方法中来进行重构,但是该部分被包装在Proc.

如何将下面的代码提取到方法中?具体来说,register_instance_option :controller节。

.
.
.
module Actions
  class Edit < RailsAdmin::Config::Actions::Base

    register_instance_option :member? do
      true
    end

    register_instance_option :route_fragment do
      'edit'
    end

    register_instance_option :http_methods do
      [:get, :put]
    end

    register_instance_option :visible? do
      authorized?
    end

    register_instance_option :controller do
      Proc.new do
        if @object.class.base_class.name == 'User'
          if request.get?
            session[:tools] = (@object.tools - Tool.admined_by(current_user)).map(&:id)
            pl = session[:tools].map do |t|
              tl = Tool.find(t)
              tl.permission_levels
            end
            session[:permission_levels] = []
            pl.flatten.each do |p|
              session[:permission_levels] << p if @object.permission_levels.include?(p)
            end
            session[:permission_levels].map!(&:id)
          elsif request.put?
            duped_tools = session[:tools].dup
            params[:user][:tool_ids] = duped_tools.
              concat(params[:user][:tool_ids]).uniq!.delete_if { |id| id == "" }.
              map { |id| id.to_i }
            duped_permission_levels = session[:permission_levels].dup
            params[:user][:permission_level_ids] = duped_permission_levels.
              concat(params[:user][:permission_level_ids]).uniq!.delete_if { |id| id == "" }.
              map { |id| id.to_i }
            if @object.update_attributes(params.require(:user).permit!)
              session[:tools] = nil
              session[:permission_levels] = nil
              duped_session = nil
              flash[:success] = t("admin.flash.successful", :name => @model_config.label, :action => t("admin.actions.edit.done"))
              redirect_to index_path
            else
              flash[:error] = t("admin.flash.error", :name => @model_config.label, :action => t("admin.actions.edit.done"))
              redirect_path = back_or_index
            end
          end
        end
      end
    end

    register_instance_option :link_icon do
      'icon-pencil'
    end
  end
end
.
.
.
4

1 回答 1

2

为了使用更少的行数并可能获得更好的性能,这里有一些代码改进:

使用更少的行:

# All `register_instance_option` can be refactored in a one-line bock:
register_instance_option :member? do
  true
end
# to
register_instance_option(:member?) { true }

更好地使用 Rails 的方法:

if @object.class.base_class.name == 'User'
# can be changed to:
if @object.kind_of?(User) # will not work if @object is a Admin which inherits from User class

array_of_ids.delete_if { |id| id == "" }
# can be changed to:
array_of_ids.select(&:present?)

array = session[:tools].map do
  # your logic
end
array = array.flatten
# can be changed to:
array = session[:tools].flat_map do
  # your logic
end
# no need for a flatten (thanks to `.flat_map`)

session[:tools] = nil
session[:permission_levels] = nil
duped_session = nil
# can be changed to:
session[:tools] = session[:permission_levels] = duped_session = nil

我会将您的代码重构为:(请随时对此发表评论)

if @object.kind_of?(User)
  if request.get?
    session[:tools] = @object.tools.where('id NOT IN (?)', Tool.admined_by(current_user).pluck(:id)) # better performances
    session[:tools] = session[:tools].includes(:permission_levels).flat_map(&:permission_levels)
    session[:permission_levels] = []
    session[:tools].each do |p|
      session[:permission_levels] << p.id if @object.permission_levels.include?(p)
    end

  elsif request.put?
    duped_tools = session[:tools].dup
    params[:user][:tool_ids] = duped_tools.concat(params[:user][:tool_ids]).uniq.select(&:present?).map(&:to_i)
    duped_permission_levels = session[:permission_levels].dup
    params[:user][:permission_level_ids] = duped_permission_levels.concat(params[:user][:permission_level_ids]).uniq.select(&:present?).map(&:to_i)
    if @object.update_attributes(params.require(:user).permit!)
      session[:tools] = session[:permission_levels] = nil
      flash[:success] = t("admin.flash.successful", name: @model_config.label, name: t("admin.actions.edit.done"))
      redirect_to index_path
    else
      flash[:error] = t("admin.flash.error", name: @model_config.label, action: t("admin.actions.edit.done"))
      redirect_path = back_or_index
    end
  end
end
于 2014-07-15T16:50:40.973 回答