【備忘録】三項演算子を使ってif文を省略
今回は三項演算子を使って、if文を省略して書く方法についてです٩( ᐛ )و
簡潔にまとめると、このif文が、
if xxx yyy else zzz end
三項演算子を使って短く書くと、こうなります。
xxx ? yyy : zzz
具体的に例を書いてみます。
bird = 'penguin' bird == 'penguin' ? (puts 'You can swim!') : (puts 'You can fly!') => You can swim!
birdがペンギンだったら'You can swim!'を、ペンギン以外だったら'You can fly!'が表示されるようにしました。
ちなみに下のように?が2つあっても驚かないでください。
price = '' default_price = 100 price.empty? ? (puts default_price) : (puts price) => 100
empty?という真偽判定を行うメソッドを使っています。 つまり、「priceは空ですか?」という判定をしていて、trueの場合はdefault_priceを表示し、falseの場合はpriceを表示します。
【備忘録】パスのあとのインスタンス変数
link_toやredirect_toなどで次のようなパスを見ることがあります。
redirect_to user_path(@user)
redirect_to @user
この二つは同じ動きをしますが、なぜパスのあとにインスタンスを入れているのでしょうか?
次のコードについて考えてみましょう。このコードから生成されるURLはなんでしょうか?
redirect_to user_path(10)
実はこの10はidを指しているんです。
そのため生成されるURLは「users/10」のようになります。
では、最初に取り上げたコードは何を指すのかというと、 呼び出されたインスタンスのidを代入していることになります。
@user = User.new(user_params) if @user.save redirect_to @user end
User.newで生成されたユーザーのidがURLに代入されてビューが表示されます。
参考
【備忘録】アソシエーションで関連付けしたオブジェクトの初期化
モデルで関連付けしたオブジェクトをコントローラで初期化します。
初期化とは、最初の状態を整えること。ここではオブジェクトの作成のことです。
まず、Userモデルを親、Postモデルを子として関連付けします。
user.rb
has_many :posts
post.rb
belongs_to :user
posts_controller.rb
@post = current_user.posts.build(post_params)
・current_userはsorceryのメソッドでログイン中のユーザーの値が入っています
・postsは、モデルで設定されているhas_many :postsによって使えるようになったメソッド。userオブジェクトで使えます
・アソシエーションでオブジェクトを初期化するときはbuildを使います。挙動はnewと同じですが、関連付けされていることが視覚的にわかるようになります。
ログイン中ユーザーの投稿に編集用アイコンを表示する
ログインしているユーザーが自分の投稿を編集できるように、編集用のえんぴつマークのアイコンをFontAwesomeを使って表示させます。
自分以外のユーザーの投稿やコメントには編集アイコンを表示させないようにします。
ログインしているユーザーが投稿を作成したユーザーかどうか判定する
sorceryのcurrent_userメソッドを使って、ログイン中ユーザーと投稿を作成したユーザーが一致するかどうかを判定します。
掲示板 _post.html.erb
<% if current_user.id == post.user_id %> <a href="#"> <i class="fa fa-pen"></i> </a> <% end %>
コメント _comment.html.erb
<% if current_user.id == comment.user_id %> <a href="#"> <i class="fa fa-pen"></i> </a> <% end %>
これは一見良さそうに見えますが、よく見ると掲示板とコメントで同じようなコードを書いています。
postとcommentで違うモデルを扱っているから仕方ないじゃん!と思いますが、ユーザーのidを取って来ている点で同じなので、まとめられるんです。
Userモデルで共通化する
Userモデルでまとめてしまいましょう!
user.rb
def own?(object) object.user_id == self.id #selfは省略可 end
objectで共通化しています。これでpostでもcommentでも、引数を指定して使えるようになります。
ちなみにインスタンスメソッドの中でselfを使うと、そのメソッドを利用したレシーバを参照することができます。
以下のビューでcurrent_user.own?のように使うので、この場合のselfの中身はuserが入るようになりますことになります。
(current_userはsorceryによって作られたログイン中ユーザーを特定するメソッドです)
投稿 _post.html.erb
<% if current_user.own?(post) %> <a href="#"> <i class="fa fa-pen"></i> </a> <% end %>
コメント _comment.html.erb
<% if current_user.own?(comment) %> <a href="#"> <i class="fa fa-pen"></i> </a> <% end %>
モデルで定義したown?メソッドを使って、ログイン中ユーザーのidとpostやcommentのuser_idを比較しています。
【Rails】Carrierwaveで画像アップロード
こんにちは。ぺんぎんです。
今回はユーザー登録や投稿の時に使う、画像アップロード機能を実装していきたいと思います。
railsの便利なライブラリ、Carrierwaveを使えば簡単に画像アップロード機能を実装することができます。
Carrierwaveとは
Railsにおける画像アップロード用のgem。
Carrierwaveでは、アップロード機能用のアップローダークラスを作って、細かい設定を書いていきます。
そのため個別のモデルに依存しないで、柔軟にいろいろな設定をすることができます。
手順
1. gemをインストール
Gemfile
gem 'carrierwave' fem 'minimagick'
今回は画像をリサイズできるようにminimagickもインストールします。 minimagickにはImageMagickが必要になります。 インストール方法はこちら。
ターミナル
bundle install
bundle installしたらサーバーを再起動させます。
2. アップローダーを生成する
$ bundle exec rails g uploader アップローダー名
$ bundle exec rails g uploader Image
→app/uploaders/image_uploader.rbというファイルが生成されます。
3. 生成されたアップローダーに設定を記述する
- デフォルト画像
- アップロード可能なファイルの種別 デフォルトで入っているコメントは消してOK。
4. ローカル環境でアップロードした画像をアップロードしないように設定する
保存した画像はgithubなどにあげて共有する必要はないですよね。
そこで、.gitignoreファイルに画像の保存先を指定して、プッシュされないように設定しましょう。
.gitignore
/public/uploads
この設定をしないでプッシュてしまった人はこちら。
5. boardsテーブルに画像のカラムを追加する
progateで学んだ人もいると思いますが、画像はDBに直接保存するわけではありません。
DBの容量がパンクしないように、画像名のカラムを作って保存するようにします。
$ bundle exec rails g migration AddImageToBoards image:string $ bundle exec rails db:migrate
これでboardsテーブルに画像用のimageカラムができました。
6. モデルでアップローダークラスとカラムの紐付け
先ほど作ったアップローダークラスは、今のままではBoardクラスとバラバラになっているので、Boardモデルでアップローダークラスを紐づけておきましょう。
class モデル名 < ActiveRecord::Base mount_uploader [:カラム名], [アップローダークラス] end
class Board < ApplicationRecord mount_uploader :image, ImageUploader end
ちなみにmountはよく耳にするあの「マウンティング」と同じ言葉です。
もともと「乗る」という意味で「据え付ける」という意味もあります。
7. コントローラでparamsに画像アップロード用カラムの追加
BoardコントローラではBoard.newで新しい掲示板を作っています。
paramsで受け取れるように、画像用カラムを追加します。
def create @board = Board.new(board_params) end def board_params params.require(:board).permit(:title, :body, :image) end
8. Viewに画像ファイルのフィールドを追加する
- 投稿フォーム
画像ファイルを送信する際のファイル選択ボックスを生成します。
ラベル部分はあとでi18nで日本語を定義します。
<%= f.label :カラム名 %> <%= f.file_field :保存されるカラム %>
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 :image %> <%= f.file_field :image, class: 'form-control mb-3', accept: 'image/*' %> <%= f.hidden_field :board_image_cache %> </div> <%= f.submit class: 'btn btn-primary' %> <% end %>
accept属性で選択できるファイルの種類を指定します。
これを指定しないと選択画面でどんなファイルも選択できてしまいます。
「image/*」は画像ファイル全般を指します。
また<%= f.hidden_field :board_image_cache %>を入れておくと、バリデーションエラーになった後でも、データが引き継がれ情報を再入力する手間が省けます。
【Rails】CarrierwaveのCache機能を使用し、バリデーション後の画像データを保持する方法
- 画像表示
アップロードした画像を表示させます。
image_tagの使い方
<%= image_tag 'ファイル名', 'オプション' %>
ここではファイル名の代わりに、アップローダークラスのurlメソッドを使って、ファイルのURLを取得するようにします。
app/views/boards/_board.html.erb
<%= image_tag board.image_url, class: 'card-img-top', size: '300x200' %>
画像がない場合にデフォルト画像を表示させたい人はこちらを見てください。
【Rails】image_tagを使って簡単に画像を表示させよう!
9. i18nで翻訳を定義する
・imageカラムの日本語を定義します。
config/locales/activerecord/ja.yml
ja: activerecord: attributes: board: title: 'タイトル' body: '本文' image: 'サムネイル'
・画像に関するメッセージの日本語を定義する
Carrierwaveですでに用意されているバリデーションのエラーメッセージを日本語にします。
Carrierwave用の定義ファイルを用意しましょう。
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}以下のサイズにしてください"
いろいろな設定
アップローダークラスでいろいろな設定をしましょう。
* アップロードしたファイルの保存場所
アップロードされた画像の保存場所は、デフォルトで「public/uploads/モデル名/画像カラム名/id」に設定されています。
class ImageUploader < CarrierWave::Uploader::Base def store_dir "uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}" end end
今回の場合は「public/uploads/board/image/id」に保存されます。
この「id」には掲示板のidが入るので、board.idが1の掲示板で画像をアップロードしたら、「public/uploads/board/image/1」というフォルダに保存されます。
* 画像がない場合のデフォルト画像の指定
class ImageUploader < CarrierWave::Uploader::Base def default_url 'sample.png' end end
これを設定しておけば、画像がない時とある時でView側で条件分岐をしなくてすみます。
* アップロードできる拡張子の指定
def extension_whitelist %w(jpg jpeg gif png) end
gitignoreを設定をしないでgitでコミットしてしまった場合
コミット後にこれを追記しても、アップロード済みのファイルは変更されません。 コミット後はファイル名を指定してgitの管理対象外に変更します。
git rm --chached ファイル名
また不要なファイルをpushしてしまった場合は、リモートリポジトリから削除します。
git rm ファイル名
必ずpush前に不要なファイルがないか確認しましょう( ^ω^ )
参照
CarrierWave github.com
【Rails】CarrierWaveチュートリアル pikawaka.com
はじめまして
どうも、はじめまして。ぺんぎんです。
読んでくださっている方ありがとうございます。
エンジニア・IT業界の経験ゼロで、エンジニア目指して1からプログラミングの勉強をしてます。
ここではRuby on Railsを中心に、自分のハマったポイントなどを、備忘録の意味もこめて書いていきます。
まだまだ初心者のぺんぎんですので、間違っていることがあればたくさんツッコんでいただけたらうれしいです。
よろしくお願いします🐧