環境の使い分け(後から見直す用)
テスト環境
config/environments/test.rbで設定
RAILS_ENV=test環境で実行
テスト環境はRspecなどのテスト実行時に利用する
developments環境
いわゆる開発環境。アプリの開発などを行うときに利用される
app/配下のファイルを変更して使用が可能。それ以外のファイルを変更した場合はサーバーを一度落として対応
config/environments/developments.rbで設定
production環境
完成したアプリケーションを実際にユーザーが使用する環境
基本的に開発段階では使用しない
データベース
データベースも環境ごとに変わるのでenvironments環境でDBにデータを挿入したとしてもtest環境ではそのデータは挿入されない。
環境ごとにDBは管理する必要がある。
環境別にデータベースの確認
rails c 環境名
で環境別コンソールを開き、モデル.allで現環境のデータを見ることができる。
もしくはrails db:migrate RAILS_ENV = 環境名で環境別にマイグレートすることができる。
link_toにnoopenerたる物がついていてはぁ?ってなった話
プログラミングを本格的にスタートして3ヶ月目に入りましたさかもとです。
今回はlink_toに_blankとnoopenerがついていてなんだこれは!ってなった話をアウトプットしようと思います。
target : ' _blank 'とは
ざっくりいうとリンクを別タブで開く際に使用するメソッドです。
しかしセキュリティー面で大きな問題があるというデメリットがあります。
その詳細な内容に関しては下記記事に詳しく書いてあるので興味がある方はそちらへ。
実はヤバい?aタグと別タブで開く(target=”_blank”)の使い方 |ホームページ制作 名古屋 愛知 |株式会社WWG ダブルダブルジー
rel: ' noopener ' とは
これは一種のセキュリティ対策であり、target: ' _blank ' のセキュリティ面の脆弱性をカバーするために用いられます。
ここは基本的にセットで用いられると思ってもらって大丈夫です。
aタグに付いているrel="noopener"って何? | ocws BLOG
こちらの記事に詳細が詳しくのっています。
最後に
せっかくわからないことが出てきたのでいつでも見返せるように残しておこうと思います。
わからないことなどは今後も記していこうと思います。
Rspecで実装側のメソッドを使用するために行ったことの話
プログラミングを本格的にスタートして3ヶ月目に入りましたさかもとです。
今回はRspecで実装側で定義されたメソッドをテスト環境でも使用できるようにしたい!という話をアウトプットしようと思います。
現状
Rspecのシステムテストで下記のような状況に陥りました。。
```
expect(page).to have_content ( current_time(Time.current) )
```
このテストは遷移先のページに現在の時刻が実装側の表記と合うようにcurrent_timeという実装側のメソッドを使用し表しています。
こうすることで、実装側で表記方法が変わってしまってもテスト側も連動して変わるのでいちいち書き換える必要がないというメリットがあります。
しかしテストを実行してかえってきた答えは
```
undefined method ' current_time ' for ~~~~
```
え。。。
というのが今回の問題でした。
解決法
結果としてテストの書き方自体に問題はありませんでした。
問題があったのは実装側で定義されたメソッドを読み込めていなかったテスト側にありました。
current_timeメソッドは実装側のApplicationHelperで定義されたものです。
しかしテスト側ではApplicationHelperファイルは読みこまれていません。
そこでrails_helper.rbに
```
config.include ApplicationHelper
```
このように記述してあげることでテスト側でも実装側で定義されたメソッドを使用することができテストも無事に通りました。
参考記事
RSpecでApplicationHelperのメソッドを使う - Qiita
FactoryBotで盛大に認識違いを繰り広げた話
プログラミングを本格的にスタートして3ヶ月目に入りましたさかもとです。
今回はFactoryBotで認識違いを起こしたせいでまたしても沼ってしまった!という話をアウトプットしようと思います。
FactoryBotについては前回の記事で説明をしているのでそちらをご一読ください。
問題点
FactoryBotでtaskモデルをこのように作成。
```
factory :task do
sequence(:title) { |n| " 書類を作成する|n| }
content { "取引先に書類を作成する" }
end
```
titleはユニークな値のためsequenceで。
次にこれをtasks_specで扱うために下記のようにテストの一番上に記述。
```
RSpec.describe 'Tasks' , type: :system do
let(:task){ create(:task) }
:
:
```
これで準備は完了。テストを書き始めます。
```
:
it ' タスクの新規登録が成功する ' do
visit new_task_path
fill_in ' Title ' , with: task.title
:
```
しかしこれでエラーが発生します。それはこのタイトルはすでに登録されています。というものです。
????
シーケンス でタイトルは別々の物が生成されるはずでは?
これが今回の問題です。
結果
今回、なぜこのような問題が起きたのか、それはコントローラーの変数と考え方がごっちゃになってしまったからです。
task.createはDBに保存される物です。なので一度よび出すとDBに保存されます。今回の場合このテスト以前に一度、呼び出しているので保存されていた分です。
また新規登録の際、DBに保存された値をもってこれないように変数で用意した値を入れてしまうと2回保存することになるので引っかかってしまったというわけです。
追記
まだ自分の中でも整理ができていないの今後追記などしていこうと思います。
間違った認識などありましたら教えていただけると幸いです。
```
FactoryBot でselect boxで選択するenumにハマった話
プログラミングを本格的にスタートして3ヶ月目に入りましたさかもとです。
今回はFactoryBotでselect boxを選択するテストを定義する際に沼ってしまった!という話をアウトプットしようと思います。
FactoryBotとは
Rspecでテストを実行する際にテスト毎に
@user = User.new( name: " ", email: " " ......... )
と定義するのは非常に面倒です。
そこでFactoryBot!gemをインストールしspec/factories/user.rbのようにファイルを生成しそこにモデルを定義してあげることで可読性と汎用性をあげることができます。
enumとは
ここでは本題とそれるので詳細は省くが列挙型といって指定された定数を保持することができる。
こちらの方の記事がわかりやすかったので確認してください。
本題
今回FactoryBotでこのenumをカラムにもつtaskモデルを定義しシステムスペックにincludeしテストに活用するという課題がありました。
そこで
spec/factories/tasks.rb
(省略)
factory :task do
name { "書類作成" }
status { "todo" }
end
このように設定しテストを実行するusers_spec.rbでは
let(:task) { FactoryBot.build(:task) }
と定義してモデルを作成。実際のテストでは
it '新規作成したタスクが表示される' do
visit new_task_path
fill_in 'Name', with: task.name
fill_in 'Status', with: task.status
(省略)
end
これで完璧!のはずでしたがテストを走らせるとStatusが見つけられないと怒られてしまいます。
ここで沼ってしまいました。
解決策
binding.pryを挟み、webdriversでスクリーンショットを確認してみるとどうやらnameは作成されていました。
つまりFactoryBotは起動していて定義されています。
問題点はenum型の記述間違いだと予想をたて下記git hubを参考に確認しましたが特に問題はなさそう。。。
ここで完全にわからなくなります。
そこで今度はテストの記述に目を向けました。そこで気付きます。
fill_inは記述する際に用いられるものでは?
そう。今回のStatusはenumにありがちなselect boxから選択し登録するものだったのです。
そうすると記述の仕方は
fill_in 'Status', with: task.status
これから
select task.status, from: 'Status'
に変わります。
これでテストも無事走りました。
参考記事
列挙型(enum)の基本的な使い方とコード例 - Qiita
https://github.com/thoughtbot/factory_bot/blob/master/GETTING_STARTED.md#enum-traits
Rspec 行ってみて大切だと思った点がある話
プログラミングを本格的にスタートして3ヶ月目に入りましたさかもとです。
今回はRspecを初めて行ってみて大切だと思った点!という話をアウトプットしようと思います。
1. FactoryBotのDateの書き方
FactoryBotでtaskモデルを定義した際にdeadlineというカラムがありました。
このカラムは" 0000/00/00/ 00:00 "のように日時を表示するカラムだったのですが私は Deadline { " 1998/01/01 " } このように書きました。
こうすると時間は00:00で定義されるのでtaskモデルが定義されます。
しかし、実際にはこの書き方はよくありません。
日時を固定するような定義の仕方は汎用性がないからです。
そこで使われるのは " 1.week.from_now "
こうすることで現在の日時が自動で適用されるので汎用性も高く便利!
2. sequenceの書き方
titleカラムに対してユニークな値を定義しなければならないという問題で私は" sequence (:title) { |n| "書類作成#{n}" } と記述しました。
これはtitleカラムに対して1つ目のモデルが定義されたらn = 1となり発効されるtitleは 「 title 1 」となります。
こうすることで絶対にかぶることのないタイトルカラムを実装することができます。
この書き方は決して間違えではありません。しかしもっと簡潔に書くこともできます。
" sequence { :title " title_1" } "
もう圧倒的簡潔。titleカラムに1つ目の定義ではtitle_1が入り2回目からは title_2 と入ります。
このほうがDRYなかきかたなので頭の片隅に入れておきましょう。
3. テストの書き方
Rspecのテストで大切なことはわかりやすく!もれなく!これに尽きると思います。
以下の例はどうでしょう
ex) it 'titleがなければ無効の状態であること" do
title = FactryBot.build(:task, title: nil )
title.valid?
expect(title.errors[:title]).to include("can't be blank")
今回は内容ではなく書き方に触れたいと思います
1. 変数は何を入れるものなのかがわかりやすいように書く。titleよりstatus_without_titleのほうが他の方はみたときにわかりやすい。
2 . title.valid?より expect(task_without_title).to be_invalidの方が良い。期待される値に対してどう処理するかが明確。be_invalidは無効。
3 . includeは配列と一緒に使われ、今回の場合エラーメッセージの中にある"can't be blank"が含まれているかを検証するマッチャです。使い方としては決して間違ってはいないかと思いますが今回の場合は eq でも問題ないということだけ念頭に置いておいてください。
多 対 多のリレーションの話
プログラミングを本格的にスタートして3ヶ月目に入りましたさかもとです。
今回は多 対 多のリレーションの実装!という話をアウトプットしようと思います。
多 対 多 とは
本来、1対多の実装を行う際は親となる側にhas meny、子となる側にbelongs_to
を付与することで1対多を実現することができます。
しかし多 対 多の場合はそうは行きません。
なぜならどちらも親であり、子でもあるからです。
この関係を実装するために大切なのが今回のキーワードになる” 中間テーブル "の作成です!
中間テーブルを用いて実装
例えば著者(auther)と本(book)モデルがそれぞれあるとします。
著者は沢山本を書きますし、本も様々な著者によって作成されます。
この著者と本は多 対 多の関係にあります。
ここでこの関係を成立させるためにすることは
1. auther.rb, book.rb, book_auther.rb(中間テーブル)の作成
2. auther.rb, book.rb にhas_menyとthroughでbook_authersに関連づけ
3. book_authersにはbelongs_toで関連付け2つのモデルを指定
この3点です。
実際に行います。
auther.rb
has_many :book_authers
has_many :books, through: :book_authers
book.rb
has_many :book_authers
has_many :authers, through: :book_authers
book_auther.rb
belongs_to :auther
belongs_to :book
これで実装は完了です。
実際に活用できるかどうかはrails cでコンソールを開き確認してみてください。