LoginSignup
6
4

More than 5 years have passed since last update.

35歳だけどRailsチュートリアルやってみた。[第4版 14章 14.3 ステータスフィード まとめ&解答例]

Posted at

はじめに

最近、プロジェクト管理業務が業務の大半を占めており、
プログラムを書く機会がなかなかありません。

このままだとプログラムがまったく書けない人になってしまう危機感(迫り来る35歳定年説)と、
新しいことに挑戦したいという思いから、
Ruby on Rails チュートリアル実例を使ってRailsを学ぼう 第4版を学習中です。
業務で使うのはもっぱらJavaなのですが、Rails楽しいですね。

これまでEvernoteに記録していましたが、ソースコードの貼付けに限界を感じたため、
Qiitaで自分が学習した結果をアウトプットしていきます。

個人の解答例なので、誤りがあればご指摘ください。

動作環境

  • cloud9
  • ruby 2.3.0p0 (2015-12-25 revision 53290) [x86_64-linux]
  • Rails 5.0.0.1

14.3.1 動機と計画

本章での学び

【test】ステータスフィードのテスト

  • feed should have the right posts
    • fixtureから、michaelユーザの情報を取得する
    • fixtureから、archerユーザの情報を取得する
    • fixtureから、lanaユーザの情報を取得する
    • フォローしているユーザの投稿を確認
      • lanaのマイクロポストを取得
        • michaelのフィードに含まれていること
    • 自分自身の投稿を確認
      • michaelのマイクロポストを取得
        • michaelのフィードに含まれていること
    • フォローしていないユーザの投稿を確認
      • archerのマイクロポストを取得
        • michaelのフィードに含まれていないこと

上記を踏まえて実装する。

  test "feed should have the right posts" do
    michael = users(:michael)
    archer  = users(:archer)
    lana    = users(:lana)
    # フォローしているユーザの投稿を確認
    lana.microposts.each do |post_following|
      assert michael.feed.include?(post_following)
    end
    # 自分自身の投稿を確認
    michael.microposts.each do |post_self|
      assert michael.feed.include?(post_self)
    end
    # フォローしていないユーザの投稿を確認
    archer.microposts.each do |post_unfollowed|
      assert_not michael.feed.include?(post_unfollowed)
    end
  end

テストは現時点ではredとなる。

演習1

マイクロポストのidが正しく並んでいると仮定して (すなわち若いidの投稿ほど古くなる前提で)、図 14.22のデータセットでuser.feed.map(&:id)を実行すると、どのような結果が表示されるでしょうか? 考えてみてください。ヒント: 13.1.4で実装したdefault_scopeを思い出してください。

user自身とuserがフォローしているマイクロポストが昇順で取得できる。
default_scopeで降順になるように実装していれば、マイクロポストが降順で取得できる。

14.3.2 フィードを初めて実装する

本章での学び

【事前準備】Rubyのmapメソッド

mapメソッドは、&とメソッドに対応するシンボルを使った短縮表記ができる。

okoyan:~/workspace/sample_app (following-users) $ rails console
Running via Spring preloader in process 2367
Loading development environment (Rails 5.0.0.1)
>> [1,2,3,4].map { |i| i.to_s }
=> ["1", "2", "3", "4"]
>> 
?> [1,2,3,4].map(&:to_s)
=> ["1", "2", "3", "4"]
>> 

カンマ区切りの文字列としてつなげることもできる。

?> [1,2,3,4].map(&:to_s).join(', ')
=> "1, 2, 3, 4"

user.followingにある各要素のidを呼び出し、フォローしているユーザのidを配列とする。

