Ruby on Rails
基礎5

  • 前回は、スキャフォールドで作ったサイトを参考に、モダンな書き方に直しました。
  • ほぼサイトは出来上がりましたが、最後に【画像】をアップロードできるようにして、完成としたいと思います。

前回の確認

  • 本格的なサイトで画像をアップロードさせる際に、考えることがあります。それは画像を【どこのサーバに保存しておくのか?】です。
  • どこのサーバってサーバは1つじゃないの?」と思うかも知れませんが、基本的にサーバは複数ある場合がほとんどです。
  • まずはそのサーバについて、理解しておきたいと思います。次へ。
  • 【サーバとはクライアント(ブラウザなど)からのリクエスト(要求)に、レスポンス(反応)するもの】を言いますが、これはかなり広い意味でのサーバです。
  • サーバには色々種類があり、基本的なWEBサイトなどでは【WEBサーバ】【アプリケーションサーバ(APサーバ)】【データベースサーバ(DBサーバ)】の3つが最低限使われています。これを【WEB3層構造(ウェブさんそうこうぞう)】と言います。
  • DBサーバ】に関しては、前にやりましたので、わかりやすいと思いますが、【WEBサーバ】【APサーバ】の違いがややこしいですね。
    • ​​​【WEBサーバ】とは、ブラウザからのリクエストを受け取り、レスポンスするサーバ(そのまんま)なのですが、その過程で、動的な処理(プログラミング処理)が必要な場合のみ【APサーバ】に処理を依頼(リクエスト)し、データベースのデータが必要であればDBサーバ】にデータをリクエストします。そして、その最終的な結果をクライアントにレスポンスする、という動きになります。
    • APサーバ】とは、上の通り、WEBサーバから動的な処理のリクエストがくれば、その処理を行い、WEBサーバにレスポンスするサーバです。​言わば計算役です。

サーバとは?

  • ただし【サーバが3つだからと言って、PCが3つあるわけではない】ということに注意してください。
  • ここでいう各サーバは【ソフトウェア】の種類であって、【ハードウェア】ではありません。
  • つまり【1つのPCに3つのサーバ】がある場合だってあります。※今作ってるサイトはコレです。
  • 一般的にはWEBサーバ】【APサーバ】は同じPCで、【DBサーバ】だけ別のPCが多いです。
    • ​これは【DBサーバ】は切り離した方が、柔軟に拡張・メンテナンスしやすいからです。
  • では画像・動画を保存するとする場所としてはどこが最適でしょうか?
  • 普通に考えればDBサーバ】なように思いますよね?でも、これはあまりよろしくない手です。
  • 基本的なWEBシステムにおいて、【WEBサーバ】と【DBサーバ】とのやりとりが、一番遅くなりやすいので、画像や動画などをDBサーバ】に保存してしまうと全体的なレスポンスが非常に遅くなりがちです。
    • ​※ただし、そういう設計のサイトもかなりありますので、仕方がない場合もあるかもしれませんが
  • 以上のことから、画像などは【WEBサーバ】内に保存しておく方が良いのです。
    • もっと正しく言うと【WEBサーバ】内に、画像・動画保存用の【ファイルサーバ(メディアサーバ)】の領域を用意して使うイメージです。
  • ただし、YouTubeやSNSなど、画像・動画がどんどん増えるサイトは、別のPCを用意して【画像・動画保存専用サーバ】とする方が良いでしょう。

サーバとは?

  • では、まずは画像をアップロードしてみましょう。
  • Railsで画像の保存用に用意されているフォルダ(app/assets/images)がありますので、そこにアップロードします。
  • images】クリックしてください。※自分のマイbookサイトのです。スキャフォールドで作った方は、もう使いません。
  • 画面上のメニューから【File】を開き、【Upload Local Files...】を選択します。次へ。

画像のアップロード方法

  • 下のようなウインドウが出るので、そこに画像をドロップします。

画像のアップロード方法

  • そうすると、画像がアップロードされます。
  • 自分の登録している本に合わせた画像を探してきて、アップロードしてください。※1つだけでOK。
  • 後は画像の表示方法です。
  • 以前、静的なページを作った際に使ったのは<img>タグでしたが、Railsでは専用のメソッドがありますので、それを使いましょう。
  • image_tag '001'】のように、image_tag "ファイル名"】を入力するだけで、画像が表示できます。拡張子も不要で解釈してくれます。
    • ​つまり、【image_tag '001'】だけで、HTMLで<img src="/assets/images/001.png"  >】というように指定しているのと同じことになります。画像へのパスがとても短く書けますね。

画像の表示

