LoginSignup
9
8

More than 5 years have passed since last update.

Getting Started with Rails(ver4.2)の日本語訳 その1

Last updated at Posted at 2015-03-23

原文

・・・・あるじゃん

この訳文について

訳者がRailsを始めるためにとりあえず訳しながら勉強を行った結果出来上がったものです。
いろいろ残念だったり、意味が違っているところもあると思いますがもし少しでもお役に立てば幸いです。
あと全てをまとめると投稿出来なかったので分割して投稿します。。。

1.前提

このガイドはRailsを始めようとする初心者向けに書かれています。
これはRailsに関する事前知識が無くても読めるドキュメントということです。
ただし、学習を始めるにあたって前提条件としていくつかのインストールがされている必要があります:
- Ruby 1.9.3以上
- RubyGems (Ruby1.9以上であれば含まれています。RubyGemsの使い方についてはRubyGems Guidesを参照して下さい。)
- SQLite3がインストールされ動作すること

RailsはRuby上で動作するウェブアプリケーションフレームワークです。
もしあなたにRubyの開発経験が無ければ、Rails学習によってとても急な学習曲線を登ることになります。

まずはRubyを学ぶための資料がオンライン上にあるので読むことをおすすめします:
- Official Ruby Programming Language website
- reSRC's List of Free Programming Books

ただしこれらの資料は対象とするRubyのバージョンが古く1.6や1.8であり、Rails開発で使用する構文が含まれていないことに注意して下さい。

2.Railsとは?

RailsはRubyで書かれたWEBアプリケーション開発フレームワークです。
WEBアプリケーションに必要な機能を備えるため、より簡単に開発を始めることが出来ます。
他の言語やフレームワークに比べより少ないコード量で必要な機能を提供することができます。
熟練したRails開発者達は「Webアプリケーション開発を楽しもう」と報告しています。

Railsは意固地なソフトウェアです。
それは物事を実装する方法には最善の方法があり、Railsはその最善な方法で書けるように設計されています。
またある時は"最善でない"方法で書くことを阻害します。
もし貴方がRailsの書き方を学習すれば貴方の生産性を大きく上げることが出来るでしょう。
もし貴方が他の言語で学んだ癖をRails開発で使うことに固執するとそれほど大きな生産性は上げられないかもしれません。

Railsは2つの大原則に従っています

繰り返さない(DRY):
DRY is a principle of software development which states that "Every piece of knowledge must have a single, unambiguous, authoritative representation within a system." By not writing the same information over and over again, our code is more maintainable, more extensible, and less buggy.

設定より規約
Rails has opinions about the best way to do many things in a web application, and defaults to this set of conventions, rather than require that you specify every minutiae through endless configuration files.

3 新しいRailsプロジェクトを作成する

このガイドを利用するより良い方法は、実際に動かしながら各章を追っていくことです。

これからこのガイドではblogという名前のシンプルなweblogのRailsプロジェクトを作成します。
まずアプリケーションの作成を始める前にRailsがインストールされている必要があります。

サンプルコードではターミナルプロンプトをUNIXでの $ で表していますが、あなたの環境ではカスタマイズされて異なっているかもしれません。もしWindowsを利用している場合貴方は c:\source_code のような表示がされていることでしょう。

3.1 Railsのインストール

まずはコマンドラインプロンプトを開きましょう。Mac OS XではTerminal.appを、Windowsではスタートメニューのコマンドを指定して実行で、cmd.exeと入力し実行しましょう。
これからの章で$で始まる様々なコマンドはコマンドライン上で実行することを意味しています。
まずはインストールされているRubyのバージョンを確認しましょう。

Railsのインストールを素早く行うツールがプラットフォーム毎に存在しています。Windowsユーザーの場合はRailsInstallerが、Mac OS Xユーザーの場合はTokaidoがそれに当たります。

$ ruby -v
ruby 2.0.0p353

もしRubyがインストールされてない場合、ruby-lang.orgを参照し使用しているプラットフォームに合わせてインストールを行って下さい。

多くのUNIX系のOSではSQLite3を利用することが出来ます。Windowsユーザーは別途SQLite3のサイトを参照してインストールを行って下さい。インストールが正常に行われパスに追加されていることを確認しましょう。

$ sqlite3 --version

これを実行することでVersionを出力します。

次にRailsをインストールしましょう。RailsのインストールはRubyGemsで管理されている物をgem installコマンドを使って行います。

$ gem install rails

最後に全てが正しくインストールされたことを確認するために次のコマンドを実行しましょう。

$ rails --version

もしRailsが使用可能な状態になっていれば"Rails 4.2.0"と表示されます。

3.2 Blogアプリケーションを作る

Railsにはジェネレーターと呼ばれる多くのスクリプトが付属しており、
これらは貴方が開発を行う上で必要な多くのものを作成してくれます。
また、必要以上のことを自分で記述する必要が無いような、最新のRails基板を提供してくれます。
そしてそのうちの一つが新規アプリケーションジェネレーターです。

ジェネレーターを使うにはまずターミナルを開きファイル作成権限があるフォルダで次のコマンドを実行します
$ rails new blog
このコマンドでブログと呼ばれるRailsアプリケーションをblogディレクトリに作成し、必要なgem依存関係をbundle installで準備します。

すべてのコマンドラインオプションを確認するにはRailsコマンドを実行する際にrails new -hのようにします
blogアプリケーションを作成したらそのフォルダに移動しましょう:
$ cd blog
このblogディレクトリにはRailsアプリケーションを構成する自動生成されたファイルやフォルダがあります。
このチュートリアルでの多くの作業はappフォルダで行いますが、ここではRailsが作成したファイルやフォルダの基本的な要約を説明します。

