我有以下复杂的方法。我正在努力寻找并实施可能的改进。现在我把if语句移到Access
类。
def add_access(access)
if access.instance_of?(Access)
up = UserAccess.find(:first, :conditions => ['user_id = ? AND access_id = ?', self.id, access.id])
if !up && company
users = company.users.map{|u| u.id unless u.blank?}.compact
num_p = UserAccess.count(:conditions => ['user_id IN (?) AND access_id = ?', users, access.id])
if num_p < access.limit
UserAccess.create(:user => self, :access => access)
else
return "You have exceeded the maximum number of alotted permissions"
end
end
end
end
我想在重构之前添加规范。我先加了一个。怎么看起来像其他人?
describe "#add_permission" do
before do
@permission = create(:permission)
@user = create(:user)
end
it "allow create UserPermission" do
expect {
@user.add_permission(@permission)
}.to change {
UserPermission.count
}.by(1)
end
end
答案 0 :(得分:2)
您是否为此课程进行了单元测试或集成测试? 我会在重构前先写一些。
假设您有测试,第一个目标可能是缩短此方法的长度。
以下是一些改进:
UserAccess.find
调用移至UserAccess
模型并将其设为命名范围。 count
方法。 每次更换后重新测试并保持提取,直到它干净。每个人都对清洁有不同的看法,但是当你看到它时就会知道。
答案 1 :(得分:2)
我会这样做。
将Access的检查更像是一个初始断言,并在发生错误时引发错误。
创建一种新方法来检查现有的用户访问权限 - 这似乎是可重用的,并且更具可读性。
然后,公司限制更像是对我的验证,将其作为自定义验证移至UserAccess类。
class User
has_many :accesses, :class_name=>'UserAccess'
def add_access(access)
raise "Can only add a Access: #{access.inspect}" unless access.instance_of?(Access)
if has_access?(access)
logger.debug("User #{self.inspect} already has the access #{access}")
return false
end
accesses.create(:access => access)
end
def has_access?(access)
accesses.find(:first, :conditions => {:access_id=> access.id})
end
end
class UserAccess
validate :below_company_limit
def below_company_limit
return true unless company
company_user_ids = company.users.map{|u| u.id unless u.blank?}.compact
access_count = UserAccess.count(:conditions => ['user_id IN (?) AND access_id = ?', company_user_ids, access.id])
access_count < access.limit
end
end
答案 2 :(得分:1)
其他想法,与移动代码无关但更清晰:
users = company.users.map{|u| u.id unless u.blank?}.compact
num_p = UserAccess.count(:conditions => ['user_id IN (?) AND access_id = ?', users, access.id])
可以成为:
num_p = UserAccess.where(user_id: company.users, access_id: access.id).count