ためしてみよう

  • 試しにshowファイルに、画像の項目を用意し、適当な画像を表示させてみましょう。​
    • ​※現段階では、どの本のshowを開いても同じ画像が表示されます。
  • さて、画像の表示方法はわかりましたが、本当にやりたいことは【登録した本ごとの画像】を表示させたいはずです。
  • つまり、名前や評価と同じように、動的にデータベースから取り出して表示させたいということです。
    • DBサーバ】には保存しない、と言いましたが、それは画像本体の話です。
  • じゃあ何を保存すれば良いかと言うと【画像へのパス】です。
  • 先ほどのimage_tagメソッドを使えば【ファイル名】の部分だけがパスとなりますので、このファイル名だけを、DBサーバに保存出来れば良いということですね。
    • 次へ。

画像の表示

  • まずは、画像のファイル名(パス)を保存するためのカラムが必要ですね。
  • img_path】というカラムを追加しましょう。【rake db:migrate】も忘れずに行いましょう。

画像の表示

  • 次にフォームに画像アップロード用のフィールドを用意します。
  • 「評価」と「感想」のフィールドの間にでも追加しましょう。(どこでも良いですが)
  • ファイルアップロード用のフィールドは【file_field】と指定します。
  • それに紐付いたパラメータとして、【img_file】となっていますが、これは後で区別をつけやすいようにあえてしています。
    • 今まではこのパラメータ名はカラム名でしたが、本当は必ずしもカラム名にする必要はありません。
  • まだ【ファイルを選択】をクリックして、ファイルを選んでも保存されません。
  • 次にコントローラー側で、アップロードファイルを受け取る設定をしていきます。

画像の表示

  • 現時点ではこんな感じです。
  • upload_file】はただのローカル変数です。これに【params[:book][:img_file]】を代入しています。
  • [:img_file]は先ほどのフィールドのパラメータ、つまりアップロードした画像データですね。
  • このアップロードした画像データ[:img_file]は、ハッシュ形式になっており、ここから画像に関するデータを取り出すことができます。次へ。

画像の表示

  • フォームのパラメータを受け取るのは、【create】メソッドと、【update】メソッドでしたね。
  • まずは、create】メソッドの方に作っていきます。以下のコードを追加してください。
  • これで、ファイル名(画像のパス)がカラムに代入できました。
  • 後は、画像本体を【app/assets/images】のフォルダに保存出来れば完璧ですね。
  • このような処理は初めて行いますので、ちょっと見慣れない書き方が出てきます。次へ。

画像の表示

  • まず、今回データベースに入れたいのは【ファイル名】でしたね。
  • ファイル名を取得するには画像データに【.original_filename】を付けます。つまり【upload_file.original_filename】となります。
  • これを先ほど作ったカラムに代入します。
  • File.open()】メソッドはローカルファイルに対して【読み込み(開く)】したり【元のファイルに追加で書き込み】したり、【新しいファイルを作成してから書き込み】したり、することができるメソッドです。今回の場合は【新しいファイルを作成してから書き込み】として使います。
    • 第1引数に、【app/assets/images/#{@book.img_path}】とすることで、作成する場所の指定をしています。
      • #{@book.img_path}】の部分は【式展開】という書き方で、【文字列の中に式(1+1などの計算や、または変数のこと)を埋め込む】ことができます。
        • つまり、この式の結果が(変数なら中身)が文字列に置き換わるという動きです。
      • 第2引数は、モードの設定(読み込みなのか、新規作成なのかなど)です。今回は、【新しいファイルを作成してから書き込み】である【w】と、バイナリモードで書き込むための【b】を組み合わせて【wb】として使っています。※画像はバイナリ(0か1の2進数のこと)で書き込む必要があります。次へ。

画像の表示

  • 以下のように書くと、app/assets/images】に画像が保存できます。

画像の表示

  • 最後に【File.open()】メソッドの中の【f.write(upload_file.read)】の部分です。
  • f.write()】が実際にデータを書き込むメソッドで、引数の【upload_file.read】が画像本体の読み込みです。
    • ​ファイル名の取得は【upload_file.original_filename】でしたが、画像本体の場合は【upload_file.read】になるということです。
  • ​【f.write(upload_file.read)】によって、実際に画像が【app/assets/images】に保存されることになります。
    • ​正解には保存ではなく、【アップロードされたのと同じデータを、サーバ内に新しく作成し直す】という動きです。

試してみよう

  • では、試しに画像付きで新しい本を登録してみましょう。
    • ※変化がわかりにくいので、先ほど試したのとは違う画像を用意して、アップロードしましょう。
  • 登録が出来たら、アップロードした画像がちゃんと表示されるようにしましょう。
    • ヒント:showファイルの画像のパス部分をデータベースのデータに変更しましょう。※""は不要です。また、controllerのストロングパラメータも追加が必要です。ここで追加するのは【変更を許可するデータベースのカラム名】の方です。フォームから渡されてくるパラメータ名ではありません。