File/Folder 概要
app/ アプリケーションのコントローラー、モデル、ビュー、メーラーやその他アセットが含まれる。このガイドの以降の部分はこのフォルダでの操作が中心になります。
bin/ アプリケーションを実行するためのrailsスクリプトが含まれています。必要であればセットアップやデプロイやアプリケーションの実行に必要なスクリプトを置くことが出来ます。
config/ 経路(routes)、データベースやその他のアプリケーションの設定が含まれます。詳細は Configuring Rails Applications.
config.ru アプリケーションを開始する際にRackを基礎とするサーバーが利用するRack設定ファイル
db/ データベーススキーマとデータベース移行用のファイルが含まれる
Gemfile Gemfile.lock
lib/ アプリケーション用の拡張モジュール
log/ アプリケーションログファイル
public/ そのままの状態で公開される唯一のフォルダ。静的ファイルやコンパイルされたアセットが含まれる
Rakefile コマンドラインから実行するタスクの定義がありますが、Railsの構成要素を通して定義されています。このためRakefileを変更するよりも、アプリケーションのlib/tasksディレクトリにファイルを追加することで独自のタスクを作成できます。
README.rdoc アプリケーションの説明書です。他の人にどのようなアプリケーションか、どのように使うのかをわかるように編集します
test/ ユニットテストやその他のテストを含みます。詳細はTesting Rails Applications.
tmp/ 一時ファイル(例えばキャッシュ、プロセスファイル、セッションファイル等)
vendor/ サードパーティーのコードが含まれます。典型的なRailsアプリケーションはvendored gemsをincludeします

4 Hello, Rails!

まずはじめに、画面上に簡単な文章を表示しましょう。これを行うのに必要なことはRailsアプリケーションサーバーを実行することです。

4.1 Webserverを実行する

貴方は既に汎用的な機能を持ったRailsアプリケーションを持っています。それを見るにはあなたの開発マシン上でウェブサーバーを実行する必要があります。貴方はblogディレクトリ上で次のコマンドを実行することでそれを実行することができます。
$ bin/rails server

訳注:Windowsの場合動作しないのでruby bin\rails serverのように行う必要がある?

CoffeeScriptのコンパイルとJavaScriptの圧縮にあなたのシステムにJavaScriptランタイムが利用可能であることが必要です。ExecJSがどーたらこーたら????

これによりRubyで標準のウェブサーバーであるWEBrickが起動します。ブラウザを開きhttp://localhost:3000にアクセスしアプリケーションが動作しているか見てみましょう。
Railsのデフォルト画面が表示されることでしょう。
rails_welcome.png

webサーバーを止めるにはwebサーバーを起動したターミナルウィンドウでCtrl+Cを押します。サーバーが停止したことが確認されると再びプロンプトが表示されます。(要は$とかがてきて次のコマンドを入力可能な状態になる)
開発モードで起動した場合Railsは殆どの場合再起動を必要としません。変更や作成したファイルは自動的にサーバーに読み込まれます。

"Welcome aboard"ページは新規のRailsアプリケーションのスモークテストです。
あなたの環境設定等を確認するのに十分な情報が含まれています。About your application's environmentを選択することでアプリケーションの環境変数を確認することも出来ます。

4.2 Railsで"Hello"と言おう

Railsに"Hello"と言うには、小さなコントローラーとビューを作成する必要があります。

コントローラーの目的はアプリケーションへのリクエストを受けることです。Routingはどのコントローラーがリクエストを受けるか決定します。多くの場合、アクション毎に異なるルーティングやコントローラーが用意される。アクションの目的は必要な情報を集めそれをビューに渡すことです。

ビューの目的はそれらの情報を人が読めるように表示することです。
重要な区別として情報を集めるのはコントローラーでありビューではありません(?)

An important distinction to make is that it is the controller, not the view, where information is collected.
ビューは単に表示だけを行うべきです。

新しいコントローラーを作成するには、"controller"ジェネレーターに作成したいコントローラ名(welcome)
とアクション名(index)を伝えます。それは次のようになります
$ bin/rails generate controller welcome index
RailsはいくつかのファイルとRouteを作成します。

create  app/controllers/welcome_controller.rb
 route  get 'welcome/index'
invoke  erb
create    app/views/welcome
create    app/views/welcome/index.html.erb
invoke  test_unit
create    test/controllers/welcome_controller_test.rb
invoke  helper
create    app/helpers/welcome_helper.rb
invoke  assets
invoke    coffee
create      app/assets/javascripts/welcome.js.coffee
invoke    scss
create      app/assets/stylesheets/welcome.css.scss

この中で特に重要なのはもちろんコントローラー(場所:app/controllers/welcome_controller.rb)とビュー(場所:app/views/welcome/index.html.erb)

app/views/welcome/index.html.erbをテキストエディタで開いてみましょう。
そして全てのコードを削除し、次の一行を追加します
<h1>Hello, Rails!</h1>

4.3 アプリケーションのホームページを設定する

今ほど私達が作成したコントローラーとビューをRailsに伝え"Hello, Rails!"と表示させたいと思います。
rootURL(logcalhost:3000)にアクセスされた場合これを表示するようにします。今は"Welcome aboard"がそこに表示されています。

それではRailsにホームページの実際の場所を教えます。
config/routes.rbをエディターで開いて下さい。

config/routes.rb
Rails.application.routes.draw do
  get 'welcome/index'

  # The priority is based upon order of creation:
  # first created -> highest priority.
  #
  # You can have the root of your site routed with "root"
  # root 'welcome#index'
  #
  # ...

このファイルはRailsが外部からのリクエストを受けた時にどのコントローラーとアクションに渡すかを保持する特別なDSL(domain-specific-language)です。
このファイルはコメントでいくつかのサンプルルートを持っており、その中の一つにサイトのルートへのリクエストを特定のコントローラーとアクションに渡すにはどのようにすればよいかも含まれている。
rootで始まる行を探しそのコメントを外す。これは次のようになります
root welcome#index
root 'welcome#index' はRailsに アプリケーションルートはwelcomeコントローラーのindexアクションであることを表し,
get 'welcome/index'はhttp://localhost:3000/welcome/indexをwelcomeコントローラーのindexアクションに渡すことを表します。この設定はコントローラージェネレーターを実行した時(rails generate contoller welcome index)に作成されました。

