Rails Tutorialsで勉強のメモ　その6(ユーザーモデルの作成)

# やること

* サイトのユーザー用のデータモデルの作成
* データを保存する手段の確保

```bash:ブランチを切る
$ git checkout master
$ git checkout -b modeling-users
```

# Userモデル

* モデル
    * Railsの場合、データモデルで使用するデフォルトのデータ構造をさす
* データを永続化する方法
    * データベースを使用してデータを長期間保存
    * データベースとやり取りするRailsライブラリはデフォルトで`Active Record`という
* `Active Record`
    * データオブジェクトの作成／保存／検索のためのメソッドを保持している
    * 上記メソッドを使用する際にSQLを意識する必要はない
* マイグレーション
    * データの定義をRubyで記述
        * DDLを使う必要がない

## データベースの移行

* `generate model`
    * モデルを作成するコマンド
    * モデル名には単数形を用いる
        * コントローラ名は複数形

```bash:Userモデルの作成
$ rails generate model User name:string email:string
      invoke  active_record
      create    db/migrate/20140814160532_create_user.rb
      create    app/models/user.rb
      invoke    rspec
      create      spec/models/user_spec.rb
```

* マイグレーション
    * データベースの構造をインクリメンタルに変更する手段を提供
    * 要求が変更された場合にデータモデルを適合させることができる
    * 上記の例の場合、`db/migrate/20140814160532_create_users.rb`にあたる
        * タイムスタンプを名前の中につけることで、複数開発者が生成しても競合しないようにしている

```rb:db/migrate/20140814160532_create_user.db：Userモデルのマイグレーション
class CreateUsers < ActiveRecord::Migration
  def change
    create_table :user do |t|
      t.string :name
      t.string :email

      t.timestamps
    end
  end
end
```

* マイグレーション
    * データベースに与える変更を定義した`change`メソッドの集合
        * `create_table`メソッドを呼び、ユーザーを保持するためのテーブルをデータベースに作成する
            * モデルは単数形（`user`）だが、テーブル名は複数形（`users`）
        * ブロックの中で、`name`と`email`というカラムをデータベースに作成
        * `t.timestamp`で`created_at`と`updated_at`というカラムを作成
            * レコード作成／更新時に自動的に更新されるカラム

* ユーザーデータモデル
    * `id`は各行を一意に識別するためのカラムで自動生成される

| カラム名 | 型 |
| --- | --- |
| id | integer |
| name | string |
| email | string |
| created_at | datetime |
| updated_at | datetime |

* マイグレーションの実行
    * `bundle exec rake db:migrate`
    * マイグレーションの適用（migrating up）
    * 内部的に`create_table`を呼び出している
    * `db/development.sqlite3`というDDLのファイルが作成される
        * SQLite Database Browserでデータベースの構造を参照できる
* マイグレーションの取り消し
    * `bundle exec rake db:rollback`
    * マイグレーションの取り消し（migrating down）
    * 内部的に`drop_table`を呼び出している

```bash:マイグレーションの適用
$ bundle exec rake db:migrate
== 20140814160532 CreateUsers: migrating ======================================
-- create_table(:users)
   -> 0.0077s
== 20140814160532 CreateUsers: migrated (0.0079s) =============================
```

## modelファイル

* Userモデル
    * `ActiveRecord::Base`の全ての機能を持つ

```rb:app/models/user.rb：Userモデル
class User < ActiveRecord::Base
end
```

## ユーザーオブジェクトの作成

* `rails console`のサンドボックスモード
    * コンソール上でDBの変更を行ってもロールバックされる