画像の表示

  • さて、これでうまくいったように見えますが、実はちょっとバグがあります。
  • 新しいファイルを追加する際に、画像を追加しないとエラーになってしまいます。
  • バリデーションでのエラーではなく、システムのエラーとしてお馴染みの画面が開いてしまいます。
  • エラー画面に書いてる通り【@book.img_path = upload_file.original_filename】の行でのエラーですが、これは、画像がアップロードされていない、つまり【upload_file】が空(nil)なのに【upload_file.original_filename】でファイル名を呼びそうとしているため、起こるエラーです。
  • このサイトでは、画像のアップロードは必須ではないようにしたいので、画像がなくてもエラーにならないようにしたいと思います。次へ。

試してみよう

  • 下の画像を参考に、画像のアップロードをしなくても、エラーにならないようにしてください。
    • ヒント:画像がない場合は、【upload_file = params[:book][:img_file]】が【upload_file = nil】と同じことになります。そのため【nil】じゃない時にだけ、【@book.img_path = upload_file.original_filename】および【File.open()】の処理をすれば良いということですね。

画像の表示

  • これで画像を付けても、画像をつけなくても、本を追加することが出来るようになりました、、まだ実はバグが残っています。
  • それは【バリデーションエラーで、データは登録されなくても、画像だけがアップロードされてしまう】というバグです。
  • 例えば、本を新規作成する際に、本のタイトルを記入しないで登録した場合でも、本のデータは登録されなくても、画像だけはこっそりアップロードされてしまうという状況になっています。
  • なぜこれが起こるかというと【book.save】メソッドの前に、画像の保存(新規書き込み)をしているからです。
  • 本来【 if @book.save】の部分で【保存OK・アカン】を切り分けていますが、その外でFile.open()】をすると、【保存OK・アカン】は関係なく実行されてしまいます。
  • ということで、【保存OK】の場合だけ実行させようとすると、【 if @book.save】がtrueの中で、実行させれば良いということになります。
    • ​次へ。

画像の表示

  • ただし、単純に以下のようにすると、今度は【@book.img_path】が保存されなくなります。
    • ※白枠は前の問題の場所なので消しています。
  • なぜかというと、@book.img_path】はデータベースの保存に関係する場所なので、【book.save】の前にないといけないからです。
  • さて、ちょっと面倒なことになってきましたが、ここは次のようにして解決したいと思います。
    • ​次へ。

画像の表示

  • 以下のように、book.save】を増やしちゃいいます。
  • これで、データの保存に成功した時だけ、画像もちゃんとアップロードされることが可能になります。※まぁこのコードはあまりイケてないので、もっと良い方法あると思います…。

画像の表示

  • さて、これで画像を付けて本を追加することが出来るようになりました。
  • 次は本の編集の時も、画像をアップロード出来るように、updateメソッドにもアップロード処理を追加しましょう。これは、createメソッドとまったく同じ内容でOKです。
  • ただ、このままコピペしては、【同じコードは書かない】というDRYの思想に反することになりますので、アップロード部分の処理をメソッド化して使いたいと思います。
    • 次へ。

試してみよう

  • アップロード部分の処理をメソッドにまとめ、createメソッドとupdateメソッドから呼び出して使うようにしてください。
  • メソッドは【upload】という名前にし、プライベートメソッドにしておきましょう。
    • ヒント:【before_action】から呼び出すと、@book変数が用意されていない状態で呼び出されてしまいますので、createメソッドおよびupdateメソッドの中から【upload】メソッドを呼び出しましょう。メソッドの呼び出しは単純に【upload】と書くだけです。
  • 画像の新規登録、編集は完成しました。
  • ただ、現在は画像登録のない本は以下の表示になってしまいます。

デフォルト画像

  • このアイコンは基本的に【画像がみつからない】というアイコンです。
  • なので、画像が登録されていないだけなのに、システムエラーで画像が見つからないように見えてしまいます。
  • そのため、ほとんどのサイトでは【デフォルトの画像】(画像登録がない場合の画像)を用意して、それを表示させています。
    • 次へ。
  • 今回はデフォルト画像として、以下の画像を使います。
  • 同じにしなくても良いので、好きな画像を選んでください。同じ画像にする場合は右クリックでダウンロードして使ってください。

デフォルト画像

  • デフォルト画像が用意出来たら、サーバにアップロードしておきましょう。

