私たちの最初のアプリ


アプリをセットアップする


このシリーズの最初の2つのセクションでは、読者はRuby on Railsを学ぶためのブログアプリを構築するように求められます。これを開始するには、以下のコマンドを実行してスターターアプリをクローンします。


# make sure to use ruby version 2.2
$ git clone // wait for edit
$ cd demystifying_rails_app_template
$ bundle exec bundle install
$ bundle exec rails server
$ bundle exec railsサーバが起動したら、ブラウザでhttp:// localhost:3000 /にアクセスするだけでアプリケーションを使用できます。


このRailsアプリを起動して実行したら、HTTPリクエストに応答させましょう。


具体的には、ブラウザから/ hello_worldへのリクエストで、Hello、worldというテキストがブラウザに表示されるようにしたいとします。


Railsでは、本質的にと見るとこれは2つのステップのプロセスです。


1 リクエストの送信先を定義します
2 この種のリクエストを処理するコードを定義します
これらの1つ目は、ルートを宣言することによって実現されます。
2つ目は、コントローラに定義されたメソッドによって実現されます。このようなリクエストを処理するロジックを含む、コントローラにあるメソッドをアクションと呼びます。


次のいくつかの章では、最初のRailsアプリケーションを構築するための手順を説明します。


リクエストと応答の送信


ルートの定義


Railsアプリケーションの「入り口」は、Railsアプリケーションに着信リクエストを処理するコードの場所を知らせる「ルート」です。


ルートの必要性を証明するために、先にパスをアクセスしましょう。


http:// localhost:3000 / hello_worldにアクセスし、何が起こるかを見てください。


Routing Error
No route matches [GET] “/hello_world”


まだルートを定義していないため、このエラーが出てしまうんです。


このようなリクエストを、新しいアクションにポイントするルートを定義することでこのようなエラーが修正できます。


Railsルートファイルには、アプリのルートリストが含まれています。


各ルートは、HTTPメソッド(GET、POSTなど)とURLパターンの組み合わせで、コントローラーとアクションの組み合わせにマッピングされます。


このエラーは、GETリクエストとURLパターン/ hello_worldの組み合わせのルートがないことを示しています。


configディレクトリのroutes.rbファイルにルートを定義しましょう。


config/routes.rb
Rails.application.routes.draw do
 get ‘/hello_world’ => ‘application#hello_world’
end


route.rbの中のブロックで、それぞれのHTTPメソットの後に、自分で名前をつけるメソッドが利用できます。


次に、URLパターンを定義し、コントローラと、このタイプのリクエストの処理コードが存在するアクションの組み合わせを定義します。


ここでは、このリクエストを処理するコードがApplicationControllerのhello_worldアクションに存在することを定義していますが、まだそれらを定義していないので、次にそれを行います。


ここで、http:// localhost:3000 / hello_worldページを更新すると、次のエラーが発生します。


Unknown action
The action ‘hello_world’ could not be found for ApplicationController


次のセクションでは、このルートのアクションをApplicationControllerで定義することで、この問題に取り組んでいきます。


アクションの定義


最初の指定ルートとして、ApplicationControllerに存在すべきhello_worldアクションを定義する時間です。


app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  def hello_world
    render plain: 'Hello, World!'
  end
end


コントローラーアクションの目的は、HTTPリクエストに応答し、適切なHTTP応答を構築することです。このアクションの場合、私たちはリクエストの詳細に完全に気を配らず、単にHello、World! 何の関係もないメッセージを構築します。ここでは、renderメソッドの呼び出しはHTTP応答を設定するためであります。上記のrenderの呼び出しでは、「Hello、World!」を引き数として渡しました。したがって、生成されたレスポンスはtext / plainのコンテンツタイプとHello!World!の本文を持ちます。


レスポンスは次のようになります。


Cache-Control:max-age=0, private, must-revalidate
Connection:Keep-Alive
Date:Tue, 23 Feb 2016 01:21:23 GMT
Etag:W/"65a8e27d8879283831b664bd8b7f0ad4"
Server:WEBrick/1.3.1 (Ruby/2.3.0/2015-12-25)
X-Content-Type-Options:nosniff
X-Frame-Options:SAMEORIGIN
X-Request-Id:24c23eec-8a37-49d9-bcaf-4f5b3f18aaaa
X-Runtime:0.021203
X-Xss-Protection:1; mode=block
Hello, World!


Rails内の応答を見ると、デバッガを使ってレスポンスを調べることができます。


render plain: 'Hello, World!'
binding.pry
### in Pry's console ###
response.body         # => "Hello, World!"
response.content_type # => "text/plain"
response.status       # => 200