```bash:Userオブジェクトの操作：作成・保存と削除
$ rails c --sandbox
Loading development environment in sandbox (Rails 4.0.4)
Any modifications you make will be rolled back on exit

# Userオブジェクトの作成
> User.new

# Userオブジェクトを初期化してuser変数に代入
> user = User.new(name: "Michael Hartl", email: "mhart@example.com")

# user変数をDBに保存
> user.save

# user変数の属性を確認
> user.name
 => "Michael Hartl"
> user.email
 => "mhart@example.com"
> user.updated_at
 => Sat, 23 Aug 2014 13:24:40 UTC +00:00

# Userオブジェクトの作成と同時に保存
> User.create(name: "A Nother", email: "another@example.org")
   (0.2ms)  SAVEPOINT active_record_1
  SQL (0.9ms)  INSERT INTO "users" ("created_at", "email", "name", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Sat, 23 Aug 2014 14:09:14 UTC +00:00], ["email", "another@example.org"], ["name", "A Nother"], ["updated_at", Sat, 23 Aug 2014 14:09:14 UTC +00:00]]
   (0.4ms)  RELEASE SAVEPOINT active_record_1
 => #<User id: 4, name: "A Nother", email: "another@example.org", created_at: "2014-08-23 14:09:14", updated_at: "2014-08-23 14:09:14">

# userの破棄
> user = user.destroy
   (0.4ms)  SAVEPOINT active_record_1
  SQL (0.6ms)  DELETE FROM "users" WHERE "users"."id" = ?  [["id", 3]]
   (0.8ms)  RELEASE SAVEPOINT active_record_1
 => #<User id: 3, name: "Michael Hartl", email: "mhart@example.com", created_at: "2014-08-23 13:24:40", updated_at: "2014-08-23 13:24:40">
```

## ユーザーオブジェクトの検索

```bash:Userオブジェクトの検索
# idで検索
> User.find(5)
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."id" = ? LIMIT 1  [["id", 5]]
 => #<User id: 5, name: "A Nother", email: "another@example.org", created_at: "2014-08-23 14:30:53", updated_at: "2014-08-23 14:30:53">

# Emailで検索
> User.find_by_email("another@example.org")
  User Load (0.4ms)  SELECT "users".* FROM "users" WHERE "users"."email" = 'another@example.org' LIMIT 1
 => #<User id: 4, name: "A Nother", email: "another@example.org", created_at: "2014-08-23 14:09:14", updated_at: "2014-08-23 14:09:14">

# 上記よりもハッシュで指定するfind_byメソッドを使うべき
> User.find_by(email: "another@example.org")
  User Load (0.3ms)  SELECT "users".* FROM "users" WHERE "users"."email" = 'another@example.org' LIMIT 1
 => #<User id: 4, name: "A Nother", email: "another@example.org", created_at: "2014-08-23 14:09:14", updated_at: "2014-08-23 14:09:14">

# 最初の1件目を取得
> User.first
  User Load (0.4ms)  SELECT "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT 1
 => #<User id: 2, name: "テストユーザー", email: "admin@localhost", created_at: "2014-08-02 06:36:09", updated_at: "2014-08-02 06:36:09">

# 全てのデータを返す
> User.all
```

## ユーザーオブジェクトの更新

* オブジェクトの更新方法
    * 属性を個別に代入
        * `save`メソッド
    * 属性の更新と保存を同時に行う
        * `update_attributes`メソッド

```bash:属性の更新
# userの登録
> user = User.create(name: "Michael Hartl", email: "mhart@exampl
e.net")
   (0.2ms)  SAVEPOINT active_record_1
  SQL (0.6ms)  INSERT INTO "users" ("created_at", "email", "name", "updated_at") VALUES (?, ?, ?, ?)  [["created_at", Sat, 23 Aug 2014 14:39:04 UTC +00:00], ["email", "mhart@example.net"], ["name", "Michael Hartl"], ["updated_at", Sat, 23 Aug 2014 14:39:04 UTC +00:00]]
   (1.4ms)  RELEASE SAVEPOINT active_record_1
 => #<User id: 7, name: "Michael Hartl", email: "mhart@example.net", created_at: "2014-08-23 14:39:04", updated_at: "2014-08-23 14:39:04">

# 属性の変更
> user.email = "mhartl@example.com"
 => "mhartl@example.com"

# 属性の更新
> user.save
   (0.2ms)  SAVEPOINT active_record_1
  SQL (0.8ms)  UPDATE "users" SET "email" = ?, "updated_at" = ? WHERE "users"."id" = 7  [["email", "mhartl@example.com"], ["updated_at", Sat, 23 Aug 2014 14:39:30 UTC +00:00]]
   (0.2ms)  RELEASE SAVEPOINT active_record_1
 => true

# 属性の更新＋保存
> user.update_attributes(name: "The Dude", email: "dude@abides.org")
   (0.2ms)  SAVEPOINT active_record_1
  SQL (1.0ms)  UPDATE "users" SET "name" = ?, "email" = ?, "updated_at" = ? WHERE "users"."id" = 7  [["name", "The Dude"], ["email", "dude@abides.org"], ["updated_at", Sat, 23 Aug 2014 14:43:01 UTC +00:00]]
   (0.1ms)  RELEASE SAVEPOINT active_record_1
 => true
```