試してみよう

  • showページを表示する際に、画像がない本は、デフォルト画像が表示されるようにしてください。
    • ヒント:イジるのはbookのshowファイルだけでOKです。【@book.img_path】が空なのか?を調べて、条件分岐させれば良いですね。※もちろん、画像がある場合は、その画像が表示されないといけません。
      • なお、カラムが空かどうかを調べるには【 if @book[:img_path] 】としてください。
        • この場合、空ならfalse、なにかしら入っていればtrueとなります。
          • ※完成したらみせてください。
  • これで画像の追加は完了です。と言いたいところですがまだあります。それはバリデーションです。
  • 画像に関してのバリデーションは少し複雑になり、複数項目でのチェックが必要になります。最低限必要な項目としては以下の2点です。
    1. 【ファイルの種類】→画像として表示できない形式のファイルがアップされても困るため。
    2. 【画像のサイズ】→デカすぎるサイズの画像がアップされるとサーバの容量が苦しくなるのと、ページの表示に時間がかかることになり、サイト全体が重くなるため。
  • この2つはバリデーションをしたいですが、文字の長さを制限する【length: { maximum: 130}】のように、Rails側で簡単なメソッドが用意されていません。
  • メソッドを自作したりも当然できますが、ちょっと面倒なことが増えていきます。
  • このように、画像のアップロードは文字以上に考えることが多いので、ややこしくなりがちです。
  • そのため、そこらへんの問題を簡単に解決出来るgemを使いたいと思います。次へ。

画像のバリデーション

  • 画像のアップロード用として、【carrierwave】(キャリアウェーブ)というgemを使います。
    • これはRailsで画像のアップロード機能をつける時は必ずといって良いほど使われているgemです。
  • ではgemを追加するために、【Gemfile】に追加しましょう。

carrierwave

  • Gemfile】に追加した後は、【bundle install】というコマンドが必要でしたね。コンソールに打ち込みましょう。これで【carrierwave】のインストールは完了です。次へ。

carrierwave

  • 次に設定のための、手順です。
  • rails g uploader img_path】というコマンドをコンソールに打ち込んでください。
    • ​これは、【carrierwave】のコマンドで【img_path】カラムに紐付けてファイルをアップロードするという設定のために必要なコマンドです。
  • 最後に、bookのmodelファイル(book.rb)に【mount_uploader :img_path, ImgPathUploader】というコードを書き込みます。
  • ここまで出来たら、一旦サーバをOffにした後、再度Onにしてください。次へ。
  • あとは、フォームの内容も一部変更しておきます。
  • 下記のように、【:img_file】だった場所を:img_path】にしておいてください。
  • 設定は終わったので、controllerのcreateメソッドを以下の状態に戻してください。
    • ※uplodeメソッドなどを外した状態です。

carrierwave

  • これは画像の追加を始めるの前と同じはずです。
  • つまりcarrierwave】の設定以外は、何もしていない状態です※ストロングパラメータに【img_path】を追加はしている。
  • これだけで、画像のアップロードは出来るようになっているので、試しに画像アリの本を追加し、showファイルから確認してみましょう。
  • うまくいきましたか?
  • このようにcarrierwave】を使うと、【ファイルのパスをデータベースに保存】したり、【サーバに画像データを保存(新規作成)】の部分、つまりロジック部分をやってくれるので、ストロングパラメータをイジるだけで画像のアップロードが出来るようになります。
  • ちなみに、【画像の置き場所】に関して前に言いましたが、【carrierwave】も【データベースにはファイルのパスだけ】で、【画像データ自体はWEBサーバに置く】という方法を行っています。
    • そのため、showファイルをイジらずに、アップロードした画像が表示されているわけです。
    • ​​画像データの本体は、【public】→【uploads】→【img_path(カラム名)】→【ID番号】のフォルダに保存されていきます。

carrierwave

  • さて、次は画像のバリデーションの実装です。
  • まずはファイルの種類のバリデーションから行いましょう。
  • 以下の【uploaders】フォルダの【img_path_uploader.rb】ファイルを開いてください。
    • このフォルダはcarrierwave】を追加した時、【rails g uploader img_path】コマンドで作成されています。

ファイルの種類のバリデーション

  • このファイルの以下のメソッド部分をアンコメント(コメント解除)してください。(38行目だと思います)

carrierwave

  • この【extension_whitelistメソッドは、見たとおりファイルの拡張子(種類)を【jpg、jpeg、gif、png】のどれかに制限するメソッドです。これ以外のファイルがアップロードされたら、その時点でエラーになります。試してみましょう。※試すファイルは上記以外なら、なんでも良いですが◯◯.htmlなど適当なファイルを作っても良いです。わからなければ聞いてください。
  • 下のようなエラーが出ると思います。
  • ちゃんとバリデーションが出来ていますね。翻訳はまだなのでしておきましょう。翻訳といえば【ja.yml】ですね。
  • carrierwave】でのエラーをまとめで追加しておきたいと思います。以下のように【ja】以下のコードを追記してください。※元のコードは省略していますが、消さないでください。

