CarrierWaveを使用している時のテストデータの準備法(FactoryBot編)
FactoryBotの基本的な使い方と同じですが、文字列と少しだけ異なります。
FactoryBot.define do factory :post do title "Sample Title" description "This is a sample description" # CarrierWageで使用しているカラム名をキーにする # 画像ファイルは「spec/support」配下に格納 image { Rack::Test::UploadedFile.new(Rails.root.join('spec/support/sample_image.jpg'), 'image/jpeg') } end end
これで出来上がり!
【CarrierWave + Heroku】でAWS S3に画像を保存しようとすると「HTTP 403」が返却される
HTTP 403とは
HTTP の 403 Forbidden クライアントエラーレスポンスコードは、サーバーがリクエストを理解したものの、認証が拒否されたことを示します。
つまり、リクエスト自体は送られているけど、何らかの理由でアクセスが拒否されたということですね。
対処法
ググったら以下がヒットしたので試してみました。
qiita.com
上記の記事によると、
新しく発表されたパブリックアクセス設定機能によりデフォルトでは管理者しかアクセスできず、IAMユーザーのアクセスがブロックされてしまうということです。
だから少し古いS3のセットアップ方法だけだと、403を返却されてしまうのですね。
解決できてよかったです。
@yukiyukimiyaiwaさん、ありがとうございます!
【Rspec】Shoulda Matchersを使用してspecをシンプルに書く
はじめに
「Shoulda Matchers」というGemを使うと、specをDRYに書けるという話です。
例えば以下のようなnameのpresenceのバリデーションを確認するspecがあるとします。
# nameが未入力の時、無効な状態であること it "is not valid without a name" do user = FactoryBot.build(:user, name: nil) user.valid? expect(user.errors[:name]).to include("can't be blank") end
テストする対象が少しの場合は良いのですが、例えばフォームの入力欄がたくさんあり、
それらに対してpresenceのバリデーションをテストしなければならないような場合はやや冗長になります。
しかし、「Shoulda Matchers」というGemを使えば、これがワンライナーで書けてしまいます。
1. 「Shoulda Matchers」のインストール
Gemfileに以下を追記し、bundle install
group :test do gem 'shoulda-matchers', '4.0.0.rc1' # 省略 end
rails_helper.rbに以下を追記
Shoulda::Matchers.configure do |config| config.integrate do |with| with.test_framework :rspec with.library :rails end end
2. 「Shoulda Matchers」の利用
先ほど冒頭で書いたサンプルは以下のように書き換えることが可能です。
# nameが未入力の時、無効な状態であること it { is_expected.to validate_presence_of :name }
これだけです。ものすごいシンプルに書けます。
上記はpresenceをバリデートする例ですが、他にも以下のようなメソッドが用意されています。
# アソシエーション it { is_expected.to have_many :posts } it { is_expected.to belong_to :user } # 一意性 it { is_expected.to validate_uniqueness_of :email } # length it { should validate_length_of(:password).is_at_least(6).with_message("は6文字以上で入力してください") }
終わりに
他にも色々なメソッドが用意されているので、興味があればその都度調べて見るのが良いと思います。
github.com
【Ruby on Rails】バリデーションメッセージが表示されない時の対処法
Railsのヘルパーメソッド「simple_format」について調べて見た
はじめに
「simple_format」とは、与えられた文字列を以下の条件で整形するメソッド。(らしい。。。)
・文字列を<p>で括る
・改行は<br />を付与
・連続した改行は、</p><p>を付与
1. simple_formatなし
# 入力値 simple_formatのテストをします。 まずは改行を1度挟みます。 # 出力値 simple_formatのテストをします。 まずは改行を1度挟みます。
本当は改行したのですが、出力値では改行されていません。
2. simple_formatあり(オプションなし)
simple_format(入力値) # 入力値 simple_formatのテストをします。 まずは改行を1度挟みます。 # 出力値 simple_formatのテストをします。 まずは改行を1度挟みます。 # ここが1文空く
出力値でも改行されていることがわかります。
全体を<p>で括っているため、最後の行にスペースが入っているように見えます。
3. simple_formatあり(オプションなし)
simple_format(入力値) # 入力値 simple_formatのテストをします。 <p>htmlタグを記述して見ます。</p> # 出力値 simple_formatのテストをします。 htmlタグを記述して見ます。 # ここが1文空く
改行は問題なくされていますが、入力した<p>が出力値に反映されていません。
htmlタグを全て除去したい場合はこれでもいいですが、残したい場合はこれはダメですね。
4. simple_formatあり(オプションあり)
simple_format(h(入力値), {}, wrapper_tag: "div") # 入力値 simple_formatのテストをします。 <p>htmlタグを記述して見ます。</p> # 出力値 simple_formatのテストをします。 <p>htmlタグを記述して見ます。</p>
改行はされていますし、htmlタグも出力されています。
また、「wrapper_tag」を追加することで<p>ではなく、別の指定したタグで囲むことができます。
まとめ
状況に応じてですが、simple_formatで文字列を囲むだけでと意図しない結果に繋がることもあるので、
文字列をどのように扱いたいか考えてから使うのがいいですね!
画像アップロード機能「Active Storage」を使ってみた!
「Active Storage」とは
Rails5.2から登場したgemで、ActiveRecordモデルへの紐付けや、
クラウドストレージサービス(AWS、GCP、Azure)へアップロードが非常に容易に行えるライブラリ。
現在は、画像アップロードには「CarrierWave」というgemが一番よく使われているが、
今後はこの「ActiveStorage」が使われることになると言われている。。。(本当?)
1. ActiveStorageを準備する
gemをインストールするためには以下のコマンドを実行します。
rails active_storage:install
そうすると、以下のようなマイグレーションファイルが作成されます。
xxxxxxxxxxxxxxxxx_create_active_storage_tables.active_storage.rb
このマイグレーションファイルの中身は以下のようになっています。
# This migration comes from active_storage (originally 20170806125915) class CreateActiveStorageTables < ActiveRecord::Migration[5.2] def change create_table :active_storage_blobs do |t| t.string :key, null: false t.string :filename, null: false t.string :content_type t.text :metadata t.bigint :byte_size, null: false t.string :checksum, null: false t.datetime :created_at, null: false t.index [ :key ], unique: true end create_table :active_storage_attachments do |t| t.string :name, null: false t.references :record, null: false, polymorphic: true, index: false t.references :blob, null: false t.datetime :created_at, null: false t.index [ :record_type, :record_id, :name, :blob_id ], name: "index_active_storage_attachments_uniqueness", unique: true end end end
この中身を見ると、テーブルが2つ作成されていることがわかります。
それぞれどういう役割を果たすかを簡単に説明すると、以下のようになります。
・active_storage_blobs ・・・ ActiveStorage::Blobというモデルと紐づいており、ファイルの実態以外の情報(識別キー、ファイル名、Content-type、ファイルのメタデータ、サイズ等)を管理するもの
・active_storage_attachments ・・・ ActiveStorage::Attachmentというモデルと紐づいており、ActiveStorage::Blobとその他のモデルを繋げる中間的な役割を果たすもの
作成されたマイグレーションファイルは特にいじらずにマイグレートを実施します。
rails db:migrate
次にファイルの実態をどこで管理するか設定している箇所を見てきます。
config/environments/development.rb
test: service: Disk root: <%= Rails.root.join("tmp/storage") %> local: service: Disk root: <%= Rails.root.join("storage") %>
「root: <%= Rails.root.join("storage") %>」という記述がありますが、
この部分がファイルの実態の保管場所を意味しています。(root直下のstorageディレクトリ)
2. 画像アップロードを実装する
models/post.rbの中に「 has_one_attached :image」を追記します。
例では、Postモデルに紐付けをしたかったので、post.rbの中に記述しました。
このように「ActiveStorage」をインストールし、テーブルを作成してしまえば、
他のテーブルは修正することがなく、下記のような一文でテーブル間の連携ができてしまいます。(めちゃ楽)
1ポスト1画像を紐付けたかったため、「has_one_attached」としましたが、
もし複数の画像を紐付けたい場合は「has_many_attached」を使えば良いです。
class Post < ApplicationRecord has_one_attached :image end
アップロード機能の実装は普通の画像アップロードと変わりません。
<% f.label :image %> <%= f.file_field :image, class: 'form-control' %> end
あとは、アップロードした画像を表示させます。
<% if @post.image.attached? %> <%= image_tag @post.image %> <% end %> end
「image.attahed?」メソッドを使うことで、画像が添付されていない場合でもエラーを回避することができます。
(image_tagは画像がない場合エラーを表示する。)
Railsで論理削除を実装したい時は「paranoia」Gemを使おう!
はじめに
このデータ(レコード)要らないと思って削除したはいいが、あとで戻したいなんてことありますよね?
Railsチュートリアル等を見ると、destroyメソッドでレコードを物理削除したりしていますが、
完全に消すのは怖いという場合、論理削除をすることをおすすめします。
「paranoia」というGemを使用するとこれが簡単に実装できてしまいます!
それでは見ていきましょう!
1. Gemをインストール
Gemfileに以下を追記する
gem 'paranoia'
bundle installする
2. 論理削除用のカラムを追加
migrationファイルの作成
※ 以下では、migrationファイルを生成するときにカラム名と型を指定しています。
rails g migration add_column_to_テーブル名 deleted_at:datetime
migrationを行う
rails db:migrate
3. モデルに独自のメソッドを追記
class Post < ApplicationRecord acts_as_paranoid end
終わりに
これでdestroyメソッドで削除しようとすると、先ほど追加した「deleted_at」に日時が入り、物理的にレコードは削除されません。
※ 本当に物理削除したい場合は、「really_destroy」メソッドを使用すると物理削除をすることができます。
めちゃくちゃ簡単でしたね!
本当にRailsのGemは豊富で実装が簡単です!