# ユーザの検証

* `Active Record`の検証（バリデーション）
    * 存在の検証(presence)
    * 長さの検証(length)
    * フォーマットの検証(format)
    * 一意性の検証(uniqueness)

## 最初のユーザテスト

* 初期spec
    * `pending`メソッドを呼び出して、黄色い文字を出力するだけ

```rb:初期spec
require 'spec_helper'

describe User do
  pending "add some examples to (or delete) #{__FILE__}"
end
```

```bash:テストの実行
# DBの作成
$ bundle exec rake db:migrate

# 開発データベースのデータモデルdb/development.sqlite3がテストデータベースdb/test.sqlite3に反映されるようにするもの
$ bundle exec rake test:prepare

# テストを実行
$ bundle exec rspec spec/models/user_spec.rb
```

```rb:spec/models/user_sprc.rbにテストケースを追加
require 'spec_helper'

describe User do
  before { @user = User.new(name: "Example User", email: "user@example.com") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }
end
```

```rb:上記は下記と同義
it "should respond to 'name'" do
  expect(@user).to respond_to(:name)
end
```

* `respond_to`メソッド
    * Rubyの`respond_to?`メソッドを呼び出す
    * そのシンボルが表すメソッドまたは属性が存在しているかどうかを確認

```bash:テストを実施：成功
$ bundle exec rspec spec/
```

```bash:respond_to?の動作確認
$ rails c --sandbox

> user = User.new
> user.respond_to?(:name)
 => true
> user.respond_to?(:foo)
 => false
```

## プレゼンスの検証

* 属性の存在を検証
    * validates`メソッドに`presence: true`という引数を与える

```rb:app/models/user.rb
class User < ActiveRecord::Base
  validates :name, presence: true
end
```

```bash:presenceの検証
$ rails c --sandbox

# name属性を未指定で作成
> user = User.new(name: "", email: "mhartl@example.com")

# 保存しようとするとfalseが返却される
> user.save
 => false

# 検証してもfalseが返却される
> user.valid?
 => false

# エラーメッセージの確認
> user.errors.full_messages
 => ["Name can't be blank"]
```

* テストケースの追加
    * `valid`がtrueであること
    * name、email属性がブランクの時は`valid?`メソッドがfalseであること

```rb:spec/models/user_spec.rb
require 'spec_helper'

describe User do
  before { @user = User.new(name: "Example User", email: "user@example.com") }

  subject { @user }

  it { should respond_to(:name) }
  it { should respond_to(:email) }

  it { should be_valid }

  describe "when name is not present" do
    before { @user.name = " " }
    it { should_not be_valid }
  end

  describe "when email is not present" do
    before { @user.email = " " }
    it { should_not be_valid }
  end
end
```

```bash:rspecの実行：emailのpresenceがないのでエラー
$ bundle exec rspec
.......F...........

Failures:

  1) User when email is not present
     Failure/Error: it { should_not be_valid }
       expected #<User id: nil, name: "Example User", email: " ", created_at: nil, updated_at: nil> not to be valid
