carrierwave
carrierwaveとは、画像アップロード用ライブラリ
導入
gem 'carrierwave'
アップローダーの作成
bundle exec rails g uploader BoardImage
生成されたアップローダーに以下記述
class BoardImageUploader < CarrierWave::Uploader::Base def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end #デフォルトの画像ファイル指定 def default_url 'board_placeholder.png' end アップロード可能なファイル種別を指定 def extension_whitelist %w(jpg jpeg gif png) end end
アップローダー先のフォルダを.gitignoreに指定することで、アップロードした画像ファイルがGithubにあがらなくなる
/public/uploads
アップローダーをモデル内のカラムに取り付けるためBoardテーブルに画像のカラムを追加
bundle exec rails g migration AddBoardImageToBoards board_image:string bundle exec rails db:migrate
Boardモデルに、アップローダーの仕様を宣言
これによりアップローダをカラムに取り付ける
レコード保存時に自動で、画像ファイルをpublic/uploads配下に保存可能に
DBのboard_imageカラムには画像ファイル名のみ保存される
class Board < ApplicationRecord mount_uploader :board_image, BoardImageUploader belongs_to :user validates :title, presence: true, length: { maximum: 255 } validates :body, presence: true, length: { maximum: 65_535 } end
コントローラーで画像ファイルの入力受付
app/controllers/boards_controller.rb def board_params params.require(:board).permit(:title, :body, :board_image, :board_image_cache) end
app/views/boards/_form.html.erb <%= form_with model: board, local: true do |f| %> <%= render 'shared/error_messages', object: f.object %> <div class="form-group"> <%= f.label :title %> <%= f.text_field :title, class: 'form-control' %> </div> <div class="form-group"> <%= f.label :body %> <%= f.text_area :body, class: 'form-control', rows: 10 %> </div> <div class="form-group"> <%= f.label :board_image %> <%= f.file_field :board_image, class: 'form-control mb-3', accept: 'image/*' %> <%= f.hidden_field :board_image_cache %> </div> <div class='mt-3 mb-3'> <%= image_tag board.board_image.url, id: 'preview', size: '300x200' %> </div> <%= f.submit class: 'btn btn-primary' %> <% end %>
app/views/boards/_board.html.erb <div class="col-sm-12 col-lg-4 mb-3"> <div id="board-id-<%= board.id %>"> <div class="card"> <%= image_tag board.board_image_url, class: 'card-img-top', size: '300x200' %> <div class="card-body"> <h4 class="card-title"> <a href="#"> <%= board.title %> </a> </h4> <div class='mr10 float-right'> <a href="#"><%= icon 'fas', 'trash', class: 'pr-1' %></a> <a href="#"><%= icon 'fa', 'pen' %></a> </div> <ul class="list-inline"> <li class="list-inline-item"> <%= icon 'far', 'user' %> <%= board.user.decorate.full_name %> </li> <li class="list-inline-item"> <%= icon 'far', 'calendar' %> <%= l board.created_at, format: :long %> </li> </ul> <p class="card-text"><%= board.body %></p> </div> </div> </div> </div>
メッセージ追加
config/locales/activerecord/ja.yml ja: activerecord: attributes: board: title: 'タイトル' body: '本文' board_image: 'サムネイル'
config/locales/carrierwave/ja.yml ja: errors: messages: carrierwave_processing_error: '処理できませんでした' carrierwave_integrity_error: 'は許可されていないファイルタイプです' carrierwave_download_error: 'はダウンロードできません' extension_whitelist_error: "は %{allowed_types}の形式でアップロードしてください" extension_blacklist_error: "%{extension}ファイルのアップロードは許可されていません。アップロードできないファイルタイプ: %{prohibited_types}" content_type_whitelist_error: "%{content_type}ファイルのアップロードは許可されていません。アップロードできるファイルタイプ: %{allowed_types}" content_type_blacklist_error: "%{content_type}ファイルのアップロードは許可されていません" rmagick_processing_error: "rmagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}" mini_magick_processing_error: "MiniMagickがファイルを処理できませんでした。画像を確認してください。エラーメッセージ: %{e}" min_size_error: "を%{min_size}以上のサイズにしてください" max_size_error: "を%{max_size}以下のサイズにしてください"
ストロングパラメーター
ストロングパラメーターとは
コントローラーでパラメータを送る際に主に利用される仕組み
受け付けたパラメータが、安全かどうか検証して安全ではないデータの登録、更新を防いでくれる
params.require(:user).permit(:nickname, :email, :password)
上記のコードがあったとするとrequireでPOSTで受け取る値のキーを設定、permitで許可するバリューを設定ができる
これによりparams[:user][:nickname]
params[:user][:email]は受け取ることできるがparams[:nickname]やparams[:email]は受け取ることができない
なぜなら、requireでuserを指定しているからで、カラムもnickname・email・passwordをpermitで指定しているため、それ以外は受け取れない
formヘルパー
formヘルパーとは
Railsの便利なメソッドのうちの一つがformヘルパーで、form_for, form_tag, form_with などがある
ポイント
action属性
入力したものをどのサーバーに送るか指定したものinput要素
サーバーに送信する値。selectやtextareaがあるinput要素のname属性
各項目の識別子
emailは@example.comというように、名前を振り分ける
params[:email]のように書かれているとする
これはformのname属性と紐づいている
渡されてきたモデル(例えばform_with model: @userの@user部分)が空かどうaction="/users"なのかaction="/users/1"を判断して設定してくれる
日時のフォーマットについて
問題
世界標準で日時が表示される
解決法
- タイムゾーンを日本時間に設定
config/application.rb module TimeFormatSandbox class Application < Rails::Application # ... # タイムゾーンを日本時間に設定 config.time_zone = 'Asia/Tokyo' end end
上記の記述で日時が日本時間になる
- フォーマットを変更する
strftimeメソッドで変更可能だが、DRYではなコードになってしまうので、lメソッドを使って実装する
# app/views/boards/_board.html.erb <%= l board.created_at, format: :long %>
ロケールを設定
config/application.rb module TimeFormatSandbox class Application < Rails::Application # ... # デフォルトのロケールを日本(ja)に設定 config.i18n.default_locale = :ja end end
ja.yml time: formats: long: "%Y年%m月%d日 %H時%M分"
すると以下のように表示されるようになる
railsの基準時刻
DB側の時刻設定と、アプリ側の時刻設定が異なる場合、別々の時間表示で保存されてしまうのでアプリケーション作成の段階でRails側の標準時刻と、DB側の標準時刻を合わせておく
renderメソッド オプション
コレクションオプション
一覧表示をする際などに、eachを使用するところを、コレクションオプションを使うことでパフォーマンスを上げることができる
eachを使った場合
コントローラー def index @users = User.all end
ビュー <% @users.each do |user| %> <tr> <td><%= user.name %></td> <td><%= user.email %></td> </tr> <% end %>
コレクションを使った場合
ビュー <%= render partial: "user", collection: @users %>
部分パーシャル <tr> <td><%= user.name %></td> <td><%= user.email %></td> </tr>
ローカルオプション
<%= render partial: 'product_body', locals: { product: @product } %> 省略形 <%= render 'product_body', product: @product %>
localオプションを使うことで、インスタンス変数をローカル変数にしてパーシャルに渡すことができる
パーシャルにインスタンス変数を渡さないほうがいい理由
パーシャルは呼び出し元のテンプレートとだけ紐付けしたほうがいいから
インスタンス変数を使うと、コントローラーとも結びつき再利用性が低くなってしまう
controller側でインスタンス変数の名前や挙動を変更したとき、partial側も変更しなければならなくなる。
特定のモデルのデータと関連づけられてしまうので、フレキシブルに使うことができない。