carrierwave

ja:
    errors:
        messages:
          carrierwave_processing_error: 処理できませんでした
          carrierwave_integrity_error: は許可されていないファイルタイプです
          carrierwave_download_error: はダウンロードできません
          extension_whitelist_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできるファイルタイプ: %{allowed_types}"
          extension_blacklist_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできないファイルタイプ: %{prohibited_types}"
          rmagick_processing_error: "rmagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}"
          mini_magick_processing_error: "MiniMagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}"
          min_size_error: "ファイルを%{min_size}バイト以上のサイズにしてください"
          max_size_error: "ファイルを%{max_size}バイト以下のサイズにしてください"
  • 下のような感じになると思います。※拡張子aiファイルをアップロードした例です。

carrierwave

  • 【Img path】の部分だけ翻訳されてませんね。これはカラム名の【img_path】のことです。
  • これも翻訳しておきましょう。次へ。
  • 下の表示になるようにしてください。※拡張子aiファイルをアップロードした例です。

試してみよう

  • 次は、サイズに関してのバリデーションを行いましょう。
  • これも簡単で、img_path_uploader.rb】ファイルに以下のように追記してください。

carrierwave

  • このように書くことによって、【0バイトから1メガバイトまで】のバリデーションを行えます。
    • バイトやメガバイトとはデータの容量(サイズ)を表す単位です。詳しくは次のページでやります。
  • このドットを並べた【..】は【範囲演算子】といって、範囲を表す書き方です。
  • 数字部分も含めた【0..1.megabytes】全体で【範囲式】と言います。​
    • 尚【.megabytes】をつけることによって【メガバイト】単位であることを示します。他にも

      キロバイトは.【.kilobytes】、ギガバイトは【.gigabytes】をつければその単位であることが示せます。※【1メガバイトから10ギガバイトまで】は【1.megabytes..10.gigabytes】など

  • ちなみに、上記の【0..1】のようにドットが2つ場合だと【0バイトから1メガバイトまで】でしたが、【0...1】のようにドット3つの書き方もでき、その場合は1未満(右端の数字自体は含めない)という意味になります。
  • バイトやメガバイトなどの言葉が出てきましたが、コンピュータの世界で使われる基本的なデータ単位は以下のようになっています。
    • ビット(bit)→ 最小単位
    • バイト(byte, B)→ ビットが8個分。【8bit = 1B】
    • キロバイト(kilobyte, KB)→ バイトが1024個分。【1KB = 1024B】
    • メガバイト(megabyte, MB)→ キロバイトが1024個分。【1MB = 1024KB】
    • ギガバイト(gigabyte, GB)→ メガバイトが1024個分。【1GB = 1024MB】
    • テラバイト(terabyte, TB)→ ギガバイトが1024個分。【1TB = 1024GB】
    • ペタバイト(petabyte, PB)→ テラバイトが1024個分。【1PB = 1024TB】
      • 30年前ごろの古いパソコンや、特殊なコンピュータでは【8bit = 1B】ではないですが、ほぼ存在しないので、気にする必要はありません。​​

データ容量の単位

データ容量の単位

  • 1ビットの中には【0か1】(言い方を変えれば、truefalseか)の情報しか保存できません。つまり【2パターン】の情報だけです。
  • では【2】という数字を保存したい場合はどうなるでしょうか?
    • 実は1ビットでは【2】という数字は保存できないため、2ビット分を使って保存します。
  • ただ、2ビット使うと言っても、それぞれのビットで使える数字は【0か1】だけです。この【0と1】だけで【2】という数字を表現しなくてはいけません。
    • 【0と1】だけで【2】を表現するためには【10】と書きます。不思議な感じですよね?
    • 【3】なら【11】
    • 【4】なら【100】
    • 【5】なら【101】
    • 【6】なら【110】
    • 【7】なら【111】
    • 【8】なら【1000
    • 【9】なら【1001
    • 【10】なら【1010】になります。なんとなくルールがわかりますか?
  • このように【0と1】だけで数を表現する方法を〘2進法(しんほう)〙と言います。(言い方を変えると、2になった時に桁(ケタ)が変わる方法)
    • 逆に普段使っている【0から9】で、数で表現をする方法のことを10進法〙と言います。