これからいろいろなrenderの使い方を見ていきますが、今はrenderの仕事がコントローラのアクションの中核的な役割の1つ、つまりHTTPレスポンスの構築を達成することであることを認識すれば十分です。


さらに、上のApplicationControllerクラスはActionController :: Baseから継承しています。 レンダリングメソッド(他にも多数)は、この継承のおかげで利用可能になりました。


ビューを使ってHTMLをレンダーする


私たちのルートがaction / hello_worldへのリクエストを適切に処理することができました。アクションをHTMLをレンダーするを変更するにしましょう。


app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  def hello_world
    render inline: '<em>Hello, World!</em>'
  end
end


ここでは、plain:の代わりにinline:を使用して、レスポンスのコンテンツタイプをHTMLに設定して、レスポンスボディ文字列をレンダーに渡します。
レスポンスは次のようになります。


HTTP/1.1 200 OK
Cache-Control: max-age=0, private, must-revalidate
Connection: Keep-Alive
Content-Length: 22
Content-Type: text/html; charset=utf-8
Date: Tue, 23 Feb 2016 02:44:36 GMT
Etag: W/"1e401bc81108cb3e3dba191111bf9059"
Server: WEBrick/1.3.1 (Ruby/2.3.0/2015-12-25)
X-Content-Type-Options: nosniff
X-Frame-Options: SAMEORIGIN
X-Request-Id: a2eac900-60da-460d-9757-94d8c41c4624
X-Runtime: 0.252767
X-Xss-Protection: 1; mode=block
<em>Hello, World!</em>


上記のほとんどは、前回のリスポンスは非常に似ています。いくつかの違いがありますが、その違いの1つはレスポンス本文にemタグがラップされていることです。


Rails内のレスポンスオブジェクトも調べてみましょう:
# assuming we're inside the hello_world action above...
render inline: '<em>Hello, World!</em>'
binding.pry
### inside Pry ###
response.body         # => "<em>Hello, World!</em>"
response.content_type # => "text/html"
response.status       # => 200


ここでは、plain:の代わりにinline:を使用することで、コンテンツタイプがtext / htmlに適切に設定されていることがわかります。


今ページを更新すると、Hello、World!が表示されます。 text / htmlコンテンツタイプとHTMLレスポンス本文文字列の<em>タグのおかげで、ブラウザのイタリック体でメッセージが表示されます。


ビューを使用したコンテンツ


今のアクションによってリクエストが処理されていますが、それには間違いがあります。私たちのアクションにはコンテンツがあります。


ここでの問題は、コントローラの仕事はコンテンツを保持することではなく、それは…まあ、制御することです。


きれいに書かれたコントローラアクションは、アプリケーションの他の部分の呼び出しを調整したり、必要なときにそれらの結果をまとめたりすることを除いて、それ自体はほとんど行いません。


コントローラアクションは単にリクエスト処理のディレクターに過ぎず、アプリケーションの他の部分に他の責任を委任する必要があります。


しかし、すでに、私たちのコンテンツは、HTMLメッセージを保持しています。
これを修正するには、そのHTMLをアクションから外しましょう。


単純なビューの作成


HTMLコンテンツはビューに属しています。したがって、HTMLコンテンツを保持するビューを作成してみましょう。


<!-- app/views/application/hello_world.html -->
<html>
  <body>
    <p>Hello, World!</p>
  </body>
</html>


これは以前と同じHTMLですが、今では独自のビューファイルに保存されています。 これが重要なので、どこに配置したのか注意してください。


app/views/application/hello_world.html


すべてのビューはapp / viewsディレクトリにあります。そこから、それらを使用するコントローラとアクションに対応するディレクトリに配置されます。


ここでは、app / views / application / hello_world.htmlファイルが残っています。ビューが定義された状態で、コントローラでそれを利用しましょう:


### app/controllers/application_controller.rb ###
class ApplicationController < ActionController::Base
  def hello_world
    render 'application/hello_world'
  end
end


NOTE:ページを再ロードする前に、Railsサーバを再起動してください。


さて、レンダーはすでに数回使用されていますが、ここでは単に文字列を渡すだけ。さらに、この文字列は、作成したばかりのビューのパスと一致することに注意してください。


その結果、hello_worldアクションは、新しく定義されたapplication / hello_worldビューを使用してHTMLレスポンスボディをレンダリングします。


レンダリングをこの方法で使用することは、以下のことと同じです。


render inline: File.read('app/views/application/hello_world.html')


ビューを指し示しているのか、アクション自体のレスポンスボディを設定しているのかに関わらず、常にHTTPレスポンスボディを設定するのはレンダリングの仕事です。
上で指摘したように、コンテンツをコントローラに置いたままにしておくのは悪い習慣なので、上のようなレンダー呼び出しレンダリングビューが表示されるのは一般的です。