もしコントローラーを作成するときにサーバーを止めていた場合再度実行(rails server)し、http://localhost:3000をブラウザで開いてみましょう。
あなたがapp/views/welome/index.html.erbに書いた”Hello Rails!”がレンダリングされて正しく表示されて、ルーティングの設定が正しくされたことを確認出来るでしょう。

ルーティングについてのさらに詳しい情報はRails Routing from the Outside In.にあります

5 起動と動作

ここまででコントローラーとアクションとビューを作成しましたが、ここでは更に物質(substance)を作成してみましょう。

Blogアプリケーションに新しくresourceを作成します。resourceとはコレクションと同じような意味で様々なオブジェクト、例えば物や人や動物等です。リソースのアイテムを作る、読み取る、更新する、削除する動作を行うことができこれはCRUDと呼ばれます。

あなたはリソースを使うことを宣言すればRailsの管理するリソースに対して標準的なRESTのメソッドを使うことができます。
貴方がする必要があるのは記事(articles)というリソースをconfig/routes.rbに追加することです。

config/routes.rb
Rails.application.routes.draw do
  resources :articles

  root 'welcome#index'
end

rake routesを実行すると定義された全ての標準的なRESTfulなアクションを確認することができます。
Prefix列(とその他の列)は後にわかるようになりますが、ここでは単数形(article)で作成されていることに注目して下さい。

$ bin/rake routes
      Prefix Verb   URI Pattern                  Controller#Action
    articles GET    /articles(.:format)          articles#index
             POST   /articles(.:format)          articles#create
 new_article GET    /articles/new(.:format)      articles#new
edit_article GET    /articles/:id/edit(.:format) articles#edit
     article GET    /articles/:id(.:format)      articles#show
             PATCH  /articles/:id(.:format)      articles#update
             PUT    /articles/:id(.:format)      articles#update
             DELETE /articles/:id(.:format)      articles#destroy
        root GET    /                            welcome#index

次のセクションでは新しい記事を作成しアプリケーションでそれを表示出来るようにします。
これは"CRUD"の"C"と"R"(creation:作成とreading:読み取り)です。
その為に次のようなフォームを作ります。これはごく基本的な機能しか備えていませんがここではそれで十分です。

new_article.png

後の章で綺麗に整え見栄えのするものにします。

5.1 Laying down the ground work

まずはじめに新しい記事を作成する場所を作る必要があります。これには/articles/newというとても良い場所があります。
ここへの/articles/newというrouteは既に定義されています。さっそくhttp://localhost:3000/articles/newを開くと次のようなRouting Errorが表示されます。

routing_error_no_controller.png

このエラーはリクエストに対応したルートに必要なコントローラーが定義されていないために起きています。
この問題の解決方法は簡単でArticlesControllerと呼ばれるコントローラーを作成することです。
それを行うには次のコマンドを実行してみましょう

$ bin/rails g controller articles

新たに作成されたapp/controllers/artcles_controller.rbを開くと空のコントローラーを見ることができます。

app/controllers/artcles_controller.rb
class ArticlesController < ApplicationController
end

コントローラーは単にApplicationControllerを継承したクラスです。
この中にあなたのメソッドを定義するとそれはこのコントローラーのアクションになります。
記事のCRUD操作を行うアクションを定義していきます?

Rubyにはpublic, private, protectedがありますが、
アクションはコントローラに定義されたpublicメソッドのみです。
これについての詳細はProgramming Rubyを確認して下さい。
訳注:これは各アクセス修飾子の事を指している?

今、更新を行うとhttp://localhost:3000/articles/new新しいエラーが表示されます。

unknown_action_new_for_articles.png

このエラーは先ほど作成したArticlesControllerにnewアクションを見つけることが出来なかったことを示しています。
これはコントローラーを作成するときに作成したいアクション名を支持しなかったため、Railsが標準の動作で空のControllerを生成したためです。

コントローラーに手動でアクションを定義しましょう。あなたがすることはコントローラにnewメソッドを作成することだけです。
app/controllers/articles_controller.rbを開きArticlesControllerクラスにnewメソッドを定義しましょう。
コントローラーは次のようになるでしょう。

class ArticlesController < ApplicationController
  def new
  end
end

AtriclesControllerにメソッドを定義したら更新http://localhost:3000/articles/newしてみましょう。新たなエラーが表示されます

template_is_missing_articles_new.png

表示されたエラーはplain actionsは情報を表示するためのViewを持っていることを期待されているためです。
ビューが利用できないためRailsはエラーを出力しました。

上のエラー画像では、下の行は切りました。切り捨てられた部分も含む完全なメッセージを見てみましょう

Missing template articles/new, application/new with {locale:[:en], formats:[:html], handlers:[:erb, :builder, :coffee]}. Searched in: * "/path/to/blog/app/views"

非常に長いメッセージですがそれぞれの各部分がなにをするのか見てみましょう。?

最初の部分はテンプレートが見つからなかったと示されています。このケースではarticles/newというテンプレートがなかったということです。
Railsは最初にこのテンプレートを見つけます。見つからなかった場合は次にapplication/newを読み取ろうとします。なぜならArticlesControllerはApplicationControllerを継承しているからです。

メッセージの次の部分はハッシュです。:localeキーは検索されたテンプレートの言語はenで有ることを示しています。初期設定は英語(en)のです。
次のキーは:formatsですが、レスポンスにどのようなフォーマットを提供するかを示しています。初期設定は:htmlでこのためRailsはHTMLテンプレートを探します。
最後のキーは:handlersでこれはテンプレートをレンダリングするために利用することが出来るハンドラーが表示されている。
:erbは最も一般的に使われているHTMLテンプレートで、:builderはXMLテンプレート、:coffeeはCoffeeScriptからJavascriptを作成するためのテンプレートです。