データ容量の単位

  • さて、データの最小単位は1ビットと言いましたが、1ビットは小さすぎるため、それをまとめた1バイト(8ビット)が、パソコン上での保存サイズの最小単位になっています。
    • つまり【2】という数は2bitで表現できますが、実際には1バイトの容量を使います。つまりパソコン内では【00000010】という形で保存されることになります。
  • 1バイトになると【256パターン】の情報が保存できます。
    • ※ビット(2パターン)が8個分だからと言って、16通りではないので注意しましょう。パターン数とはビット数ではなく、組み合わせ数なので2×8ではなく2^8(2の8乗)です。つまり【2×2×2×2×2×2×2×2】です。​
  • 1バイト【256パターン】ですが、1キロバイト(1バイトの1024倍)になると、どれくらいのパターン数になるでしょうか?実は、これはもうここに表示しきれないパターン数になります。
  • 例えば、1バイトを2倍ずつさせてみると、以下のように数がトンデモない速度に増えていきます。
    • 2バイト(16bit)→【256^2(2^16と同じ)= 65536】
    • 4バイト(32bit)→【65536^2(2^32と同じ)= 4294967296】
    • 8バイト(64bit)→【4294967296^2(2^64と同じ)= 18446744073709551616
    • 16バイト(128bit)→【18446744073709551616^2(2^128と同じ)= 3402823669209384634
      63374607431768211456】
      • このように、16バイト(16倍)の時点で、トンデモない数字になるので1キロバイト(1024倍)は文字通り【書ききれない】ですし、正確な数字をコンピュータに計算させるのも非常に大変です。仮に計算できたところで、人間の感覚で理解できる数の限度を超えるので、意味がありません。

データ容量の単位

  • ちなみに、1億を超えるようなデカイ数を計算すると、大体の電卓では表示できずに【◯◯E+◯◯】というような、ナゾの表示になります。(◯の部分はなんらかの数字、Eは小文字の場合もあり)
  • 例えば、Macに付属の電卓で100000000(1億)×100000000(1億)の計算をさせて見ると【1e+16】と表示されますが、これにはちゃんと意味があって【1×10の16乗(1×10^16)】という意味になります。※累乗(10^16の部分)は、かけざんより先に計算されます。
    • つまり【1e+16】は【10000000000000000】を表しています。※1と、0が16個
    • ​​​このような表示方法を【指数表記(しすうひょうき)】と言います。
  • もう1つ試してみましょう。
    • 先ほど8バイトの場合のパターン数【4294967296 ^ 2】つまり【4294967296 × 4294967296】の計算を、Macに付属の電卓にさせてみると【1.8446744e+19】と表示されました。
    • これは【1.8446744 × 10の19乗(1.8446744 × 10 ^ 19)】という意味で、結果は【18446744000000000000】になります。※18446744と、0が12個
      • アレ?4294967296^2の答えは【18446744073709551616】のはずです。
        • そう、これは細かい数を切り捨てされて表示されているのです
      • このようにほとんどの電卓では一定の数以上は正確な計算ができません。(電卓の性能によります)
        • またどんどん数字を増やしていくと、電卓はエラーになります。パソコンも同じようにとんでもない数字は計算自体ができなくなります。
  • ちなみに、一般的に販売されているHDDなどの容量は少し計算方式が違って、1024倍ではなく1000倍での計算になっています。つまり「1TBのHDD」として売られていても、パソコンにつなぐと、931GBしかありません。※B→KB→MB→GB→TBなど、すべて1000倍で、呼び方が変わります。
  • 普通に考えて「詐欺じゃねーか!」と思いますが、これは解釈の違いなので詐欺にはならないです。(ちょっと悪質な感じはしますが)
  • というのも、パソコンは1TBを1024GBで認識しますが、1TBは1000GBでも間違いではなく、むしろメートルなどの数え方と同じになるので、こちらの方がわかりやすかったりします。
    • つまり、これは【B→KB→MB→GB→TB】の規格が、あやふやの状態だから起こってしまう現象です。
  • これじゃイカン!と新たな規格として【キビバイト(KiB)→メビバイト(MiB)→ギビバイト(GiB)、テビバイト(TiB)】という規格が考え出されました。
  • このB→KiB→MiB→GiB→TiB】は、必ず1024倍であることを意味します。つまり1TiB(テビバイト)は、”絶対”に1024GiB(ギビバイト)であるということです。
    • ​ただ、これはあまり知られていないので、ほとんど使われません。結局はあやふやなまま【B→KB→MB→GB→TB】が、1000倍の場合も、1024倍の場合でも使われています。
      • ​※パソコン上では、【B→KB→MB→GB→TB】でも、すべて1024倍で統一されています。

