执行this code kata并且我必须从以下方法中尽可能多地删除if语句:
# returns permissions if user is set in security context
def get_user_permissions
user_permissions = Set.new
if (@user != nil)
user_permissions << :DEFAULT_PERMISSION
if (has_cm_team_role)
user_permissions << :CM_TEAM_ROLE_PERMISSION
end
if (has_cm_invoice_view_role || has_invoice_finance_role)
user_permissions << :CM_INVOICE_USER_PERMISSION
user_permissions << :INVOICE_VIEW_PERMISSION
user_permissions << :ACCESS_ALL_INVOICE_PERMISSION
end
if (has_invoice_finance_role)
user_permissions << :FINANCE_INVOICE_PERMISSION
end
if (has_application_access)
user_permissions << :CM_INVOICE_USER_PERMISSION
end
if (has_application_access(:CM_INVOICE_ROLE))
user_permissions << :CM_ANY_INVOICE_PERMISSION
end
if (has_application_access(:PA_INVOICE_ROLE))
user_permissions << :PA_ANY_INVOICE_PERMISSION
end
if (has_application_access(:SDT_INVOICE_ROLE))
user_permissions << :SDT_ANY_INVOICE_PERMISSION
end
end
user_permissions
end
我的第一次尝试几乎有效,但有些测试失败了:
def get_user_permissions
user_permissions = Set.new
if (@user != nil)
user_permissions << :DEFAULT_PERMISSION
# add the permissions in another method
add_permissions(user_permissions)
end
user_permissions
end
def add_permissions(user_permissions)
# a hash where each key is a condition, and each value is a permission
hash = {
has_cm_team_role => :CM_TEAM_ROLE_PERMISSION,
has_cm_invoice_view_role || has_invoice_finance_role => :CM_INVOICE_USER_PERMISSION,
has_cm_invoice_view_role || has_invoice_finance_role => :INVOICE_VIEW_PERMISSION,
has_cm_invoice_view_role || has_invoice_finance_role => :ACCESS_ALL_INVOICE_PERMISSION,
has_invoice_finance_role => :FINANCE_INVOICE_PERMISSION,
has_application_access => :CM_INVOICE_USER_PERMISSION,
has_application_access(:CM_INVOICE_ROLE) => :CM_ANY_INVOICE_PERMISSION,
has_application_access(:PA_INVOICE_ROLE) => :PA_ANY_INVOICE_PERMISSION,
has_application_access(:SDT_INVOICE_ROLE) => :SDT_ANY_INVOICE_PERMISSION
}
# loop through the hash and add permissions if the key is true
hash.each do |condition, permission|
if (condition)
user_permissions << permission
end
end
这种方法的问题在于,每个不会评估三个 OR 语句(在我的哈希的第二,第三和第四个键中)。所以我通过使用Procs解决这个问题,如下:
def add_permissions(user_permissions)
hash = {
Proc.new{has_cm_team_role} => :CM_TEAM_ROLE_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :CM_INVOICE_USER_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :INVOICE_VIEW_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :ACCESS_ALL_INVOICE_PERMISSION,
Proc.new{has_invoice_finance_role} => :FINANCE_INVOICE_PERMISSION,
Proc.new{has_application_access} => :CM_INVOICE_USER_PERMISSION,
Proc.new{has_application_access(:CM_INVOICE_ROLE)} => :CM_ANY_INVOICE_PERMISSION,
Proc.new{has_application_access(:PA_INVOICE_ROLE)} => :PA_ANY_INVOICE_PERMISSION,
Proc.new{has_application_access(:SDT_INVOICE_ROLE)} => :SDT_ANY_INVOICE_PERMISSION
}
hash.each do |condition, permission|
if (condition.call)
user_permissions << permission
end
end
end
确定,这是有效的,测试全部通过,但我将所有的密钥转换为Procs,只是为了让其中3个正确评估。我更喜欢只在需要时使用Procs,即第二,第三和第四个键,如下所示:
def add_permissions(user_permissions)
hash = {
# just use the method name unless a Proc is required
has_cm_team_role => :CM_TEAM_ROLE_PERMISSION,
# use a Proc here, so that the OR is evaluated later
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :CM_INVOICE_USER_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :INVOICE_VIEW_PERMISSION,
Proc.new{has_cm_invoice_view_role || has_invoice_finance_role} => :ACCESS_ALL_INVOICE_PERMISSION,
has_invoice_finance_role => :FINANCE_INVOICE_PERMISSION,
has_application_access => :CM_INVOICE_USER_PERMISSION,
has_application_access(:CM_INVOICE_ROLE) => :CM_ANY_INVOICE_PERMISSION,
has_application_access(:PA_INVOICE_ROLE) => :PA_ANY_INVOICE_PERMISSION,
has_application_access(:SDT_INVOICE_ROLE) => :SDT_ANY_INVOICE_PERMISSION
}
然后用某种方法确定密钥是否为Proc,如果是,则调用它,但如果没有,只需将条件视为任何其他密钥:
hash.each do |condition, permission|
if condition.is_proc?
if (condition.call)
user_permissions << permission
end
elsif condition
user_permissions << permission
end
end
end
任何提示?还有比我试图做的更好的想法吗?通过这样做,我是否使它更具周期性复杂性?我应该坚持使用我的工作解决方案,其中所有的密钥都是Procs?
答案 0 :(得分:3)
condition.is_a? Proc
满足您的条件吗?
答案 1 :(得分:1)
没有关于过程问题的事情。我从未做过代码kata,但我认为你可以改进的东西很少。
首先,作为哈希键的条件对我来说是一个坏主意。你将有许多重复的密钥,只有虚假和真实 我会以另一种方式执行此操作并将您的权限设置为键,值将为true或false。
你也有3次完全相同的指令,每次只改变2个字母。
if (has_application_access(:CM_INVOICE_ROLE))
user_permissions << :CM_ANY_INVOICE_PERMISSION
end
if (has_application_access(:PA_INVOICE_ROLE))
user_permissions << :PA_ANY_INVOICE_PERMISSION
end
if (has_application_access(:SDT_INVOICE_ROLE))
user_permissions << :SDT_ANY_INVOICE_PERMISSION
end
可以减少到
%(cm pa sdt).each do |key|
user_permissions << :"#{key}_ANY_INVOICE_PERMISSION" if has_application_access(:"#{key}_INVOICE_ROLE")
end
我试着这样做,得到了两个结果。一个使用哈希,一个只是尽可能地切割。
# Hash version
def get_user_permissions
return Set.new if !!@user
user_permissions_hash = {:DEFAULT_PERMISSION => true,
:CM_TEAM_ROLE_PERMISSION => has_cm_team_role,
:CM_INVOICE_USER_PERMISSION => has_cm_invoice_view_role || has_invoice_finance_role || has_application_access,
:INVOICE_VIEW_PERMISSION => has_cm_invoice_view_role || has_invoice_finance_role,
:ACCESS_ALL_INVOICE_PERMISSION => has_cm_invoice_view_role || has_invoice_finance_role,
:FINANCE_INVOICE_PERMISSION => has_invoice_finance_role
}
%(cm pa sdt).each do |key|
user_permissions_hash[:"#{key}_ANY_INVOICE_PERMISSION"] = has_application_access(:"#{key}_INVOICE_ROLE")
end
return user_permissions_hash.map {|k, v| k if v}.compact.to_set
end
# Normal version
def get_user_permissions
return (user_permissions = Set.new) if !!@user
user_permissions << :DEFAULT_PERMISSION
user_permissions << :CM_TEAM_ROLE_PERMISSION if has_cm_team_role
user_permissions << :CM_INVOICE_USER_PERMISSION if has_cm_invoice_view_role || has_invoice_finance_role || has_application_access
if (has_cm_invoice_view_role || has_invoice_finance_role)
user_permissions << :INVOICE_VIEW_PERMISSION
user_permissions << :ACCESS_ALL_INVOICE_PERMISSION
end
user_permissions << :FINANCE_INVOICE_PERMISSION if has_invoice_finance_role
%(cm pa sdt).each do |key|
user_permissions << :"#{key}_ANY_INVOICE_PERMISSION" if has_application_access(:"#{key}_INVOICE_ROLE")
end
user_permissions
end