最後の部分はRailsはどこでテンプレートを探したかを示しています。
テンプレートは標準的なRailsアプリケーションでは同一の場所に保持されているが、より複雑なアプリケーションの場合複数の場所に保存することも出来ます。

この問題を解決するための最も簡単なtemlateはapp/views/articles/new.html.erbにテンプレートを作成することです。
ファイル名についている拡張子は:
最初の拡張子はテンプレートのフォーマットを表し、2番目の拡張子はhandlerを表します。
Railsはアプリケーションのapp/viewsの中のarticles/newから呼び出すテンプレートを探します。
このテンプレートはフォーマットはhtmlで無ければならずhandlerはerb builder cofeeのいずれかである必要がある。
ここでは新しいHTMLフォームを作成したいのでERBを使用することになります。
従ってアプリケーションのapp/viewsの中にarticles/new.html.erbを配置することがわかります。

それでは、app/views/articles/new.html.erbを作成し次のような内容を書き込みましょう

<h1>New Article</h1>

http://localhost:3000/articles/newを更新するとページタイトルが表示されます。
これでルート・コントローラー・アクションそしてビューが調和し動作しました!
記事を新規作成するフォームを作成する準備ができました。

5.2 初めてのフォーム

テンプレートにフォームを作成するには、フォームビルダーを利用できます。
一般的なフォームビルダーはRailsが持つヘルパーメソッドでform_forです。
このメソッドを使うにはapp/views/articles/new.html.erbで次のようなコードを書きます

<%= form_for :article do |f| %>
  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>
  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>
  <p>
    <%= f.submit %>
  </p>
<% end %>

ページを更新するとサンプルと全く同じフォームが表示されるでしょう。Railsでフォームを作成することはとても簡単です。

先ほどform_forを呼んだ時にこのフォームのためのオブジェクトを識別する物を渡しました。
この場合、それは:articleシンボルです。この呼び出しでform_forヘルパーにこのフォームは何なのかを教えている。
このメソッドの中の部分はFormBuilderオブジェクトをfとして提供される。
fは2つのラベルと2つのテキストフィールドでそれぞれ1つづつのペアは記事のタイトルと本文を表します。
最後にsubmitを呼び出しこのフォームを送信するためのsubmitボタンを作成します。

しかしこのフォームには一つ問題があります。
それはページのHTMLのソースコードを確認するとaction属性が/article/newを指していることです。
この問題 なぜなら このルートは今あなたが見ているページに行く。このURLは記事の新規作成のためのURLとしてだけ使いたい。

別のどこかに飛ばすために、違うURLをフォームにセットする必要がある。
これはform_forに:urlオプションを与えることでとても簡単に解決することが出来ます。
Raiilsでは一般的にnewフォームが送信するのは"create"アクションが利用されますので、フォームをそのように変更してみましょう。

app/view/articles/new.html.erbのform_forを次のように変更してみましょう
<%= form_for :article, url: articles_path do |f| %>

サンプルでは:urlオプションにarticle_pathヘルパーを渡しています。
これがどのような意味があるかはまず先ほど確認したルート一覧をもう一度見てみましょう

$ bin/rake routes
      Prefix Verb   URI Pattern                  Controller#Action
    articles GET    /articles(.:format)          articles#index
             POST   /articles(.:format)          articles#create
 new_article GET    /articles/new(.:format)      articles#new
edit_article GET    /articles/:id/edit(.:format) articles#edit
     article GET    /articles/:id(.:format)      articles#show
             PATCH  /articles/:id(.:format)      articles#update
             PUT    /articles/:id(.:format)      articles#update
             DELETE /articles/:id(.:format)      articles#destroy
        root GET    /                            welcome#index

article_pathヘルパーはPrefixがarticlesのルートのURI PatternをRailsに伝え、またformは(標準で)POSTでそのルートにリクエストを送ります。
これにより現在のコントローラであるArticlesControllerのcreateアクションと関連付けられます。
これでフォームとそれに関連するルートが定義され、新しい記事を作成する事ができるようになりましたのでフォームの項目を埋めて次に進みましょう。
フォームのSubmitボタンを押してみましょう。このようなエラーが表示されるはずです

unknown_action_create_for_articles.png

次はおれを動くようにするためにArticlesControllerにcreateアクションを作る必要があります。

5.3 記事を作成する

”Unknown action”を表示しないようにするには、ArticlesController(app/controllers/articles_controller.rb)にcreateアクションを定義することです。
newアクションの下に次に示すように定義しましょう。

app/controllers/articles_controller.rb
class ArticlesController < ApplicationController
  def new
  end

  def create
  end
end

もう一度submitを行ってみると、次のような別のエラー(a template is missing)が表示されます。
これは問題ありませんので、ここでは放っておきましょう。
では、createアクションでデータベースに記事の保存を行うよう続きを作っていきましょう。。

def create
  render plain: params[:article].inspect
end

これはrenderメソッドにkeyがplainで値がparams[:article].inspectなシンプルなハッシュを渡している。
paramsメソッドはフォームから送られてきたパラメーターを提供するオブジェクトです。
paramsメソッドはActiveSupport::HashWithIndifferentAccessを返し、パラメータ名の文字やシンボルをキーとしてアクセスすることが出来ます。
?今の状況では、含まれるパラメータはformから送られてきたもののみになります。?

これからparamsメソッドはとても頻繁に使うことになるので、paramsメソッドについてしっかり確認しておきましょう。
次のURLについて考えてみましょうhttp://www.example.com/?username=dhh&email=dhh@email.com
このURLの場合params[:username]は"dhh"が、params[:email]は"dhh@email.com"が格納されています。

もう一度フォームをsubmitしてみましょう。もうテンプレートエラーはなくなっているでしょう。
代わりに次のような何かが表示されていると思います
{"title"=>"First article!", "text"=>"This is my first article."}
このアクションはformから飛んできた記事のパラメーターが表示されています。
ただし、これでは役に立ちません。単にパラメータを見れただけで何も行われていないからです。