```

```rb:app/models/user.rbにemailのpresence設定を追加
class User < ActiveRecord::Base
  validates :name, presence: true
  validates :email, presence: true
end
```

```bash:テスト成功
$ bundle exec rspec
```

## 長さの検証

```rb:spec/models/user_spec.rbに長さのテストケースを追加
  describe "when name is too long" do
    before { @user.name = "a" * 51 }
    it { should_not be_valid }
  end
```

```bash:テストを実施して失敗
$ bundle exec rspec
```

* 長さの検証の設定
    * `length: { maximum: ＜最大文字数＞ }`

```rb:app/models/user.rbに長さの設定を追加
class User < ActiveRecord::Base
  validates :name, presence: true, length: { maximum: 50 }
  validates :email, presence: true
end
```

## フォーマットの検証

```rb:spec/models/user_spec.rbにemailのフォーマット検証ロジックを追加
  describe "when email format is invalid" do
    it "should be invalid" do
      addresses = %w[
        user@foo,com
        user_at_foo.org
        example.user@foo.
        foo@bar_baz.com
        foo@bar+baz.com
      ]
      addresses.each do |invalid_address|
        @user.email = invalid_address
        expect(@user).not_to be_valid
      end
    end
  end

  describe "when email format is valid" do
    it "should be valid" do
      addresses = %w[
        user@foo.COM
        A_US-ER@f.b.org
        frst.lst@foo.jp
        a+b@baz.cn
      ]
      addresses.each do |valid_address|
        @user.email = valid_address
        expect(@user).to be_valid
      end
    end
  end
```

* フォーマットの検証
    * `format: { with: ＜フォーマット＞ }`
    * `\A`は文字列の先頭を表す
    * `\z`は文字列の末尾を表す

```rb:app/models/user.rbにemailのフォーマット検証を追加
class User < ActiveRecord::Base
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX }
end
```

## 一意性の検証

* `@user.dup`
    * 同じユーザを複製
    * 既に登録済みのユーザを登録しようとしてエラーになることを期待

```rb:spec/models/user_spec.rbに一意性検証のテストコードを追加
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
```

* 一意性の検証
    * `uniqueness: true`を設定

```rb:app/models/user.rbに一意性の検証を追加
class User < ActiveRecord::Base
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: true
end
```

```bash:一意性の検証で、現時点では大文字小文字を区別する
$ rails c --sandbox

> user = User.create(name: "Example User", email: "user@example.com")
> user_with_same_email = user.dup
# メールアドレスを大文字に変換してバリデーションチェック　→　一意性がtrueとみなされている
> user_with_same_email.email = user.email.upcase
> user_with_same_email.valid?
 => true
```

* 大文字小文字を区別しないためには
    * `:case_sensitive`を設定

```rb:spec/models/user_spec.rbに一意性検証のテストコードを追加
  describe "when email address is already taken" do
    before do
      user_with_same_email = @user.dup
      user_with_same_email.email = @user.email.upcase
      user_with_same_email.save
    end

    it { should_not be_valid }
  end
```

```rb:app/models/user.rbに大文字小文字を区別しない設定を追加
class User < ActiveRecord::Base
  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
end
```

* DB側の一意性制約
    * emailカラムにDBのインデックスを作成し、そのインデックスが一意であることを要求
    * `rails generate migration`で作成
    * `add_index :＜テーブル名＞, :＜カラム名＞, unique: true`

```bash:インデックスの作成
$ rails generate migration add_index_to_users_email
      invoke  active_record
      create    db/migrate/20140824083152_add_index_to_users_email.rb
```

```rb:db/migrate/20140824083152_add_index_to_users_email.rb
class AddIndexToUsersEmail < ActiveRecord::Migration
  def change
    add_index :users, :email, unique: true
  end
end
```

```bash:データベースのマイグレート
$ cat db/schema.rb
ActiveRecord::Schema.define(version: 20140814160532) do

  create_table "users", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

end

$ bundle exec rake db:migrate

