環境の使い分け(後から見直す用)

テスト環境

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とは

ここでは本題とそれるので詳細は省くが列挙型といって指定された定数を保持することができる。

こちらの方の記事がわかりやすかったので確認してください。

qiita.com

 

本題

今回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を参考に確認しましたが特に問題はなさそう。。。

github.com

ここで完全にわからなくなります。

そこで今度はテストの記述に目を向けました。そこで気付きます。

fill_inは記述する際に用いられるものでは?

そう。今回のStatusはenumにありがちなselect boxから選択し登録するものだったのです。

そうすると記述の仕方は

fill_in 'Status', with: task.status

これから

select task.status, from: 'Status'

に変わります。

これでテストも無事走りました。

 

参考記事

列挙型(enum)の基本的な使い方とコード例 - Qiita

RSpec入門 6.システムスペック - 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でコンソールを開き確認してみてください。