?> User.first.following.map(&:id)
  User Load (0.6ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
  User Load (0.7ms)  SELECT "users".* FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
=> [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51]

ActiveRecordで用意しているfollowing_idsメソッドを使うことで、上記と同じ結果が得られる。

?> User.first.following_ids
  User Load (0.2ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
   (0.3ms)  SELECT "users".id FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
=> [3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51]

応用して、カンマ区切りの文字列を取得することもできる。

?> User.first.following_ids.join(', ')
  User Load (0.3ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
   (0.4ms)  SELECT "users".id FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
=> "3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51"

【test】テスト実行

テスト実行時に以下のようなエラーが発生。

7ffe7035b000-7ffe7035d000 r--p 00000000 00:00 0                          [vvar]
7ffe7035d000-7ffe7035f000 r-xp 00000000 00:00 0                          [vdso]
ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0                  [vsyscall]


[NOTE]
You may have encountered a bug in the Ruby interpreter or extension libraries.
Bug reports are welcome.
For details: http://www.ruby-lang.org/bugreport.html

エラーになるため、bundle updateを実行。

yokoyan:~/workspace/sample_app (following-users) $ bundle update
The dependency tzinfo-data (>= 0) will be unused by any of the platforms Bundler is installing for. Bundler is installing for ruby but the dependency is only for x86-mingw32, x86-mswin32, x64-mingw32, java. To add those platforms to the bundle, run `bundle lock --add-platform x86-mingw32 x86-mswin32 x64-mingw32 java`.
Fetching gem metadata from https://rubygems.org/.........
Fetching version metadata from https://rubygems.org/..
Fetching dependency metadata from https://rubygems.org/.
Resolving dependencies.....
Using rake 12.0.0
Using CFPropertyList 2.3.5
Using concurrent-ruby 1.0.5
Installing i18n 0.8.6 (was 0.8.1)
Installing minitest 5.10.3 (was 5.10.1)
Using thread_safe 0.3.6
Using builder 3.2.3
Using erubis 2.7.0
Installing mini_portile2 2.2.0 (was 2.1.0)
Installing rack 2.0.3 (was 2.0.1)
Using nio4r 1.2.1
Using websocket-extensions 0.1.2
Using mime-types-data 3.2016.0521
Using arel 7.1.4
Using ansi 1.5.0
Using execjs 2.7.0
Using bcrypt 3.1.11
Installing rb-fsevent 0.10.2 (was 0.9.8)
Using ffi 1.9.18
Using will_paginate 3.1.0
Using bundler 1.14.6
Using byebug 9.0.0
Using coderay 1.1.1
Using coffee-script-source 1.12.2
Using method_source 0.8.2
Installing thor 0.20.0 (was 0.19.4)
Installing debug_inspector 0.0.3 (was 0.0.2) with native extensions
Using excon 0.58.0
Using formatador 0.2.5
Using multi_json 1.12.1
Using ipaddress 0.8.3
Using xml-simple 1.1.5
Using inflecto 0.0.2
Using json 1.8.6
Using trollop 2.1.2
Installing lumberjack 1.0.12 (was 1.0.11)
Using nenv 0.3.0
Using shellany 0.0.1
Using slop 3.6.0
Using guard-compat 1.2.1
Using mini_magick 4.7.0
Using ruby-progressbar 1.8.1
Using puma 3.4.0
Installing tilt 2.0.8 (was 2.0.6)
Using spring 1.7.2
Using sqlite3 1.3.11
Installing turbolinks-source 5.0.3 (was 5.0.0)
Using fission 0.5.0
Using faker 1.6.6
Installing tzinfo 1.2.3 (was 1.2.2)
Installing nokogiri 1.8.0 (was 1.7.0.1) with native extensions
Using rack-test 0.6.3
Using sprockets 3.7.1
Using websocket-driver 0.6.5
Using mime-types 3.1
Installing autoprefixer-rails 7.1.3 (was 6.7.7.1)
Using uglifier 3.0.0
Installing rb-inotify 0.9.10 (was 0.9.8)
Using bootstrap-will_paginate 0.0.10
Using coffee-script 2.4.1
Using fog-core 1.45.0
Using notiffany 0.1.1
Using pry 0.10.4
Using guard-minitest 2.4.4
Using minitest-reporters 1.1.9
Using turbolinks 5.0.1
Using activesupport 5.0.0.1
Using loofah 2.0.3
Using rbvmomi 1.11.3
Installing mail 2.6.6 (was 2.6.4)
Installing sass-listen 4.0.0
Using listen 3.0.8
Using fog-json 1.0.2
Using fog-xml 0.1.3
Using fog-local 0.3.1
Using fog-vmfusion 0.1.0
Installing rails-dom-testing 2.0.3 (was 2.0.2)
Installing globalid 0.4.0 (was 0.3.7)
Using activemodel 5.0.0.1
Using jbuilder 2.4.1
Using rails-html-sanitizer 1.0.3
Installing fog-vsphere 1.12.0 (was 1.11.3)
Installing sass 3.5.1 (was 3.4.23)
Using guard 2.13.0
Using spring-watcher-listen 2.0.0
Using fog-aliyun 0.2.0
Using fog-brightbox 0.13.0
Using fog-dnsimple 1.0.0
Using fog-openstack 0.1.21
Using fog-profitbricks 4.0.0
Using fog-sakuracloud 1.7.5
Using fog-serverlove 0.1.2
Using fog-softlayer 1.1.4
Using fog-storm_on_demand 0.1.1
Using fog-atmos 0.1.0
Installing fog-aws 1.4.1 (was 1.4.0)
Using fog-cloudatcost 0.1.2
Using fog-digitalocean 0.3.0
Using fog-dynect 0.0.3
Using fog-ecloud 0.3.0
Using fog-google 0.1.0
Using fog-powerdns 0.1.1
Using fog-rackspace 0.1.5
Using fog-radosgw 0.0.5
Using fog-riakcs 0.1.0
Using fog-terremark 0.1.0
Using fog-voxel 0.1.0
Using fog-xenserver 0.3.0
Using activejob 5.0.0.1
Using activerecord 5.0.0.1
Using carrierwave 1.1.0
Using actionview 5.0.0.1
Using bootstrap-sass 3.3.6
Using fog 1.40.0
Using actionpack 5.0.0.1
Using actioncable 5.0.0.1
Using actionmailer 5.0.0.1
Using railties 5.0.0.1
Using sprockets-rails 3.2.0
Using rails-controller-testing 0.1.1
Using coffee-rails 4.2.1
Using jquery-rails 4.1.1
Using web-console 3.1.1
Using rails 5.0.0.1
Using sass-rails 5.0.6
Bundle updated!
Gems in the group production were not installed.

【test】再度テストを実行

テスト結果がgreenになることを確認。

yokoyan:~/workspace/sample_app (following-users) $ rails test
Running via Spring preloader in process 15601
Started with run options --seed 9757

DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only                                                                                                                     ] 18% Time: 00:00:02,  ETA: 00:00:10
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as

Examples:

get '/profile',
  params: { id: 1 },
  headers: { 'X-Extra-Header' => '123' },
  env: { 'action_dispatch.custom' => 'custom' },
  xhr: true,
  as: :json
 (called from block (2 levels) in <class:MicropostsInterfaceTest> at /home/ubuntu/workspace/sample_app/test/integration/microposts_interface_test.rb:27)
  75/75: [====================================================================================================================================================================================================] 100% Time: 00:00:05, Time: 00:00:05

Finished in 5.33761s
75 tests, 335 assertions, 0 failures, 0 errors, 0 skips

演習1

リスト 14.44において、現在のユーザー自身の投稿を含めないようにするにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか?

user.feedの実行結果は以下の通り。
フォローしているユーザのIDと、自分のIDを渡している。

yokoyan:~/workspace/sample_app (following-users) $ rails console
Running via Spring preloader in process 1248
Loading development environment (Rails 5.0.0.1)
>> 
?> user = User.first
  User Load (0.4ms)  SELECT  "users".* FROM "users" ORDER BY "users"."id" ASC LIMIT ?  [["LIMIT", 1]]
=> #<User id: 1, name: "Example User", email: "example@railstutorial.org", created_at: "2017-08-26 04:58:19", updated_at: "2017-08-26 04:58:19", password_digest: "$2a$10$0FM4wRDzxU.nOpDa5RmxZuyTz/omIcX4Qm4nguWAde0...", remember_digest: nil, admin: true, activation_digest: "$2a$10$gQQiCXRCh4ZDsruNiSv5euZW4Vwt7kcKm6tZkxM1MMg...", activated: true, activated_at: "2017-08-26 04:58:19", reset_digest: nil, reset_sent_at: nil>
>> 
?> user.feed
   (0.6ms)  SELECT "users".id FROM "users" INNER JOIN "relationships" ON "users"."id" = "relationships"."followed_id" WHERE "relationships"."follower_id" = ?  [["follower_id", 1]]
  Micropost Load (3.2ms)  SELECT "microposts".* FROM "microposts" WHERE (user_id IN (3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51) OR user_id = 1) ORDER BY "microposts"."created_at" DESC

つまり、自分の投稿を含めないようにするには、2つ目の引数を削除する。

/sample_app/app/models/user.rb
  def feed
    # Micropost.where("user_id = ?", id)
    # Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
    Micropost.where("user_id IN (?) ", following_ids)
  end

以下のテストで結果がredとなる。


 FAIL["test_micropost_interface", MicropostsInterfaceTest, 1.9879938876256347]
 test_micropost_interface#MicropostsInterfaceTest (1.99s)
        Expected at least 1 element matching "div.pagination", found 0..
        Expected 0 to be >= 1.
        test/integration/microposts_interface_test.rb:14:in `block in <class:MicropostsInterfaceTest>'

 FAIL["test_feed_should_have_the_right_posts", UserTest, 3.517132450826466]
 test_feed_should_have_the_right_posts#UserTest (3.52s)
        Expected false to be truthy.
        test/models/user_test.rb:108:in `block (2 levels) in <class:UserTest>'
        test/models/user_test.rb:107:in `block in <class:UserTest>'

演習2

リスト 14.44において、フォローしているユーザーの投稿を含めないようにするにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか?

演習1と逆で、1つめの引数を削除する。
(試作フィードの状態に戻すことになる)

/sample_app/app/models/user.rb
  def feed
    Micropost.where("user_id = ?", id)
    # Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
  end

以下のテストがredになることを確認。

 FAIL["test_feed_should_have_the_right_posts", UserTest, 2.452872692141682]
 test_feed_should_have_the_right_posts#UserTest (2.45s)
        Expected false to be truthy.
        test/models/user_test.rb:104:in `block (2 levels) in <class:UserTest>'
        test/models/user_test.rb:103:in `block in <class:UserTest>'

演習3

リスト 14.44において、フォローしていないユーザーの投稿を含めるためにはどうすれば良いでしょうか? また、そのような変更を加えると、リスト 14.42のどのテストが失敗するでしょうか? ヒント: 自分自身とフォローしているユーザー、そしてそれ以外という集合は、いったいどういった集合を表すのか考えてみてください。

フォローしていないユーザーの投稿を含めるためには、
micropostsテーブルのすべての情報を取得する。

/sample_app/app/models/user.rb
  def feed
    # Micropost.where("user_id = ?", id)
    # Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
    Micropost.all
  end

以下のテストがredになることを確認。
フォローしていないユーザが含まれないことが期待値であるためエラーとなっている。

 FAIL["test_feed_should_have_the_right_posts", UserTest, 1.5933369509875774]
 test_feed_should_have_the_right_posts#UserTest (1.59s)
        Expected true to be nil or false
        test/models/user_test.rb:112:in `block (2 levels) in <class:UserTest>'
        test/models/user_test.rb:111:in `block in <class:UserTest>'

14.3.3 サブセレクト

本章での学び

今の実装ではパフォーマンスに懸念があるため、サブセレクトを使って解決する。

【model】feedメソッドのリファクタリング

同じ変数を複数の場所に挿入する場合は、whereメソッド内の変数にキーと値のペアにしたほうが便利とのこと。

/sample_app/app/models/user.rb
  def feed
    # 自分のみ
    # Micropost.where("user_id = ?", id)
    # フォローしているユーザか自分の投稿
    # Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
    Micropost.where("user_id IN (:following_ids) OR user_id = :user_id", following_ids: following_ids, user_id: id)
    # フォローしていないユーザも含める
    # Micropost.all
  end

上記からさらに、サブクエリのSQLを追加する。

/sample_app/app/models/user.rb
 def feed
    # フォローしているユーザか自分の投稿
    # Micropost.where("user_id IN (?) OR user_id = ?", following_ids, id)
    # Micropost.where("user_id IN (:following_ids) OR user_id = :user_id", following_ids: following_ids, user_id: id)
    #最終的な実装
    following_ids = "SELECT followed_id FROM relationships WHERE follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids}) OR user_id = :user_id", user_id: id)

動作確認

テストがgreenになることを確認。

yokoyan:~/workspace/sample_app (following-users) $ rails test
Running via Spring preloader in process 2913
Started with run options --seed 15753

DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only=====                                             ] 66% Time: 00:00:03,  ETA: 00:00:02
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as

Examples:

get '/profile',
  params: { id: 1 },
  headers: { 'X-Extra-Header' => '123' },
  env: { 'action_dispatch.custom' => 'custom' },
  xhr: true,
  as: :json
 (called from block (2 levels) in <class:MicropostsInterfaceTest> at /home/ubuntu/workspace/sample_app/test/integration/microposts_interface_test.rb:27)
  75/75: [=================================================================================================================================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.46490s
75 tests, 335 assertions, 0 failures, 0 errors, 0 skips

ブラウザからもフォローしているユーザのフィードが表示されていることを確認。

image

MASTERブランチへのマージ

yokoyan:~/workspace/sample_app (master) $ rails test
yokoyan:~/workspace/sample_app (master) $ git add -A
yokoyan:~/workspace/sample_app (master) $ git status
yokoyan:~/workspace/sample_app (master) $ git commit -m "Add user following"
yokoyan:~/workspace/sample_app (master) $ git checkout master
yokoyan:~/workspace/sample_app (master) $ git merge following-users 

Herokuへのデプロイ

yokoyan:~/workspace/sample_app (master) $ git push
yokoyan:~/workspace/sample_app (master) $ git push heroku

HerokuのDBのマイグレーション

本番環境のDBのリセット、マイグレーション、テストデータの登録を行う。

yokoyan:~/workspace/sample_app (master) $ heroku pg:reset DATABASE                                                                                                              
yokoyan:~/workspace/sample_app (master) $ heroku run rails db:migrate
yokoyan:~/workspace/sample_app (master) $ heroku run rails db:seed

演習1

Homeページで表示される1ページ目のフィードに対して、統合テストを書いてみましょう。リスト 14.49はそのテンプレートです。

  • feed on Home page
    • getリクエストを送信する(root_path)
    • @userのフィードを生成し、1ページ目を取得する。micropostの数だけ繰り返す。
      • micropost内のcontentをエスケープして、HTML内に表示されること

上記を踏まえて実装する。

/sample_app/test/integration/following_test.rb
  test "feed on Home page" do
    get root_path
    @user.feed.paginate(page: 1).each do |micropost|
      assert_match CGI.escapeHTML(micropost.content), response.body
    end
  end

テスト結果がgreenであることを確認。

yokoyan:~/workspace/sample_app (master) $ rails test
Running via Spring preloader in process 1866
Started with run options --seed 52063

DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only                                    ] 68% Time: 00:00:03,  ETA: 00:00:02
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as

Examples:

get '/profile',
  params: { id: 1 },
  headers: { 'X-Extra-Header' => '123' },
  env: { 'action_dispatch.custom' => 'custom' },
  xhr: true,
  as: :json
 (called from block (2 levels) in <class:MicropostsInterfaceTest> at /home/ubuntu/workspace/sample_app/test/integration/microposts_interface_test.rb:27)
  76/76: [===================================================================================================================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.53767s
76 tests, 395 assertions, 0 failures, 0 errors, 0 skips

演習2

リスト 14.49のコードでは、期待されるHTMLをCGI.escapeHTMLメソッドでエスケープしています (このメソッドは11.2.3で扱ったCGI.escapeと同じ用途です)。このコードでは、なぜHTMLをエスケープさせる必要があったのでしょうか? 考えてみてください。ヒント: 試しにエスケープ処理を外して、得られるHTMLの内容を注意深く調べてください。マイクロポストの内容が何かおかしいはずです。また、ターミナルの検索機能 (Cmd-FもしくはCtrl-F) を使って「sorry」を探すと原因の究明に役立つはずです。

content属性に含まれる改行コードを含め、エスケープするため。

エスケープ処理を外して検証。

/sample_app/test/integration/following_test.rb
  test "feed on Home page" do
    get root_path
    @user.feed.paginate(page: 1).each do |micropost|
      # assert_match CGI.escapeHTML(micropost.content), response.body
      assert_match micropost.content, response.body
    end
  end

テスト結果がredになることを確認。

yokoyan:~/workspace/sample_app (master) $ rails test
Running via Spring preloader in process 2044
Started with run options --seed 8292

 FAIL["test_feed_on_Home_page", FollowingTest, 2.3300648159347475]
 test_feed_on_Home_page#FollowingTest (2.33s)
        Expected /I'm\ sorry\.\ Your\ words\ made\ sense,\ but\ your\ sarcastic\ tone\ did\ not\./ to match "<!DOCTYPE html>\n<html>\n  <head>\n    <title>Ruby on Rails Tutorial Sample App</title>\n        \n    <link rel=\"stylesheet\" media=\"all\" href=\"/assets/application-10fa38882e9521d0e9f81abaad450c57aa1940c84d7a510d6d14e6ade7210745.css\" data-turbolinks-track=\"reload\" />\n    <script src=\"/assets/application-8145d5d9dada575ad93c1a2586a1fff566ccef067d7d39e629336a3561895941.js\" data-turbolinks-track=\"reload\"></script>\n        <!--[if lt IE 9]>\n      <script scr=\"//cdnjs.cloudflare.com/ajax/libs/html5shiv/r29/html5.min.js\">\n      </script>\n    <![endif]-->\n  </head>\n  <body>\n        <header class=\"navbar navbar-fixed-top navbar-inverse\">\n      <div class=\"container\">\n        <a id=\"logo\" href=\"/\">sample app</a>\n        <nav>\n          <ul class=\"nav navbar-nav navbar-right\">\n            <li><a href=\"/\">Home</a></li>\n            <li><a href=\"/help\">Help</a></li>\n              <li><a href=\"/users\">Users</a></li>\n              <li class=\"dropdown\">\n              <a href=\"#\" class=\"dropdown-toggle\" data-toggle=\"dropdown\">\n                Account <b class=\"caret\"></b>\n              </a>\n              <ul class=\"dropdown-menu\">\n                <li><a href=\"/users/762146111\">Profile</a></li>\n                <li><a href=\"/users/762146111/edit\">Settings</a></li>\n                <li class=\"divider\"></li>\n                <li>\n                  <a rel=\"nofollow\" data-method=\"delete\" href=\"/logout\">Log out</a>\n                </li>\n              </ul>\n            </li>\n          </ul>\n        </nav>\n      </div>\n    </header>\n\n    <div class=\"container\">\n          <div class=\"row\">\n    <aside class=\"col-md-4\">\n      <section class=\"user_info\">\n        <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n<h1>Michael Example</h1>\n<span><a href=\"/users/762146111\">view my profile</a></span>\n<span>34 microposts</span>\n      </section>\n      <section class=\"stats\">\n        <div class=\"stats\">\n  <a href=\"/users/762146111/following\">\n    <strong id=\"following\" class=\"stat\">\n      2\n    </strong>\n    following\n  </a>\n  <a href=\"/users/762146111/followers\">\n    <strong id=\"followers\" class=\"stat\">\n      2\n    </strong>\n    followers\n  </a>\n</div>\n      </section>\n      <section>\n        <form class=\"new_micropost\" id=\"new_micropost\" enctype=\"multipart/form-data\" action=\"/microposts\" accept-charset=\"UTF-8\" method=\"post\"><input name=\"utf8\" type=\"hidden\" value=\"&#x2713;\" />\n  \n  <div class=\"field\">\n    <textarea placeholder=\"Compose new micropost...\" name=\"micropost[content]\" id=\"micropost_content\">\n</textarea>\n  </div>\n  <input type=\"submit\" name=\"commit\" value=\"Post\" class=\"btn btn-primary\" data-disable-with=\"Post\" />\n  <span class=\"picture\">\n    <input accept=\"image/jpeg,image/gif,image/png\" type=\"file\" name=\"micropost[picture]\" id=\"micropost_picture\" />\n  </span>\n</form>\n<script type=\"text/javascript\">\n  $('#micropost_picture').bind('change', function() {\n    var size_in_megabytes = this.files[0].size/1024/1024;\n    if (size_in_megabytes > 5) {\n      alert('Maximum file size is 5MB. Please choose a smaller file.')\n    }\n  });\n</script>\n      </section>\n    </aside>\n    <div class=\"col-md-8\">\n      <h3>Micropost Feed</h3>\n        <ol class=\"microposts\">\n    <li id=\"micropost-941832919\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Writing a short test\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted less than a minute ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/941832919\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-3454773\">\n  <a href=\"/users/409608538\"><img alt=\"Lana Kane\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/de9a58df9617af487e8b28dbb3aa50de?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/409608538\">Lana Kane</a></span>\n  <span class=\"content\">\n    I&#39;m sorry. Your words made sense, but your sarcastic tone did not.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted 10 minutes ago.\n  </span>\n</li>\n<li id=\"micropost-499495288\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    I just ate an orange!\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted 10 minutes ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/499495288\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-12348100\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Sad cats are sad: http://youtu.be/PKffm2uI4dk\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 2 hours ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/12348100\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-970054474\">\n  <a href=\"/users/409608538\"><img alt=\"Lana Kane\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/de9a58df9617af487e8b28dbb3aa50de?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/409608538\">Lana Kane</a></span>\n  <span class=\"content\">\n    Dude, this van&#39;s, like, rolling probable cause.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 4 hours ago.\n  </span>\n</li>\n<li id=\"micropost-19959062\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Sunt ad blanditiis totam aut qui repudiandae rerum id sint.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/19959062\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-58620899\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Quidem doloremque qui consectetur architecto.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/58620899\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-68403196\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Explicabo aliquid voluptatem occaecati consectetur doloremque quia error pariatur id.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/68403196\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-71534927\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Velit error et aut non laboriosam dolorem aut.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/71534927\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-106776847\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Facilis quas et ut minima.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/106776847\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-177734013\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Voluptas consequatur enim aperiam qui.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/177734013\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-228979669\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Enim porro quam magni aliquid at dolores.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/228979669\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-234210660\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Consequatur tenetur mollitia dolores et.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/234210660\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-294621321\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Esse accusantium maxime dolore aut suscipit doloremque soluta ut at.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/294621321\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-328290505\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Omnis eius minima est distinctio voluptatem dolor impedit eum.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/328290505\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-352097504\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Quia et consectetur similique natus.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/352097504\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-406445230\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Et aut veniam aut similique consequatur qui est.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/406445230\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-444017243\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Quod sed est atque non dicta qui.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/444017243\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-488304196\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Aut consequuntur et et molestiae.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/488304196\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-525605047\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Ullam et voluptatem velit enim rerum.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/525605047\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-603694155\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Temporibus at omnis rerum voluptatem consectetur est culpa.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/603694155\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-613834836\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Reiciendis nam quod voluptates et at sit perspiciatis nihil.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/613834836\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-646488084\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Nobis et sunt mollitia natus saepe tempore.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/646488084\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-676538406\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Et molestiae quia blanditiis reiciendis illum sit aut enim.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/676538406\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-706600661\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Aut aliquam est provident nihil cum quaerat.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/706600661\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-762321612\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Sint dolor voluptatum blanditiis eveniet aut temporibus hic.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/762321612\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-792652861\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Error quaerat animi nulla nostrum iste nam.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/792652861\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-828012954\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Velit iste omnis laudantium voluptatibus.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/828012954\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-856985457\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Fugit dolorem quasi et temporibus omnis alias architecto.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/856985457\">delete</a>\n  </span>\n</li>\n<li id=\"micropost-860142042\">\n  <a href=\"/users/762146111\"><img alt=\"Michael Example\" class=\"gravator\" src=\"https://secure.gravatar.com/avatar/03ea78c0884c9ac0f73e6af7b9649e90?s=50\" /></a>\n  <span class=\"user\"><a href=\"/users/762146111\">Michael Example</a></span>\n  <span class=\"content\">\n    Architecto voluptatem voluptatem dolor sed.\n    \n  </span>\n  <span class=\"timestamp\">\n    Posted about 1 month ago.\n      <a data-confirm=\"You sure?\" rel=\"nofollow\" data-method=\"delete\" href=\"/microposts/860142042\">delete</a>\n  </span>\n</li>\n\n  </ol>\n    <div class=\"pagination\"><ul class=\"pagination\"><li class=\"prev previous_page disabled\"><a href=\"#\">&#8592; Previous</a></li> <li class=\"active\"><a rel=\"start\" href=\"/?page=1\">1</a></li> <li><a rel=\"next\" href=\"/?page=2\">2</a></li> <li class=\"next next_page \"><a rel=\"next\" href=\"/?page=2\">Next &#8594;</a></li></ul></div>\n\n    </div>\n  </div>\n\n\n      <footer>\n  <small>\n    The <a href=\"http://railstutorial.jp\">Ruby on Rails Tutorial</a>\n    by <a href=\"http://www.michaelhartl.com\">Michael Hartl</a>\n  </small>\n  <nav>\n    <ul>\n      <li><a href=\"/about\">About</a></li>\n      <li><a href=\"/contact\">Contact</a></li>\n      <li><a href=\"http://news.railstutorial.org/\">News</a></li>\n    </ul>\n  </nav>\n</footer>\n      \n    </div>\n  </body>\n</html>\n".
        test/integration/following_test.rb:65:in `block (2 levels) in <class:FollowingTest>'
        test/integration/following_test.rb:63:in `block in <class:FollowingTest>'

DEPRECATION WARNING: ActionDispatch::IntegrationTest HTTP request methods will accept only============                        ] 80% Time: 00:00:03,  ETA: 00:00:01
the following keyword arguments in future Rails versions:
params, headers, env, xhr, as

Examples:

get '/profile',
  params: { id: 1 },
  headers: { 'X-Extra-Header' => '123' },
  env: { 'action_dispatch.custom' => 'custom' },
  xhr: true,
  as: :json
 (called from block (2 levels) in <class:MicropostsInterfaceTest> at /home/ubuntu/workspace/sample_app/test/integration/microposts_interface_test.rb:27)
  76/76: [===================================================================================================================] 100% Time: 00:00:04, Time: 00:00:04

Finished in 4.62458s
76 tests, 339 assertions, 1 failures, 0 errors, 0 skips

おわりに

ついにRailsチュートリアルのアプリケーションが完成しました!
4月からこつこつ続けてきて約4ヶ月で完走です。
RubyもRailsも知識ゼロでしたが、自分の手で作り上げていくのはとても楽しかったです。

新しいことを学ぶのに、年齢は関係ないですね。

素晴らしい教材を提供してくださったMichaelさん、安川さんに感謝です!

6
4
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
6
4