5.4 記事モデルを作成する

RailsではModelsは単数形の名前をつけ、それに対応するテーブルは複数形になります。
Railsはモデルを作成するジェネレータを提供しており、多くの開発者はモデルを作成するときにこれを利用します。
新しいモデルを作成するために、次のコマンドをターミナルで実行してみましょう
$ bin/rails generate model Article title:string text:text
このコマンドを実行すると、RailsにArticleモデルでstring型のtitle属性とtext型のtext属性を欲しいと伝えた(ことになる)。
これらの属性は自動的にarticleテーブルに追加されArticleモデルにもマッピングされる。

Railsは要求に対していくつかのファイルを作成します。その中で今のところ見るべきなのはapp/models/article.rbとdb/migrate/YYYYMMDDXXXXX_create_articles.rb(少し異なると思いますがあなたの環境で読み替えて下さい)です。
後者はデータベースの構造を作るもので次で見ていきます。

Active Recordは自動でtableのcolumnとmodelの属性をマッピングします。ActiveRecordが自動的に行うことであなたはRailsのモデルの中で属性を定義する必要がありません。

5.5 マイグレーションの実行

私達は、モデルを作成した際にdb/migrateディレクトリにマイグレーションファイルを作成したのを見てきました。
マイグレーションファイルは、シンプルにデータベースの作成と修正を行えるようデザインされたRubyのクラスです。
RailsでのマイグレーションはRakeコマンドを利用して行います。また、マイグレーションを行った後に必要ならばそれを取り消すこともできます。
なぜならマイグレーションファイルは名前にタイムスタンプを含んでおり、処理を行った順番を管理しているからです。

先ほど作成したdb/migrate/XXXXXXX_create_article.rbを見てみましょう。

class CreateArticles < ActiveRecord::Migration
  def change
    create_table :articles do |t|
      t.string :title
      t.text :text

      t.timestamps null: false
    end
  end
end

このマイグレーションコードは、マイグレーションを実行した時に呼び出されるchangeというメソッドを作成しています。
またこのメソッドで定義された動作は可逆性があります。
これはRailsはこのマイグレーションでの変更をどうやれば元に戻せるかをわかっているということです。
実際にもとに戻す方法は後で説明します。

このマイグレーションを実行すると、stringとtextのカラムを持ったarticlesテーブルが作成出来ます。
また、記事の作成と更新時間を追跡できるように2つのtimestampフィールドを作成します。

さらに細かな説明はRails Database Migrations.を参照して下さい。

それでは、実際にRakeコマンドを利用してマイグレーションを実行してみましょう。

$ bin/rake db:migrate

マイグレーションコマンドが実行されるとArticlestableが作成されたことが通知されます。

==  CreateArticles: migrating ==================================================
-- create_table(:articles)
   -> 0.0019s
==  CreateArticles: migrated (0.0020s) =========================================

なぜなら初期設定では開発環境で実行しているからです。(なぜなら?)
このコマンドはconfig/database.ymlで定義されたdevelopセクションで定義されたデータベースに反映されています。
もし他の環境やproduction環境でマイグレーションを実行したい場合は、commandで明示的に指定する必要が有ります。
rake db:migrate RAILS_ENV=production

5.6 コントローラでデータを保存する

ArticleControllerの作成に戻りましょう。
createアクションを新たに作成したArticleモデルを使ってでデータベースに保存するように変更してみましょう。
app/controllers/articles_controller.rbを開createアクションを次のように変更しましょう。

def create
  @article = Article.new(params[:article])

  @article.save
  redirect_to @article
end

全てのRailsのモデルは自動的にマッピングされたデータベース列を、与えられた引数のそれぞれの属性で初期化することができます。
最初の行はそれを利用してparams[:article]のそれぞれの値でArticleモデルの初期化を行っています。
その後、@article.saveを実行しデータベースに保存を行っています。
最後にshowアクションにリダイレクトしています。このアクションは後で定義します。

あなたはこのガイドのarticleは小文字であったのに、Article.newが大文字なのか不思議に思うかもしれません。
ここでは/models/article.rbで定義されたRubyのクラスであるArticleを参照しているためです。
Rubyではクラス名は大文字で始めます。

 

あとで説明しますが、@articles.saveは保存の成否をboolean値で返却します。

それではhttp://localhost:3000/articles/newで記事を作成することが大体できるようになったので試してみましょう。
あなたは次のようなエラーを見ることになるでしょう。

forbidden_attributes_for_new_article.png

Railsには貴方がセキュアなアプリケーションを書くためのセキュリティ機能があり、その機能によりエラーが出ています。
その機能はstrong parametersと呼ばれる機能で、モデルの初期化時に読み出しを許可するパラメータ名を明示的に指定する必要があります。

なぜこのような面倒な指定が必要なのでしょうか?自動的にコントローラーのパラメーターをモデルにセットしたほうが楽ができるでしょう。
しかし、その利便性を悪用することも出来るでしょう。
例えばもし、制約に違反するようなパラメーターや入力を受け付けないはずのパラメータが付与されて、新しい記事としてリクエストが来た場合はどうなるでしょうか?
それらの不正な入力は、あなたのモデルに正常なものと一緒に紛れ込みあなたのアプリケーションを壊していくでしょう。

これを防ぐためホワイトリスト方式で不正なモデルへの割り当てを防ぐ機能がコントローラーにあります。
createアクションではtitleとtextパラメータを利用したいのでこの2つを許可します。
これにはrequireとpermitという構文を利用します。それではcreateアクションの一行目を書き換えてみましょう

@article = Article.new(params.require(:article).permit(:title, :text))

この許可するコードは同じコントローラーの他の部分(例えば作成時・更新時)でも使うことになるのでメソッド化しましょう。
またこのメソッドはこのコントローラー以外から呼ばれることがないようにprivateにしておきましょう。
この変更を加えると次のようになります。

def create
  @article = Article.new(article_params)

  @article.save
  redirect_to @article
end