$ cat db/schema.rb
ActiveRecord::Schema.define(version: 20140824083152) do

  create_table "users", force: true do |t|
    t.string   "name"
    t.string   "email"
    t.datetime "created_at"
    t.datetime "updated_at"
  end

  add_index "users", ["email"], name: "index_users_on_email", unique: true

end
```

* メールアドレス保存時の考慮事項
    * メールアドレス保存時に全ての文字を小文字にする
        * DBのアダプタが常に大文字小文字を区別するインデックスを使用しているとは限らないため
    * コールバック機能を使用
* コールバック
    * `Active Record`オブジェクトが持続している間のどこかの時点で、`Active Record`オブジェクトに呼び出してもらうメソッド
    * 今回は`before_save`コールバックを使用

```rb:app/models/user.rbに、メールアドレス保存時に小文字に変換するロジックを追加
class User < ActiveRecord::Base
  before_save { self.email = email.downcase }

  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
end
```

# セキュアなパスワードの追加

* ユーザの認証
    * パスワードの送信
    * 暗号化
    * DB内の暗号化された値との比較
        * 暗号化された値同士を比較する
* セキュアなパスワードの実装方法
    * `has_secure_password`メソッドを使用
    * ハッシュ関数には`bcrypt`を使用して、不可逆的に暗号化してパスワードハッシュを作成

## 暗号化されたパスワード

* ユーザのデータモデル
    * `password_digest`カラムを追加

| カラム名 | 型 |
| --- | --- |
| id | integer |
| name | string |
| email | string |
| password_digest | string |
| created_at | datetime |
| updated_at | datetime |


```rb:Gemfileにbcrypt用のgemを追加
gem 'bcrypt-ruby', '3.1.2'
```

```bash:gemのインストール
$ bundle install
```

```rb:spec/models/user_spec.rbにpassword_digestカラムがあることのテストケースを追加
   it { should respond_to(:password_digest) }
```

* マイグレーション名
    * 末尾に`_to_users`とつけると、`users`テーブルにカラムを追加するマイグレーションがRailsによって自動作成される
    * 第2引数でカラム名と型を指定

```bash:password_digest用のマイグレーションを作成
$ rails generate migration add_password_digest_to_users password_digest:string
      invoke  active_record
      create    db/migrate/20140824101047_add_password_digest_to_users.rb

$ cat db/migrate/20140824101047_add_password
_digest_to_users.rb
class AddPasswordDigestToUsers < ActiveRecord::Migration
  def change
    add_column :users, :password_digest, :string
  end
end
```

```bash:開発DBをマイグレーションしてテストDBを準備し、テストを実施
$ bundle exec rake db:migrate
$ bundle exec rake test:prepare
$ bundle exec rspec spec/
```

## パスワードと確認

* パスワードの確認
    * モデルの中で`Active Record`を使用して制限を与えるのが慣習
    * `password`属性と`password_confirmation`属性をUserモデルに追加し、レコードをDBに保存する前に2つの属性が一致するように要求する
        * これらの属性は一時的にメモリ上に置き、DBには保存されないようにする
        * これらの属性は`has_secure_password`で自動的に実装される

* テストコードの追加／修正
    * `@user`の初期化時に`password`属性と`password_confirmation`属性も初期化する
    * `password`と`password_confirmation`カラムの存在チェック
        * `password`、`password_confirmation`はDB上に作成されるわけではない（仮想的な属性）
    * `password`の存在確認テスト
    * `password`と`password_confirmation`の不一致テスト

```rb:spec/models/user_spec.rb
  before do
    @user = User.new(name: "Example User", email: "user@example.com",
                     password: "foobar", password_confirmation: "foobar")
  end

  it { should respond_to(:password) }
  it { should respond_to(:password_confirmation) }

  describe "when password is not present" do
    before do
      @user = User.new(name: "Example User", email: "user@example.com",
                       password: " ", password_confirmation: " ")
    end
    it { should_not be_valid }
  end

  describe "when password doesn't match confirmation" do
    before { @user.password_confirmation = "mismatch" }
    it { should_not be_valid }
  end
