制御フロー

コールバック

私たちは前および/または後にいくつかのロジックを実行する場合#callに実行され、我々はコールバックを使用することができます。コールバックは、ユーザーがサインインしているかどうかをチェックするような一般的なタスクのためのコードを片付けをするレコードを設定し、404の応答または整頓アップ応答を処理するのに有用です。

対応するDSLの方法があるbeforeafter。これらのメソッドはそれぞれ、我々が呼び出したいメソッド、または匿名PROCの名前であるシンボルを受け入れます。

 

メソッド

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action
    before :track_remote_ip

    def call(params)
      # ...
    end

    private
    def track_remote_ip
      @remote_ip = request.ip
      # ...
    end
  end
end

上記のコードでは、我々は分析の目的のためのリモートIPアドレスを追跡しています。それが私たちのビジネスロジックに厳密に関連していないので、我々はコールバックに移動します。

コールバックメソッドは、任意の引数を受け入れることができます:params

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action
    before :validate_params

    def call(params)
      # ...
    end

    private
    def validate_params(params)
      # ...
    end
  end
end

 

PROC

上記の例は、匿名のprocsので書き換えることができます。彼らは、アクションのインスタンスのコンテキストにバインドされています。

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action
    before { @remote_ip = request.ip }

    def call(params)
      # @remote_ip is available here
      # ...
    end
  end
end

コールバックprocがオプションの引数をバインドすることができますparams

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action
    before {|params| params.valid? }

    def call(params)
      # ...
    end
  end
end

電子メールを送信するようなモデルドメインの論理演算のためのコールバックを使用しないでください。これは、コードの保守、テスト容易性と偶然の副作用のために多くの問題を引き起こしアンチパターンです。

 

停止

制御フローのために例外を使用すると、RubyのVMのために高価です。私たちの言語がサポートしている軽量な代替手段があります:信号が(参照throwcatch)。

花見は、提供するために、この仕組みを利用してより高速な制御フローを経由して私たちの行動に#halt

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action

    def call(params)
      halt 401 unless authenticated?
      # ...
    end

    private
    def authenticated?
      # ...
    end
  end
end

使用される場合、このAPIは、流れを中断し、フレームワークに制御を返します。後続の命令は完全にスキップされます。

ときにhalt使用され、流れが中断され、制御は、フレームワークに戻されます。

それはそれが意味haltをスキップするために使用することができ#call、我々はそれを使用する場合、完全に起動するbeforeコールバック。

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action
    before :authenticate!

    def call(params)
      # ...
    end

    private
    def authenticate!
      halt 401 if current_user.nil?
    end
  end
end

#halt最初の引数としてHTTPステータスコードを受け入れます。このように使用すると、レスポンスのボディは、対応するメッセージ(例えば、「未承認」のために設定されます401)。

オプションの第二引数は、カスタムボディを設定するために渡すことができます。

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action

    def call(params)
      halt 404, "These aren't the droids you're looking for"
    end
  end
end

ときに#halt使用され、花見は HTTPステータスとメッセージを持つデフォルトのステータス・ページをレンダリングします。

Hanami default template

HTTP 404エラーのためのUIをカスタマイズするには、使用できるカスタムエラーページを

 

HTTPステータス

場合にはあなたの代わりに使用するのでは、エラーを処理するためのビューを聞かせて欲しい#halt、あなたが使用する必要があります#status=

典型的なケースは、失敗したフォームの送信:我々は(非成功したHTTPステータスを返すようにしたい422)とビューが再びフォームをレンダリングし、検証エラーを表示するようにしましょう。

# apps/web/controllers/books/create.rb
module Web::Controllers::Books
  class Create
    include Web::Action

    params do
      required(:title).filled(:str?)
    end

    def call(params)
      if params.valid?
        # persist
      else
        self.status = 422
      end
    end
  end
end
# apps/web/views/books/create.rb
module Web::Views::Books
  class Create
    include Web::View
    template 'books/new'
  end
end
# apps/web/templates/books/new.html.erb
<% unless params.valid? %>
  
    <% params.error_messages.each do |error| %><%= error %>

 


    <% end %>
  

 


<% end %>


 

リダイレクト

制御フロー管理の特別な場合は、HTTPリダイレクトに対するものです。我々が使用することができ、他のリソースへの要求を再ルーティングしますredirect_to

ときにredirect_to起動され、制御フローが停止され、動作中に後続のコードが実行されません

これは、URIを表す文字列、およびオプションの受け入れ:status引数を。デフォルトでは、ステータスがに設定されています302

# apps/web/controllers/dashboard/index.rb
module Web::Controllers::Dashboard
  class Index
    include Web::Action

    def call(params)
      redirect_to routes.root_path
      foo('bar') # This line will never be executed
    end
  end
end

 

バック

時には、あなたはしたいと思うredirect_toそれを行うための簡単な方法は、以下の方法であるように、ブラウザの履歴にバックアップ:

redirect_to request.headers["Referer"] || fallback_url