0

次のアクションは、新しいコメントを作成します。

  • ユーザーには多くのステータスがあります
  • ステータスには多くのコメントがあります

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

ありがとうございました。

4

3 に答える 3

2

いつ戻りたい401ですか?

  1. ユーザーが見つからない場合
  2. ユーザーが現在のユーザーではないか、そのユーザーの友達ではない場合
  3. ステータスが見つからない場合
  4. 新しいコメントが正常に作成されなかった場合

非常に多くの条件を使用する代わりに、例外を発生させるメソッドを使用できます。そうすることで、目的の動作 (レンダリング401) でその例外から救うことができます。

したがって、リストされた条件に対する私の提案は次のとおりです。

  1. find!の代わりに使用します。wherefirst
  2. raise何か、できればカスタム例外 ( NotAFriendError)
  3. 1.と同じ、使用find!
  4. use 、これはand thenとcreate!同等で、検証に失敗した場合に例外を発生させます。newsave!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
于 2012-10-14T14:10:56.033 に答える
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 が返されることに注意してください。ただし、これはより理にかなっている可能性があります (私はそうだと思います)。
  • オブジェクトが有効でない場合に戻るため、 の@comment.valid?直前@comment.saveで呼び出さないでください。savefalse
  • ブール論理||の代わりに使用します (それらは同じではありません)。or
  • render(status: ..., content: '')の代わりに使用しhead ... and returnます。
  • ブール変数を使用して、メソッドの成功を追跡します。

このロジックの一部をモデルに引き出してみることをお勧めします。たとえばUser#friend_with、同じユーザーが渡された場合は、おそらく true を返す必要があります。

于 2012-10-13T12:59:31.653 に答える
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
于 2012-10-13T12:36:50.823 に答える