```

```rb:app/models/user.rbにhas_secure_passwordを追加
class User < ActiveRecord::Base
  before_save { self.email = email.downcase }

  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
end
```

* `has_secure_password`を追加するだけでテストコードがパスできる
    * テストがOKになることを確認したら、上記の`has_secure_password`をコメントアウトしておく

```bash:テストコードの実行
$ bundle exec rspec spec/
```

## ユーザー認証

* ユーザをメールアドレスとパスワードに基づいて取得する手段
    1. ユーザをメールアドレスで検索
        * `user = User.find_by(email: email)
    2. 受け取ったパスワードでユーザを認証
        * `current_user = user.authenticate(password)`

* 認証に関するテストケース
    * `authenticate`が応答することの確認
    * パスワードが一致する場合と一致しない場合についてテストケースを記載
    * パスワードの長さの確認

```rb:spec/models/user_spec.rbに上記テストケースを追加
  it { should respond_to(:authenticate) }

  describe "with a password that's too short" do
    before { @user.password = @user.password_confirmation = "a" * 5 }
    it { should be_invalid }
  end

  describe "return value of authenticate method" do
    before { @user.save }
    let(:found_user) { User.find_by(email: @user.email) }

    describe "with valid password" do
      let(:user_for_invalid_password) { found_user.authenticate("invalid") }

      it { should_not eq user_for_invalid_password }
      specify { expect(user_for_invalid_password).to be_false }
    end
  end
```

* `let`メソッド
    * テスト内でローカル変数を作成
    * `let(:found_user) { User.find_by(email: @user.email) }`の場合
        * `found_user`という変数を作成し、ブロック内の戻り値が代入される
* `specify`メソッド
    * `it`と同義
    * `it`を使用すると英語として不自然な場合に使用
        * ×：`user: user with invalid password should be false`
        * ○：`specify: user with invalid password should be false`
* `eq`演算子
    * オブジェクト同士が同値であるかどうかを確認


## ユーザモデルのパスワード認証の実装

* パスワードの長さ検証
    * `length: { minimum: 6 }

* `password`と`password_confirmation`を追加
* パスワードが存在することの確認
* パスワードとパスワードの確認が一致することの確認
* `password_digest`を比較してユーザを認証
    * `has_secure_password`
    * 内容については[secure_password.rb](https://github.com/rails/rails/blob/master/activemodel/lib/active_model/secure_password.rb)を参照

```rb:app/models/user.rbにパスワード関連の設定を追加
class User < ActiveRecord::Base
  before_save { self.email = email.downcase }

  validates :name, presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true,
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, length: { minimum: 6 }
end
```

## ユーザの作成


```bash:ユーザデータを作成
$ rails c

# ユーザの作成
> User.create(name: "Michael Hartl", email: "mhartl@example.com", password: "foobar", password_confirmation: "foobar")

# パスワードの確認
> user = User.find_by(email: "mhartl@example.com")
> user.password_digest
 => "$2a$10$GEZwKUtE7ZqAkgsBhHmIrueLFPZhECEauTC2FqbIGsWg8rzGr3Mwq"

# authenticateメソッドの確認
# パスワードが誤っている場合はfalse、正しい場合はユーザオブジェクトを返す
> user.authenticate("invalid")
 => false
> user.authenticate("foobar")
 => #<User id: 1, name: "Michael Hartl", email: "mhartl@example.com", created_at: "2014-08-24 15:11:15", updated_at: "2014-08-24 15:11:15", password_digest: "$2a$10$GEZwKUtE7ZqAkgsBhHmIrueLFPZhECEauTC2FqbIGsWg...">
```

# 変更内容のコミット

```bash:変更内容のコミットとmasterへのマージ
$ git branch
  filling-in-layout
  master
* modeling-users
  static-pages

$ git add .
$ git commit -m "Make a basic User model (including secure passwords)"

$ git checkout master
$ git merge modeling-users
```