ぞえの技術めも

Ruby on Rails勉強中

【163日目】【1日20分のRailsチュートリアル】【第11章】第11章のまとめ

Ruby on Railsチュートリアル(第3版)

今日は「11.5 最後に」から。

11.5 最後に

Micropostsリソースの追加によって、サンプルアプリケーションはほぼ完成に近づきました。残すところは、ユーザーをお互いにフォローするソーシャルな仕組みのみとなります。

ほぅほぅ、後はお互いにフォローする仕組みか…!

もし11.4.4をスキップしていたら、ここで今までの変更のコミットとmergeを済ませてください。

スキップしてるのでコミットとマージを済ませよう。

$ bundle exec rake test
59 tests, 306 assertions, 0 failures, 0 errors, 0 skips
$ git add -A
$ git commit -m "Add user microposts"
$ git checkout master
$ git merge user-microposts
$ git push

リモートリポジトリにもpushできてますね。

f:id:kt_zoe:20170713123425p:plain

準備ができたら、本番環境へデプロイしてみましょう。

本番環境へのデプロイはいいか…メールのとこからやってないし。。。

なお、必要なgemはここまでですべてインストールしたので、今後の章では新たなgemは追加しません。参考までに、最終状態のGemfileをリスト11.67に示します。

試しに比較してみたらfogのバージョンが私の環境では1.36.0になってた。(チュートリアルは`1.26.0)
んー、、、まぁいっか。

11.5.1 本章のまとめ

見返すと色々やったんだな…。全部理解できているかと言えば怪しいけど。。。

CarrierWaveを使うと画像アップロードや画像リサイズができる

個人的にはこれびっくりだった。簡単すぎる~

今日の学習時間は【16分】

次は「11.6 演習」から。

【162日目】【1日20分のRailsチュートリアル】【第11章】アップロード時に画像のリサイズを実施する

Ruby on Railsチュートリアル(第3版)

今日は「11.4.3 画像のリサイズ」から。

11.4.3 画像のリサイズ

ファイルサイズに対するバリデーション (11.4.2) はうまくいきましたが、画像サイズ (縦横の長さ) に対する制限はないので、大きすぎる画像サイズがアップロードされると図11.21のようにレイアウトが壊れてしまいます。

そうそう、レイアウトが崩れちゃうんですよね~。(実践済み)

画像をリサイズするためには、画像を操作するプログラムが必要になります。今回はImageMagickというプログラムを使うので、これを開発環境にインストールしておく必要になります。 Cloud IDEでは下記コマンドでImageMagickをインストール。

インストール途中で続けていいか聞かれるのでYを入力。

$ sudo apt-get update
$ sudo apt-get install imagemagick --fix-missing

次に、MiniMagickというgemを使って、CarrierWaveからImageMagickを使えるようにします。

元々生成されてたinclude文をコメントアウトして、縦横どちらかが400pxを超えていた場合、適切なサイズに縮小するオプションを追加。
これだけでリサイズできちゃうの…?

app/uploaders/picture_uploader.rb

  :
  # Include RMagick or MiniMagick support:
  # include CarrierWave::RMagick
  include CarrierWave::MiniMagick
  process resize_to_limit: [400, 400]
  :

気になるので動作見てみよう。

サーバーを起動して

$ rails server -b $IP -p $PORT

前と同じ画像をアップロードしてみる。

f:id:kt_zoe:20170712123425p:plain

わー!リサイズできてる!!いい感じ!

画像のアップロード時にリサイズするのですでにアップロードしてるやつには適用されないよう。残念なままで残しておくか。。。。

今日の学習時間は【22分】

次は「11.4.4 本番環境での画像アップロード」、、、と見せかけて、本番環境はそもそもアカウント登録できない(メール機能追加してない)のでこの項はスルーかな。
また本番環境作りたい!と思ったときにでも読みます。

というわけで次は「11.5 最後に」から。いよいよ第11章も終わりが近づいてきた…!

【161日目】【1日20分のRailsチュートリアル】【第11章】画像のバリデーションをビューに組み込む

Ruby on Railsチュートリアル(第3版)

今日は「11.4.2 画像の検証」の画像のバリデーションをビューに組み込むところから。

11.4.2 画像の検証

リスト11.60リスト11.61で定義した画像のバリデーションをビューに組み込むために、クライアント側に2つの処理を追加しましょう。

画像の拡張子のチェックと画像の容量チェックの処理を追加する。

これらの追加的なチェック機能をまとめると、リスト11.62のようになります。

拡張子のチェックは簡単なんだな…。

画像の容量チェック&アラート表示はjQueryを使うらしい。

app/views/shared/_micropost_form.html.erb

  :
  <span class="picture">
    <%= f.file_field :picture, accept: 'image/jpeg,image/gif,image/png' %>
  </span>
<% end %>

<script type="text/javascript">
  $('#micropost_picture').bind('change', function() {
    var size_in_megabytes = this.files[0].size/1024/1024;
    if (size_in_megabytes > 5) {
      alert('Maximum file size is 5MB. Please choose a smaller file.');
    }
  });
</script>

ちなみに、リスト11.62のようなコードでは大きすぎるファイルのアップロードを完全には阻止できない、という点を覚えておいてください。
(中略)
こういった場合にも対応できるようにするため、リスト11.61で実装したサーバー側のバリデーションも重要なのです。

クライアント側、サーバー側それぞれの処理だけではちょっと不足してて、クライアント側ではフォームからの投稿に対してガードをかけつつ、サーバー側ではそれ以外での送信からしっかり守る!って感じかな~。

今日の学習時間は【14分】

次は「11.4.3 画像のリサイズ」から。

【160日目】【1日20分のRailsチュートリアル】【第11章】画像のバリデーションを定義する

Ruby on Railsチュートリアル(第3版)

今日は「11.4.2 画像の検証」から。

11.4.2 画像の検証

11.4.1アップローダーも悪くはありませんが、いくつかの目立つ欠点があります。
例えば、アップロードされた画像に対する制限がないため、もしユーザーが巨大なファイルを上げたり、無効なファイルを上げると問題が発生してしまいます

とてつもなく容量の大きい画像がアップロードされたらレイアウト崩れだけじゃない問題発生しそう。

生成されたアップローダーの中にコメントアウトされたコードがありますが、ここのコメントアウトを取り消すことで、画像のファイル名から有効な拡張子 (PNG/GIF/JPEGなど) を検証することができます (リスト11.60)。

40行目あたりにあるextension_white_listコメントアウトを外す。有効な拡張子はこれでいいのかな。いいんだろうな。

app/uploaders/picture_uploader.rb

  # アップロード可能な拡張子のリスト
  def extension_white_list
    %w(jpg jpeg gif png)
  end

2つ目のバリデーションでは、画像のサイズを制御します。これはMicropostモデルに書き足していきます。

画像の容量は5MBまで。

独自のバリデーションを定義するために、今まで使っていたvalidatesメソッドではなく、validateメソッドを使っている点に注目してください。

何が違うんだろう…。独自のバリデーションを定義するためにはvalidateメソッドってこと?

app/models/micropost.rb

  :
  validate  :picture_size

  private

    # アップロード画像のサイズを検証する
    def picture_size
      if picture.size > 5.megabytes
        errors.add(:picture, "should be less than 5MB")
      end
    end
end

中途半端だけど今日はここまで。

今日の学習時間は【17分】

次は「11.4.2 画像の検証」の画像のバリデーションをビューに組み込むところから。

【159日目】【1日20分のRailsチュートリアル】【第11章】基本的な画像アップロード機能を実装する

Ruby on Railsチュートリアル(第3版)

今日は「11.4.1 基本的な画像アップロード」のHomeページ上にアップローダーを追加するところから。

11.4.1 基本的な画像アップロード

図 11.18のようにHomeページ上にアップローダーを追加するためには、マイクロポストのフォームにfile_fieldタグを含める必要があります (リスト11.57)。

マイクロポストのフォームにfile_fieldタグを追加する。

app/views/shared/_micropost_form.html.erb

<%= form_for(@micropost, html: { multipart: true }) do |f| %>
  :
  <span class="picture">
    <%= f.file_field :picture %>
  </span>
<% end %>

html: { multipart: true }
form_forの引数に上のオプションが追加されていることに注目してください。これはファイルをアップロードする際に必要となるオプションです。

へー。画像をアップロードするにはオプションの追加が必要、と。

最後に、Webから更新できる許可リストにpicture属性を追加しましょう。追加すると、micropost_paramsメソッドはリスト11.58のようになります。

picture属性追加する。

app/controllers/microposts_controller.rb

  private

    def micropost_params
      params.require(:micropost).permit(:content, :picture)
    end

一度画像がアップロードされれば、Micropostパーシャルのimage_tagヘルパーでその画像を描画できるようになります (リスト11.59)。

spanタグの中に画像を描画するようにビューを修正。

app/views/microposts/_micropost.html.erb

  :
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  :

手動で画像付きの投稿をしてみると、図 11.20のようになります。

動作確認してみよう。サーバーを起動して

$ rails server -b $IP -p $PORT

まずホーム画面にアクセス。

f:id:kt_zoe:20170703123527p:plain

画像をアップロードするフォーム?追加されてる!

試しにWindowsに元々入ってたサンプル ピクチャをアップロードしてみる。

f:id:kt_zoe:20170703123547p:plain

ひえっ!画像がデカすぎてレイアウトが残念な感じに…!!!
この辺はおいおい対応していくんでしょう。とりあえず画像のアップロードはできた、ということで。

今日の学習時間は【25分】

次は「11.4.2 画像の検証」から。

【158日目】【1日20分のRailsチュートリアル】【第11章】画像アップロードの準備

Ruby on Railsチュートリアル(第3版)

今日は「11.4 マイクロポストの画像投稿」から。

11.4 マイクロポストの画像投稿

この節では、応用編として画像付きマイクロポストを投稿できるようにしてみます。

ほへー。画像も扱うのか…!

投稿された画像ってどこに保存するんだろう。

11.4.1 基本的な画像アップロード

投稿した画像を扱ったり、その画像をMicropostモデルと関連付けするために、今回はCarrierWaveという画像アップローダーを使います。まずはcarrierwave gemをGemfileに追加しましょう (リスト11.55)。

なるほど、画像を扱うためのgemがあってそれを使うのか…!色んなものあるね

Gemfile

gem 'carrierwave',             '0.10.0'
gem 'mini_magick',             '3.8.0'
gem 'fog',                     '1.36.0'

あとで必要になるmini_magick gemとfog gemsも含めている点に注目してください。これらのgemは画像をリサイズしたり (11.4.3)、本番環境で画像をアップロードする (11.4.4) ために使います。

色んなものあるね

いつものようにインストールします。

インストールしましょう。

$ bundle install
  :
Bundle complete! 26 Gemfile dependencies, 116 gems now installed.
Gems in the group production were not installed.
Use `bundle show [gemname]` to see where a bundled gem is installed.

なんか関連するgemがいっぱいインストールされた。

CarrierWaveを導入すると、Railsのジェネレーターで画像アップローダーが生成できるようになります。早速、次のコマンドを実行してみましょう (画像のことをimageとすると一般的過ぎるので、今回はpictureと呼ぶことにします) 。

imageとpictureの違い分かってないや…まぁいっか。。。。

$ rails generate uploader Picture
      create  app/uploaders/picture_uploader.rb

CarrierWaveでアップロードされた画像は、Active Recordモデルの属性と関連付けされているべきです。関連付けされる属性には画像のファイル名が格納されるため、String型にしておきます。(図11.19)

ふむふむ。データベースには画像のファイル名を格納して関連付けるのか。

必要となるpicture属性をMicropostモデルに追加するために、マイグレーションファイルを生成し、開発環境のデータベースに適用します。

マイグレーションしてデータベースを更新。

$ rails generate migration add_picture_to_microposts picture:string
      invoke  active_record
      create    db/migrate/20170629020527_add_picture_to_microposts.rb
$ bundle exec rake db:migrate
  :
== 20170629020527 AddPictureToMicroposts: migrating ===========================
-- add_column(:microposts, :picture, :string)
   -> 0.0005s
== 20170629020527 AddPictureToMicroposts: migrated (0.0006s) ==================

Micropostモデルにアップローダーを追加した結果をリスト11.56に示します。

Micropostモデルにアップローダーを追加。

app/models/micropost.rb

  :
  mount_uploader :picture, PictureUploader
  :

システムによっては、ここで一旦Railsサーバーを再起動させる必要があります。再起動させたらテストスイートを走らせてみてください。成功しているはずです。

今日はサーバーを起動させてないのでそのままテスト実行で大丈夫かな。

$ bundle exec rake test
59 tests, 306 assertions, 0 failures, 0 errors, 0 skips

うん、大丈夫でした。

項の途中だけど今日はここまで。

今日の学習時間は【20分】

次は「11.4.1 基本的な画像アップロード」のHomeページ上にアップローダーを追加するところから。

【157日目】【1日20分のRailsチュートリアル】【第11章】フィード画面におけるマイクロポストのテストを追加する

Ruby on Railsチュートリアル(第3版)

今日は「11.3.5 フィード画面におけるマイクロポストのテスト」から。

11.3.5 フィード画面におけるマイクロポストのテスト

まずはマイクロポスト用のfixtureに、別々のユーザーに紐付けられたマイクロポストを追加していきます (リスト11.51)。

michael以外のユーザーに紐付けられたマイクロポストをいくつか追加。

test/fixtures/microposts.yml

ants:
  content: "Oh, is that what you want? Because that's how you get ants!"
  created_at: <%= 2.years.ago %>
  user: archer

zone:
  content: "Danger zone!"
  created_at: <%= 3.days.ago %>
  user: archer

tone:
  content: "I'm sorry. Your words made sense, but your sarcastic tone did not."
  created_at: <%= 10.minutes.ago %>
  user: lana

van:
  content: "Dude, this van's, like, rolling probable cause."
  created_at: <%= 4.hours.ago %>
  user: lana

次に、自分以外のユーザーのマイクロポストは削除をしようとすると、適切にリダイレクトされることをテストで確認します (リスト11.52)。

michaelがさっき追加したantsのマイクロポストを削除しようとするとルートにリダイレクトされることをテストで確認する。

test/controllers/microposts_controller_test.rb

  test "should redirect destroy for wrong micropost" do
    log_in_as(users(:michael))
    micropost = microposts(:ants)
    assert_no_difference 'Micropost.count' do
      delete :destroy, id: micropost
    end
    assert_redirected_to root_url
  end

最後に、統合テストを書きます。今回の統合テストでは、ログイン、マイクロポストのページ分割の確認、無効なマイクロポストを投稿、有効なマイクロポストを投稿、マイクロポストの削除、そして他のユーザーのマイクロポストには [delete] リンクが表示されないことを確認、といった順でテストしていきます。
いつものように、統合テストを生成するところから始めましょう。

統合テストは盛りだくさんだな…。

まずは統合テストを生成。

$ rails generate integration_test microposts_interface
      invoke  test_unit
      create    test/integration/microposts_interface_test.rb

先ほどの順で書いた統合テストは、リスト11.53のようになります。

ふーむ、サンプルコード読んだら何となく何してるかは分かるかな…。

follow_redirect!って何だろうと思ったけど、リダイレクトを追うコードらしい。
リダイレクトを追ってって、リダイレクト後のページをテストするのか。

test/integration/microposts_interface_test.rb

require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:michael)
  end

  test "micropost interface" do
    log_in_as(@user)
    get root_path
    assert_select 'div.pagination'
    # 無効な送信
    assert_no_difference 'Micropost.count' do
      post microposts_path, micropost: { content: "" }
    end
    assert_select 'div#error_explanation'
    # 有効な送信
    content = "This micropost really ties the room together"
    assert_difference 'Micropost.count', 1 do
      post microposts_path, micropost: { content: content }
    end
    assert_redirected_to root_url
    follow_redirect!
    assert_match content, response.body
    # 投稿を削除する
    assert_select 'a', text: 'delete'
    first_micropost = @user.microposts.paginate(page: 1).first
    assert_difference 'Micropost.count', -1 do
      delete micropost_path(first_micropost)
    end
    # 違うユーザーのプロフィールにアクセスする
    get user_path(users(:archer))
    assert_select 'a', text: 'delete', count: 0
  end
end

既にアプリケーション側のコードは実装してあるので、このテストは成功するはずです。

成功しますね。

$ bundle exec rake test
59 tests, 306 assertions, 0 failures, 0 errors, 0 skips

今日の学習時間は【19分】

次は「11.4 マイクロポストの画像投稿」から。