データ容量の単位

  • さて、だいぶ脱線しましたが、画像サイズのバリデーションの途中でした。
  • 下のコードで【0バイトから1メガバイトまで】の意味になりましたが、ちょっと最大1メガバイトでは物足りませんね。
  • また、0バイトのデータ(空ファイル)というのは本来存在しません(最低1バイトの領域を使うので)。もしあるとすると、わざと作成したか、壊れたデータの可能性が高いです。そのため、アップロードできるのは1バイトからにしておきたいと思います。次へ

carrierwave

試してみよう

  • 画像のサイズを【1バイトから、10メガバイトまで】アップロードOKに変更してください。

試してみよう

  • もう一つのサイトにも同じことをしてください。
    • ※完成したら見せてください。
  • さて、以上で画像のアップロードも完了です。
  • 残りは動画ですが、基本的には画像のアップロードと同じです。てかアップロード方法自体はまったく同じでOKです。
    • 違う点としては、表示させる時に画像では【image_tag】を使いましたが、動画の場合は【video_tag】で表示させます。(HTMLでは<video>タグに変換されます)
  • ただし、動画の場合は考えいけないことが沢山あります。
  • 画像でも容量を気にするという話をしましたが、動画の場合はより容量問題が大きくなります。(基本的に、画像の10倍以上の容量になるので)
  • そのため、動画を直接アップロードできるサイトというのは、YouTubeなど極々一部のサイトだけです。これは膨大な動画を保存しておくサーバを用意するには費用がかかりすぎるからです。
    • つまり個人サイトで動画をアップロード可能にするのは現実的ではありません。

動画のアップロード

  • そこで、よく用いられるのが【YouTubeに動画をアップして、その動画を自分のサイトに埋め込む】という方法です。動画の保存場所をYouTubeにしてしまうということです。
    • これで容量問題は完全に解決します。
  • また、この方法にしておけば自分で動画を用意する必要がなく、YouTubeにある動画をそのまま使えます。
    • ※他人の動画でもサイトに埋め込んで使うのまったく問題がありません。
    • ※勝手にダウンロードして使うのはギリアウトです。
  • ということで、今回は動画のアップロードではなく【動画の埋め込み】方法で進めましょう。まず、新しいカラムを追加します。
  • カラムの追加のコマンドは【rails g migration クラス名 カラム名:型】でしたね。
    • 今回は、クラス名は【AddIframeToBook】、カラム名は【iframe】、型は【文字列型】にしておきましょう。
    • ※【iframe】(インナーフレーム)とはHTMLタグの1つで、WEBページに、別のページを埋め込むためのタグです。特に動画の埋め込みによく使われます。またアイフレームと呼ぶ人も多いです。
  • 後は、【rake db:migrate】もしておけばカラムの追加はOKです。

動画の埋め込み

  • 次は、【①ファームにiframeフィールドを用意すること】と【②ファームから渡されてきたパラメータをストロングパラメータで受け取れるようにすること】と【③iframeで動画を表示すること】が必要になりますね。

試してみよう

  • 【①ファームにiframeフィールドを用意】と【②ファームから渡されてきたパラメータをストロングパラメータで受け取れる】ようにしてください。
    • ​ヒント:①で用意するフィールドタイプは、【f.file_field】ではなく、【f.text_field】でOKです。※ファイルのアップロードはしないため。
  • さて、最後は【③iframeで動画を表示すること】だけです。
  • まずは、【iframeで動画を埋め込む】基本的な方法をやっておきましょう。
  • YouTubeのサイトを開いて、好きな動画を1つ選んで、その動画のページを開いてください。
    • ※今回はYouTubeに、すでにある動画を使って進めてください。
  • その動画の下に【共有】というボタンがあるので、それをクリックしてください。

動画の埋め込み

  • ウィンドウが開くので、さらに【埋め込む】をクリックしてください。次へ。
  • さらに開いたページに表示されている<iframe>から</iframe>までのコードが、この動画を埋め込んで表示するためのコードです。

動画の埋め込み

  • このように、埋め込みコードはYouTube側が作ってくれています。後はこのコードを自分のサイトにコピペすれば良いだけです。
  • 上の赤枠部分をコピペしておきましょう。次へ。
  • では実際に、自分のサイトに表示させるのですが、まずは試しにbookのindexファイルの一番上にでも貼り付けて表示させてみましょう。
  • 下のようになればOKです。

動画の埋め込み

  • カンタンですね。次へ。※今、indexページに追加したコードは消しておきましょう。
  • 例えば、indexページに表示させるだけであれば、このように貼り付けるだけで終わりですが、今回は本によって動画を切り替えて表示させる(動的サイト)ので、当然このままでは終わりません。
    • そう、先ほど作った【iframe】カラムに追加して、本ごとに切り替えて表示させるわけです。
  • 動的に表示させるのはshowファイルなので、showファイルを開き、以下のコードを追加してください。※場所は画像の下らへんがいいかと思います。

