Rails:如何优化此操作

时间:2012-10-13 12:32:18

标签: ruby-on-rails ruby optimization methods

下面的动作会创建一个新评论。

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

如何优化此操作,以便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

谢谢。

3 个答案:

答案 0 :(得分: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

我做过的一些事情:

  • 结合了很多if条件,因为没有必要将它们分开。
  • where(id: ...).first更改为find(...),因为它们是相同的。请注意,如果find失败,它将给出404.这可能更有意义,但是(我认为确实如此)
  • 请勿在{{1​​}}之前致电@comment.valid?,因为如果对象无效,@comment.save会返回save
  • 使用false代替||作为布尔逻辑(they're not the same)。
  • 使用or代替render(status: ..., content: '')
  • 使用布尔变量来跟踪方法的成功。

我建议您尝试将一些逻辑推入模型中。例如,head ... and return如果传递给同一个用户,则应该返回true。

答案 1 :(得分:2)

您想何时返回401

  1. 未找到用户时
  2. 当用户不是当前用户或不是该用户的朋友时
  3. 未找到状态时
  4. 尚未成功创建新评论时
  5. 您可以使用引发异常的方法,而不是使用这么多条件。执行此操作时,您可以使用所需行为(渲染401)来拯救这些异常。

    所以我对列出条件的建议是:

    1. 使用find!代替where,然后使用first
    2. raise,最好是自定义异常(NotAFriendError
    3. 与1.相同,使用find!
    4. 使用create!,它等同于new,然后是save!,如果验证失败,将会引发ActiveRecord::RecordInvalid异常。
    5. 结果如下:

      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
      

答案 2 :(得分: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