2012-10-13 39 views
0

下面的操作会创建一条新评论。Rails:如何优化此操作

  • 用户有很多状态
  • 一个状态有很多评论

使head 401 and return不重复多少次能优化这个动作。

def create 
    @user = User.where(id: params[:user_id]).first 
    if @user 
    if current_user.friend_with?(@user) or current_user == @user 
     @status = @user.statuses.where(id: params[:status_id]).first 
     if @status 
     @comment = @status.comments.build(params[:comment]) 
     @comment.owner = current_user 
     if @comment.valid? 
      @comment.save 
      current_user.create_activity(:comment_status, @comment, @user) 
     else 
      head 401 and return 
     end 
     else 
     head 401 and return 
     end 
    else 
     head 401 and return 
    end 
    else 
    head 401 and return 
    end 
end 

谢谢。

回答

2

什么时候要退回401

  1. 当用户还没有发现
  2. 当用户不是当前用户,或者不是用户
  3. 的朋友,当状态一直没有找到
  4. 当新的评论还没有已成功创建

而不是使用这么多的条件,您可以使用引发异常的方法。当您这样做时,您可以通过所需的行为(渲染401)从异常中解救出来。

所以我对于上市条件的建议是:

  1. 使用find!,而不是where然后first
  2. raise的东西,最好是自定义异常(NotAFriendError
  3. 一样1,使用find!
  4. 使用create!,这是一个相当于new然后save!这将提高ActiveRecord::RecordInvalid异常,如果它失败的验证。

这里的结果:

def create 
    begin 
    @user = User.find!(params[:user_id]) 
    raise unless current_user.friend_with?(@user) || current_user == @user 
    @status = @user.statuses.find!(params[:status_id]) 
    @comment = @status.comments. 
     create!(params[:comment].merge(:owner => current_user)) 
    rescue ActiveRecord::RecordNotFound, ActiveRecord::RecordInvalid 
    head 401 
    end 
    # everything went well, no exceptions were raised 
    current_user.create_activity(:comment_status, @comment, @user) 
end 
0
def create 
    @user = User.where(id: params[:user_id]).first 
    if @user 
    if current_user.friend_with?(@user) or current_user == @user 
     @status = @user.statuses.where(id: params[:status_id]).first 
     if @status 
     @comment = @status.comments.build(params[:comment]) 
     @comment.owner = current_user 
     if @comment.valid? 
      @comment.save 
      current_user.create_activity(:comment_status, @comment, @user) 
      everythingOK = true 
     end 
     end 
    end 
    end 
    head 401 and return unless everythingOK 
end 
2

你有很多过度检查和代码中的分支,因此它可以简化为这样:

def create 
    success = false 

    @user = User.find(params[:user_id]) 
    current_user_is_friend = current_user.friend_with?(@user) || current_user == @user 

    if @user && current_user_is_friend && @status = @user.statuses.find(params[:status_id]) 
    @comment = @status.comments.build(params[:comment]) 
    @comment.owner = current_user 
    if @comment.save 
     current_user.create_activity(:comment_status, @comment, @user) 
     success = true 
    end 
    end 

    render(status: 401, content: '') unless success 
end 

有几件事情我做:

  • 结合了很多的条件,因为它们不需要分开。
  • where(id: ...).first更改为find(...),因为它们是相同的。需要注意的是,如果find失败,它会给出一个404,这可能更有意义,但(我认为它)
  • 不要@comment.save前右打电话@comment.valid?,因为save返回false如果对象是无效。
  • 对于布尔逻辑(they're not the same),使用||而不是or。使用render(status: ..., content: '')代替head ... and return
  • 使用布尔变量来跟踪方法的成功。

我会建议你试着将这些逻辑推出模型。例如,如果User#friend_with传递的是同一个用户,则应该只返回true。

+1

'那里(:ID => ...)。first'并不完全等同于'find',因为'find'引发'的ActiveRecord :: RecordNotFound'而不是返回零。这种情况现在将返回404,而不是标准错误页面而不是401。此外,'head 401和return'将返回401没有内容,而'render(status:401)'将呈现401状态的模板。 – willglynn

+0

你能解释一下为什么你建议不使用内容而不使用'head'使用'render'? – shime

+1

@shime因为简单地'返回'意味着渲染没有内容是一个副作用,而不是一个明确的陈述。最好先说明你的意图,而不是依赖副作用,读者期待他们。 –