動画の埋め込み

  • これで、【iframe】に入れたものが、そのまま表示されることになりますね。
  • つまり、iframe】に、YouTubeからコピペしたコードを登録しておけば表示されるはずです。
    • ​とりあえずやってみた結果が下です。
  • 実はこれだけでは、データベースから表示させることが出来ません。
  • 上のようにコードだけが表示されていると思います。一旦ここまで試しておいてください。
  • なぜこの現象がおこるかと言うと、Railsでは【<%= %>で、HTML特殊文字(<>など)を出力する時は、必ずHTML特殊文字ではない形式で出力する】というルールが働いています。
    • ※見た目は【<>】でもHTMLの【<>】ではなく、文字列としての【<>】となっているということです。
  • これはセキュリティ対策の一種で、勝手にHTMLコードを登録されて、実行されないために自動で制御してくれているということです。
    • バリデーションの時に入力内容を制限するのと同じように、出力する側でもセキュリティ対策をしてくれているというわけです。
  • このように、特定の意味を持つコードを、無害な文字列に変換すること【エスケープ】と言います。

動画の埋め込み

  • さて、このエスケープを解除して表示させる方法もあるのですが、解除してしまうとセキュリティリスクが高まりますので、少し方法を変えます。
  • ポイントとしては、【HTMLコードは出力させない】ようにすれば良いので、埋め込みに必要な<iframe>タグの部分をshowファイルに直接記入し、【iframe】カラムに入れるのは【動画識別コード】だけにすれば良いのです。次へ。
  • 【動画識別コード】とは以下の部分です。
  • 【<iframe width="560" height="315" src="https://www.youtube.com/embed/ココの部分" frameborder="0" allow="autoplay; encrypted-media" allowfullscreen></iframe>】
  • 【動画識別コード】の部分だけを動的に切り替える、つまりデータベースに入れておけば、セキュリティを保ちながら、YouTube動画を表示できるというわけです。
  • 【動画識別コード】以外の部分に関しては、showファイルに直接書いておきましょう。

動画の埋め込み

試してみよう

  • bookのshowファイルを変更し、動画を表示できるようにしてください。
    • ※すでに登録済みの【iframe】のデータは編集で変更しておきましょう。
  • さて、動画の表示はできるようになりましたが、【動画を登録していない本】に関しては、以下のように、動画がエラー状態として表示されます。

動画の埋め込み

  • ということで、これも直しておきましょう。
  • やることは画像と同じように【iframeカラムに文字が入っていれば表示】することです。
    • 何も入っていなければ何も表示させなくて良いでしょう。※画像の時は「デフォルト画像」を表示させていましたね。

試してみよう

  • 動画が登録されていれば表示され、登録されていなければ何も表示されないようにしてください。
    • ※画像の時は【if @book[:img_path] 】で判定を取りましたが、f.text_fieldの場合は何も登録していなくても【""】というデータが入っていますので、同じやり方だと常にtrueになります。
    • そのため【iframeカラムのデータが、""ではない時】という条件を作る必要があります。
      • ※完成したら見せてください。
  • さて、以上で動画の表示も完了です。
  • 本当はもっと色々やることは考えられるのですが、キリがないので、ひとまずの完成としたいと思います。
  • 基礎的なことは結構やりましたが、まだまだ奥の深いのWEBの世界です。【やりたいこと】を実現するには、色んな壁が出て来るでしょう。
  • わからないことが出てきた時に【こんなん習ってないからわからない】と思いたくなるでしょうが、【プログラミングはほとんど基礎の応用。同じ状況などほとんどない】ということを理解しておいてください。
  • 【1+2=3って習ったからわかるけど、2+1は習ってないからわからない】と言っているのと同じです。
    • つまりは【1+2】の答えを学ぶのでなく、【+】という演算子のルールを学ぶのです。これはプログラミングも同じです。
  • また、問題解決のための情報はインターネット上に大体あります。
  • つまり、後は、必要な情報を調べて取り出すことが出来れば良いだけです。ここまで進んでこれた人なら、そのレベルには達してます。
  • 大事なことは【今、なにに悩んでいるか?】を、いかに具体的に出来るかです。
  • 具体的な問題点が理解出来れば、インターネット社会において、それを調べることはカンタンなのです。
    • まぁこれが意外と難しく、社会人においても重要なスキル(問題解決力・論理的思考力)とされています。

完成

  • Railsに関してはひとまず終わりです。
  • 次のステップは相談してください。

お疲れ様です。