所以我在我的新闻稿发布申请中有这个大方法。方法是更新人造丝,我需要将用户分配给人造丝。我的关系是n:n到表colporteur_in_rayons
,其中包含since_date
和until_date
属性。
我是初级程序员,我知道这段代码非常虚拟:) 我很欣赏每一个建议。
def update
rayon = Rayon.find(params[:id])
if rayon.update_attributes(params[:rayon])
if params[:user_id] != ""
unless rayon.users.empty?
unless rayon.users.last.id.eql?(params[:user_id])
rayon.colporteur_in_rayons.last.update_attributes(:until_date => Time.now)
Rayon.assign_user(rayon.id,params[:user_id])
flash[:success] = "Rayon #{rayon.name} has been succesuly assigned to #{rayon.actual_user.name}."
return redirect_to rayons_path
end
else
Rayon.assign_user(rayon.id,params[:user_id])
flash[:success] = "Rayon #{rayon.name} has been successfully assigned to #{rayon.actual_user.name}."
return redirect_to rayons_path
end
end
flash[:success] = "Rayon has been successfully updated."
return redirect_to rayons_path
else
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
end
答案 0 :(得分:5)
def update
rayon = Rayon.find(params[:id])
unless rayon.update_attributes(params[:rayon])
flash[:error] = "Rayon not updated."
return redirect_to :back
end
puid = params[:user_id]
empty = rayon.users.empty?
if puid == "" or (not empty and rayon.users.last.id.eql?(puid))
msg = "Rayon updated.",
else
msg = "Rayon #{rayon.name} assigned to #{rayon.actual_user.name}.",
rayon.colporteur_in_rayons.last.update_attributes(
:until_date => Time.now) unless empty
Rayon.assign_user(rayon.id, puid)
end
flash[:success] = msg[msg_i]
return redirect_to rayons_path
end
答案 1 :(得分:1)
有一些双重代码。所以删除它。但是,控制器中还有一些业务代码,不应该存在。所以我应该按如下方式重构控制器代码:
def update
rayon = Rayon.find(params[:id])
if rayon.update_attributes(params[:rayon])
if params[:user_id] != ""
rayon.handle_update_user(params[:user_id]
flash[:success] = "Rayon #{rayon.name} has been succesuly assigned to #{rayon.actual_user.name}."
else
flash[:success] = "Rayon has been successfully updated."
end
return redirect_to rayons_path
else
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
end
控制器方法现在可以清楚地处理需要采取的操作,并在需要时相应地设置闪存方法。
在Rayon模型中,您可以编写代码,当用户完成更新时需要执行的操作:
class Rayon
def handle_update_user(user_id)
if (!users.empty? && users.last.id.eql?(params[:user_id]))
# do nothing!
else
colporteur_in_rayons.last.update_attributes(:until_date => Time.now) unless users.empty?
Rayon.assign_user(rayon.id,params[:user_id])
end
end
end
这清楚地表明了这些担忧。人造丝应该知道当用户更新它时会发生什么(函数的名称可以改进到你实际想要它的意思,因为这对我来说并不完全清楚)。 它可能更短,但我想明确地写下如果最后一个用户与当前用户相同则不需要做任何事情。否则,需要采取行动。如果我理解正确的话。
答案 2 :(得分:0)
这是我的看法。我把一堆评论内联描述了为什么我改变了我的所作所为。
def update
rayon = Rayon.find(params[:id])
if rayon.update_attributes(params[:rayon])
user_id = params[:user_id] # using same value a couple times
# if-else strongly preferred over unless-else...
# so replace `unless foo.empty?` with `if foo.length > 0`
if user_id.length > 0 # then string != ""
# `if A && B` more readable than `unless X || Y` in my opinion
if rayon.users.length > 0 && rayon.users.last.id != user_id
rayon.colporteur_in_rayons.last.update_attributes(:until_date => Time.now)
end
# same line in if-else; pull outside
Rayon.assign_user(rayon.id, user_id)
flash[:success] = "Rayon #{rayon.name} has been successfully assigned to #{rayon.actual_user.name}."
else
flash[:success] = "Rayon has been successfully updated."
end
# all branches in here return this value, pull outside
return redirect_to rayons_path
else
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
end
我注意到你的代码中最大的问题是你的第一个if-block中有很多重复。真部分中的所有分支都达到了return redirect_to rayons_path
,因此被拉到了块的末尾。你有两次相同的flash[:success] = ...
,所以也被拉出来了。
if-else
比unless-else
更具可读性,因此请尽量避免使用后者。我不是一个粉丝,除非立即嵌套在另一个中,所以我将其改为复合if语句。
Rails中的一个主要习语是DRY(不要重复自己),所以尽量找出做重复代码的地方。
(另请注意,我没有测试过这种重构 - 我很确定逻辑仍然相同,但我无法证明。)
答案 3 :(得分:0)
def update
rayon = Rayon.find(params[:id])
unless rayon.update_attributes(params[:rayon])
flash[:error] = "Rayon has not been updated."
return redirect_to :back
end
if params[:user_id].empty?
msg = "Rayon has been successfully updated."
else
if rayon.users.empty?
Rayon.assign_user(rayon.id,params[:user_id])
msg = "Rayon #{rayon.name} has been successfully assigned to #{rayon.actual_user.name}."
elsif not rayon.users.last.id.eql?(params[:user_id])
rayon.colporteur_in_rayons.last.update_attributes(:until_date => Time.now)
Rayon.assign_user(rayon.id,params[:user_id])
msg = "Rayon #{rayon.name} has been succesuly assigned to #{rayon.actual_user.name}."
end
end
flash[:success] = msg
return redirect_to rayons_path
end