private
  def article_params
    params.require(:article).permit(:title, :text)
  end

5.7 記事を表示しよう

もし記事登録フォームからもう一度登録すると'not finding the show action'を文句を言われるでしょう。
これでは困りますので、次に進む前にshowアクションを作りましょう。

rake routesコマンドで既に見てきたようにshowアクションは次のように定義されています。

article GET    /articles/:id(.:format)      articles#show

:idという構文はRailsにパスのその部分は:idというパラメーターであると教えています。
我々のケースではそれは記事IDに当たります。

それでは前にもやったようにapp/controllers/articles_controller.rbにshowアクションを追加しそれのViewも作成しましょう。

例題としてコントローラーにしばしば登場する標準的なCRUDアクションの順番はindex, show, edit, create, update そしてdestroyです。
あなたは特にその定義する順番を守る必要はありませんが、それらはpublicメソッドでないといけないことを覚えておいて下さい。
このガイドでも既に述べたようにプライベートなメソッドより前に定義しておく必要があります。

それを踏まえてshowアクションを定義してみましょう

class ArticlesController < ApplicationController
  def show
    @article = Article.find(params[:id])
  end

  def new
  end
   # snipped for brevity

ここで見るべきところは、リクエストから取得したparams[:id]をArticle.findを使って記事を探しています。
またインスタンス変数(@で始める変数)に記事オブジェクトを保持しています。
なぜこのようにしたかというと、Railsは全てのインスタンス変数をViewに渡すからです。

次にapp/views/articles/show.html.erbを作成しましょう。

<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>

この変更により、ついに記事の新規作成を最後まで行うことが出来ます。
http://localhost:3000/articles/newで試してみましょう。

show_action_for_articles.png

5.8 全ての記事をリスト化する

さらに記事を一覧表示する機能が必要なのでそれを作成しましょう。
そのためのルートはrake routesの出力の次の部分です

articles GET    /articles(.:format)          articles#index

ルートに対応するindexアクションをArticleController(app/controllers/article_controller.rb)に追加しましょう。
indexアクションを書くときはコントローラーの最初のメソッドとして書くのが恒例です。それでは書いてみましょう

class ArticlesController < ApplicationController
  def index
    @articles = Article.all
  end

  def show
    @article = Article.find(params[:id])
  end

  def new
  end

  # snipped for brevity

そしてViewを追加しましょう。場所はapp/views/articles/index.html.erbです

<h1>Listing articles</h1>

<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
  </tr>

  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.text %></td>
    </tr>
  <% end %>
</table>

では http://localhost:3000/articlesにアクセスして全ての記事が表示されるか確認してみましょう。

5.9 リンクを貼る

ここまでで記事を作る(create)、見る(show)、一覧表示する(list)ことが出来るようになりました。
ではそれらのページを移動するリンクを追加しましょう。

app/views/welcome/index.html.erbを開き次のように修正してみましょう

<h1>Hello, Rails!</h1>
<%= link_to 'My Blog', controller: 'articles' %>

link_toメソッドはRailsのViewヘルパーの一つです。これは表示する文字と飛ばす場所を指定するとハイパーリンクを作成します。
この場合作成されるパスはarticlesになります。

それでは他のビューにも追加しましょう。まずapp/views/articles/index.html.erbの

タグの上に"NewArticle"というリンクを追加しましょう。
<%= link_to 'New article', new_article_path %>

このリンクで新規記事登録フォームへ移動し新しい記事を作ることが出来ます。

更にapp/views/articles/new.html.erbに別のリンクを作りましょう。indexに戻るリンクをフォームの下に作りましょう

<%= form_for :article, url: articles_path do |f| %>
  ...
<% end %>

<%= link_to 'Back', articles_path %>

最後にapp/views/articles/show.html.erbにindexアクションに戻るリンクを先ほどと同様追加し、
記事を見た後に記事一覧画面にもう一度戻れるようにしましょう。

<p>
  <strong>Title:</strong>
  <%= @article.title %>
</p>

<p>
  <strong>Text:</strong>
  <%= @article.text %>
</p>

<%= link_to 'Back', articles_path %>

もしリンクを貼りたいアクションが、遷移元と同じコントローラーの場合、:controllerオプションを指定する必要はありません。
Railsは指定がない場合に現在のコントローラーへのリンクとして動きます。

 

開発モード(特に指定していなければ標準でこのモードです)では、Railsはブラウザからのリクエスト毎にアプリケーションをリロードします。
何か変更を加えた時に再起動をする必要はありません。

5.10 バリデーションを追加しよう

モデルファイル(app/models/articles.rb)は次のようなとても単純な物です

class Article < ActiveRecord::Base
end

これには多くの機能はありませんが、ArticleクラスはActiveRecord::Baseを継承している点に注意して下さい。
ActiveRecordはモデルクラスに標準的なデータベースでのCRUD(Create,ReadUpdate,Deatroy)処理、データのバリデーション、洗礼された検索、モデルのリレーションシップ等の多くの機能を無償で提供します。

Railsにはモデルに送られたデータをバリデートすることを助けるメソッドが用意されています。
app/models/articles.rbを開いて次のように編集してみましょう。

class Article < ActiveRecord::Base
  validates :title, presence: true,
                    length: { minimum: 5 }
end

この変更は全ての記事は5文字以上のタイトルを持つことを保証するものです。
このようにRailsはモデルに存在・一意・フォーマット・関連オブジェクトの存在等の様々な条件でのバリデートを行うことが出来ます。
バリデーションについては詳しくはActive RecordValidationを参照して下さい。

それではタイトルが五文字に満たない無効な記事を@article.saveで保存しようとするとどうなるでしょうか?
この場合、saveメソッドからfalseが返却されます。
コントローラー(app/controller/articles_controller.rb)を再度確認してみましょう。
createActionの中で@article.saveの成否をチェックしていないことに気がつくでしょう。
もし@article.saveがfalseを返す場合、ユーザーを記事登録フォームに戻す必要があります。
ではnewとcreateアクションを変更してそれを実現しましょう。

def new
  @article = Article.new
end

def create
  @article = Article.new(article_params)

  if @article.save
    redirect_to @article
  else
    render 'new'
  end
end

private
  def article_params
    params.require(:article).permit(:title, :text)
  end

newアクションはインスタンス変数@articleに新しい記事インスタンスを作成し、代入しています。
createアクションの中で@article.saveがfalseを返した場合redirect_toの代わりにrenderを仕様していることに注意して下さい。
renderメソッドはnewテンプレートでレンダリングすることを指示しており、この時@articleの値はcreateの物がそのまま使われます。

入力値が@articleに入ってるのでそれが使われるという意味・・・のはず(だいぶ意訳)。
このレンダリングは入力値の送信と同じリクエストで行われますが、一方でredirect_toはブラウザに新たなリクエストを行うように要求します。

http://localhost:3000/articles/newをリロードし、タイトルを入力せずに記事を保存しようとしてみましょう。
Railsはあなたの要求を受けて記事登録画面に戻しますがこれはあまり便利ではありません。
あなたはユーザーに対して何がダメだったのかを伝える必要があります。
ではapp/views/articles/new.html.erbを編集してエラーメッセージを確認出来るようにしましょう。

<%= form_for :article, url: articles_path do |f| %>

  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@article.errors.count, "error") %> prohibited
        this article from being saved:
      </h2>
      <ul>
        <% @article.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>

<% end %>

<%= link_to 'Back', articles_path %>

見慣れないいくつかの物があるので順に見て行きましょう。
まずエラーがあるのかどうかを@articles.errors.any?を使って調べ、もしエラーがあった場合は@article.errors.full_messagesを使って全てのエラーを表示しています。

pluralizeはRailsのヘルパーの一つで引数に数と文字列を渡しています。もし数が2以上の場合、文字列を自動的に複数形にしてくれます。

また、コントローラーのnewアクションで@article = Article.newを行ったていましたが、
もし行わなかった場合Viewで@articleがnilとなってしまい@article.errors.any?を呼んだ時にエラーが出てしまうのです。

Railsは自動でエラーメッセージを<div class="field_with_errors">で囲います。
このため対応したCSSを定義することによって出力を定義することができます。

これで新規記事登録フォームからタイトルがない記事を登録しようとすると、適切なエラーメッセージが表示されるようになりました。

form_with_errors.png

5.11 記事を更新しよう

ここまででCRUDのうち"CR"を作ることができました。では次にUに当たる更新を作っていきましょう、

まず初めに、ArticlesControllerにeditアクションを追加しましょう。editアクションは一般的にnewとcreateの間に次のように作成します。

def new
  @article = Article.new
end

def edit
  @article = Article.find(params[:id])
end

def create
  @article = Article.new(article_params)

  if @article.save
    redirect_to @article
  else
    render 'new'
  end
end

Viewは新規記事作成フォームで作ったものと大体同じようなものです。
app/views/articles/edit.html.erbを次のように作りましょう

<h1>Editing article</h1>

<%= form_for :article, url: article_path(@article), method: :patch do |f| %>

  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@article.errors.count, "error") %> prohibited
        this article from being saved:
      </h2>
      <ul>
        <% @article.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <p>
    <%= f.label :title %><br>
  NaN. 
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>

<% end %>

<%= link_to 'Back', articles_path %>

今回はフォームの送り先にupdateアクションが利用されます。これはまだ定義していませんがすぐ後に作ります。

RESTプロトコルのupdateはHTTPのPATCHを利用して行いますので、
method: :patchオプションを使用してRailsにこのフォームはHTTPメソッドのPATCHで送るように指示しています。

The first parameter of form_for can be an object, say, @article which would cause the helper to fill in the form with the fields of the object. Passing in a symbol (:article) with the same name as the instance variable (@article) also automagically leads to the same behavior. This is what is happening here. More details can be found in form_for documentation.

あまりにも自信がないので英文のままとりあえずおいておく
form_forの最初の引数は@articleでもいいんだけども:articleにしとけば同じ名前のインスタンス変数(@article)を自動でみつけてやってくれるよ。
何が起こっているか詳しくはform_forのドキュメント見てね。

次にapp/controllers/articles_controller.rbにupdateアクションを作成しましょう。createアクションとprivateメソッドの間に足しましょう。

def create
  @article = Article.new(article_params)

  if @article.save
    redirect_to @article
  else
    render 'new'
  end
end

def update
  @article = Article.find(params[:id])

  if @article.update(article_params)
    redirect_to @article
  else
    render 'edit'
  end
end

private
  def article_params
    params.require(:article).permit(:title, :text)
  end

The new method, update, is used when you want to update a record that already exists, and it accepts a hash containing the attributes that you want to update

モデルのupdateメソッドは既に存在するレコードを更新したいときに利用し、モデルの持つハッシュ属性を使って更新処理を行います。

新規作成の時と同じように、もしエラーがあり更新出来なかった場合はユーザーにエラーメッセージを表示しフォーム画面に戻します。

updateを行うときに全ての属性を渡す必要はありません。例えば@article.update(title: 'A new title')のように呼び出した場合、
Railsはタイトル属性だけを更新し、他のレコードはそのままにしておきます。

最後に、記事一覧画面に編集アクションへのリンクを追加したいと思います。
app/views/articles/index.html.erbの"Show"リンクの隣に次のように追加しましょう。

<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
    <th colspan="2"></th>
  </tr>

  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.text %></td>
      <td><%= link_to 'Show', article_path(article) %></td>
      <td><%= link_to 'Edit', edit_article_path(article) %></td>
    </tr>
  <% end %>
</table>

さらにもう一つ、記事のページ(app/views/articles/show.html.erb)"Edit"リンクを追加しましょう。
テンプレートの最下部に次のコードを追加しましょう。

...

<%= link_to 'Back', articles_path %> |
<%= link_to 'Edit', edit_article_path(@article) %>

これでアプリはどのようになったか確認してみましょう。

index_action_with_edit_link.png

5.12 partialsを利用してViewの重複を整理しよう

編集ページは新規ページは非常に似たページになっており、実際にそれらは同じコードでフォームを表示しています。
そこでview partislを使って重複した部分を削除しましょう。
慣例によりpartialファイルはファイル名をアンダースコア[_]で始めます。

partialsの概要はLayouts and Rendering in Rails に記載されています。

それでは新しくapp/views/articles/_form.html.erbを作成し、次のようなコードを書きましょう。

<%= form_for @article do |f| %>

  <% if @article.errors.any? %>
    <div id="error_explanation">
      <h2>
        <%= pluralize(@article.errors.count, "error") %> prohibited
        this article from being saved:
      </h2>
      <ul>
        <% @article.errors.full_messages.each do |msg| %>
          <li><%= msg %></li>
        <% end %>
      </ul>
    </div>
  <% end %>

  <p>
    <%= f.label :title %><br>
    <%= f.text_field :title %>
  </p>

  <p>
    <%= f.label :text %><br>
    <%= f.text_area :text %>
  </p>

  <p>
    <%= f.submit %>
  </p>

<% end %>

これは記事作成画面と編集画面の同じ定義がされている部分をform_forの引数の部分を除きそのまま抜き出した物です。
form_forは今までよりもずいぶん短くなりました。(オプションの指定がありませんね。)
シンプルに定義されたform_forは標準で@articleのRESTでの標準的な経路を提供します。
RailsがRESTのどれを利用するかを自動的に推測してくれるのです。
更に詳しい情報はResource-oriented styleを参照して下さい。

それではapp/views/articles/new.html.erbを先ほど作ったpartialを利用して書き換えてみましょう。

<h1>New article</h1>

<%= render 'form' %>

<%= link_to 'Back', articles_path %>

同じようにapp/views/articles/edit.html.erbも書き換えましょう。

<h1>Edit article</h1>

<%= render 'form' %>

<%= link_to 'Back', articles_path %>

5.13 記事の削除を行う

それでは最後にCRUDの「D」に当たる削除処理を作りましょう。
RESTの慣習に従うためまずはDELETEのルートをrake routesで調べましょう。

DELETE /articles/:id(.:format) articles#destroy

これによると削除処理はHTTPのDELETEのメソッドを利用してarticlesコントローラーのdestroyメソッドで行うようです。
もし仮に削除のルートが典型的なHTTPのGETメソッドで実装された場合次のような悪意のあるURLを作成することが出来てしまいます。

<a href='http://example.com/articles/1/destroy'>かわいいネコの画像だよ!</a>

このためDELETEメソッドを利用してリソースの削除処理を行うようになっています。
削除処理はまだ定義していませんがapp/controllers/articles_controller.rbのdestroyメソッドで行います。
それではdestroyメソッドを他のCRUDアクションと同じようにpublicメソッドでprivate(又はprotected)の上に次のように定義しましょう。

def destroy
  @article = Article.find(params[:id])
  @article.destroy

  redirect_to articles_path
end

この変更を加えたArticlesControllerの全文は次のようになっていると思います。

class ArticlesController < ApplicationController
  def index
    @articles = Article.all
  end

  def show
    @article = Article.find(params[:id])
  end

  def new
    @article = Article.new
  end

  def edit
    @article = Article.find(params[:id])
  end

  def create
    @article = Article.new(article_params)

    if @article.save
      redirect_to @article
    else
      render 'new'
    end
  end

  def update
    @article = Article.find(params[:id])

    if @article.update(article_params)
      redirect_to @article
    else
      render 'edit'
    end
  end

  def destroy
    @article = Article.find(params[:id])
    @article.destroy

    redirect_to articles_path
  end

  private
    def article_params
      params.require(:article).permit(:title, :text)
    end
end

データベースから削除したくなった場合ActiveRecordオブジェクトのdestroyを呼ぶことで削除を行うことが出来ます。
ここではindexアクションにリダイレクトされるため、Viewを追加する必要がないことに注意して下さい。

最後に削除リンクをindexアクションのテンプレート(app/views/articles/index.html.erb)に追加すると共に、
全ての内容を次に記載します。

<h1>Listing Articles</h1>
<%= link_to 'New article', new_article_path %>
<table>
  <tr>
    <th>Title</th>
    <th>Text</th>
    <th colspan="3"></th>
  </tr>

  <% @articles.each do |article| %>
    <tr>
      <td><%= article.title %></td>
      <td><%= article.text %></td>
      <td><%= link_to 'Show', article_path(article) %></td>
      <td><%= link_to 'Edit', edit_article_path(article) %></td>
      <td><%= link_to 'Destroy', article_path(article),
              method: :delete,
              data: { confirm: 'Are you sure?' } %></td>
    </tr>
  <% end %>
</table>

ここで使ったlink_toは今まで使ってきたものと少し異なっています。
第二引数としてルート名を渡してから、更にオプションで他の引数をセットしています。
:methodと:'data-confirm'はHTML5の属性として出力されます。
これによりリンクをクリックした時に、Railsはまず確認ダイアログを表示しユーザーに確認を求めた後削除処理を行うようになります。

この処理はアプリケーションを生成した時に、自動であなたのアプリケーションのレイアウト(app/views/layouts/application.html.erb)に組み込まれているJavascript(jquery_ujs)を介して行われています。
このファイルが無いと確認ダイアログボックスは表示されません。

confirm_dialog.png

おめでとうございます!これで記事の作成・表示・一覧・更新・削除を行えるようになりました!

Railsではルーティングを一つずつ手作りするよりもresourcesオブジェクトを使用してルーティングを設定することが推奨されています。。
さらなるルーティングに関する情報はRails Routing from the Outside Inを参照して下さい。

 続きます

http://qiita.com/milu0_0_0/items/157303ba607bb7f3b2d6

9
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
9
8