オブジェクトとは

はじめに

プログラミング学習中の方向けです。
オブジェクトの理解を深めたい方の手助けになれば幸いです。
オブジェクトについて説明している記事と一緒に見ていただけると理解が深まると思います。
本記事は書籍現場Railsの内容を元に作成しています。

概要

  • オブジェクトとは
  • 具体的な例
  • オブジェクトの機能はクラスで決まる
  • オブジェクトの概念を理解すると

    オブジェクトとは

    プログラミングの世界ではオブジェクトという概念が存在します。
    一言でいうとオブジェクトとは、様々な機能(メソッド)が定義されたクラスのことです。
    現実世界でいうと人間、猫、机など実態が存在するモノや、空気、水など流動的なモノ、または時間、愛など掴みどころのない抽象的な概念などがオブジェクトに当てはまります。
    つまり言葉で区別できるものはすべてオブジェクトになります。 オブジェクトは様々な機能が定義されていると説明しました。
    オブジェクトには標準で様々な機能があり、プログラマは機能を利用したりまたは欲しい機能を追加することもできます。
    現実世界で例えると、人間は標準で2足歩行ができたり、食事を食べる、排泄するといった機能が備わっています。
    また欲しい機能があったら、学ぶことでスキルを取得できます。(学問、水泳、ものづくりなど)

    具体的な例

    では実際に具体的なコードを書いてオブジェクトの理解を深めましょう。

irb(main):010:0> "氏名"
=> "氏名"
irb(main):011:0> 1
=> 1
irb(main):012:0> "氏名".class
=> String
irb(main):013:0> 1.class
=> Integer

実行したコードは、文字列オブジェクト、整数オブジェクトです。
普段コードを書いていると気にならないと思いますが、これら2つはどちらもオブジェクトです。

irb(main):012:0> "氏名".class
=> String

こちらのコードは"氏名"がどのオブジェクトに属しているか聞いています。
どのオブジェクトに属しているかというのは、目の前の動物が、猫なのかクマなのか人間なのかという意味です。
返答としてStringと返ってきました。
つまり"氏名"オブジェクトはStringクラスのオブジェクトということが分かりました。

irb(main):013:0> 1.class
=> Integer

1も同じように聞くとIntegerクラスのオブジェクトだと分かりました。
オブジェクトにはそれぞれidが割り振られています。
idとはそれぞれを識別するためのものです。
例を上げると私達は人間というオブジェクトに属しているが、ひとりひとり見た目、人格、性格が異なるようにプログラミングの世界でも異なります。

irb(main):001:0> '氏名'.object_id ①
=> 70240571267320
irb(main):002:0> '氏名'.object_id ②
=> 70240599834760
irb(main):003:0> 1.object_id ③
=> 3
irb(main):004:0> 1.object_id ④
=> 3

コードで見ていきましょう。
オブジェクト.object_idというコードを打つと、オブジェクトの固有のidが取得できます。(マイナンバー的なものです。) 出力結果から分かるのは①と②は全く同じ見た目なのに内部では異なるオブジェクトと扱われています。
では③と④はどうでしょうか?
同じidになっています。先程オブジェクトには固有のidがありひとつひとつ異なると説明しましたが、型によっては同じにしたほうが都合が良いものもあります。
現実でも、数字の1は見た目が同じでも実は100種類の1がありそれぞれ特性が異なりますとか言われたら、困りますよね?
このように普遍の原理的なものは存在しますが、基本的にはオブジェクトはそれぞれ固有のidを持っているという認識を持っておきましょう。

オブジェクトの機能はクラスで決まる

オブジェクトにはそれぞれ特性があります。
例を上げると人間は標準で2足歩行の機能が備わっているように、文字オブジェクト、整数オブジェクトにもそれぞれ機能が備わっています。
コードを見ていきましょう

irb(main):005:0> '氏名'.length
=> 2

オブジェクト.lengthとすると2と出力されました。
これは文字の長さを取得しています。
これはStringクラスが標準で定義されているメソッドを呼び出しています。
このようにオブジェクト固有のメソッドが標準で備わっています。
利用する側としては、オブジェクトの特性や使用できる機能を知ることで様々な処理をオブジェクトにさせることができます。

オブジェクトの概念を理解すると

ここまで長々と書いてきましたが、まとめるとrubyで入力した情報はすべてオブジェクトと処理されます。
様々な機能はオブジェクト同士を組み合わせることで実現します。
特にRuby on Railsを使用していると、内部でいろいろ自動でやってくれるので忘れがちですが、裏側ではメソッドの組み合わせで様々な処理がなされているに過ぎないといっていいでしょう。

Are you sure? を削除する

はじめに

10月からRunteqの課題取組中
駆け出しエンジニアです.
日々の学びをアウトプットします.

概要

  • 削除できない?
  • 原因
  • 解決策 

    削除できない?

    下のコードを実行したところ、削除ができていなかった.

  it 'Taskが削除されること' do
    visit project_tasks_path(task.project)
    click_link 'Destroy'
    expect(page).not_to have_selector '#task_list', text: task.title
    expect(Task.count).to eq 0
    expect(current_path).to eq project_tasks_path(task.project)
  end

ブラウザを確認しても削除できていない

原因

  • エラーメッセージ
Selenium::WebDriver::Error::UnexpectedAlertOpenError:
       unexpected alert open: {Alert text : Are you sure?}

エラーメッセージからDestroyリンクをクリックすると、アラートが出てきたといっている.
リンクのコードからも読み取れるように、削除する前に確認のダイアログが実装されている.

<%= link_to 'Destroy', [@project, task], method: :delete, data: { confirm: 'Are you sure?' } %>

つまりアラートに対応するコードを記述すれば解決しそうだ.

解決策

# 確認タイアログを実行するコード
  accept_confirm do
    click_link 'Destroy'
  end
  • 参考サイト

www.rubydoc.info

traitの定義の仕方、呼び出し方

はじめに

10月からRunteqの課題取組中
駆け出しエンジニアです.
日々の学びをアウトプットします.  

概要

  • データを変更したもの呼び出したい  
  • 定義の仕方  
  • 呼び出し方  

    データを変更したもの呼び出したい 

    FactoryBotを使用していると、1部のカラムのみ変更したデータを呼び出したいときがある.
    そういった時に便利なのがtraitだ.

    定義の仕方

FactoryBot.define do
  factory :task do
    title { 'Task' }
    status { rand(2) }
    from = Date.parse("2019/08/01")
    to   = Date.parse("2019/12/31")
    deadline { Random.rand(from..to) }
    association :project

    #上の内容も引き継ぎつつ、カラムの内容は上書き
    trait :yesterday do
      status { :done }
      completion_date { Time.current.yesterday }
    end
    trait :tomorrow do
       status { :doing }
      completion_data { Time.current.tomorrow }
    end
       ・
       ・
       ・
  end
end

呼び出し方

  done_task  = create(:task, :yesterday)
  doing_task = create(:task, :tomorrow)

click_linkが動作しなかったケース

はじめに

10月からRunteqの課題取組中
駆け出しエンジニアです.
日々の学びをアウトプットします.  

概要

  • click_linkが動作しない  
  • 原因  
  • 解決方法

    click_linkが動作しない

    下のコードを実行中テストがパスしない

RSpec.describe 'Task', type: :system do
  let(:project) { create(:project) }
  let(:task) { create(:task, project_id: project.id) }
  describe 'Task一覧' do
    context '正常系' do
      it 'Project詳細からTask一覧ページにアクセスした場合、Taskが表示される>こと' do
        visit project_path(project)
        click_link 'View Todos'
        expect(page).to have_content task.title
        expect(Task.count).to eq 1
        expect(current_path).to eq project_tasks_path(project)
      end
    end
  end

原因

ブラウザーを見てみると、ページ遷移していない.
click_linkが動作していない可能性がある.
調べた結果こちらのコードが関係していることが分かった.
clik_linkで押されるリンクのコードでオプションに注目してほしい.

<%= link_to 'View Todos', project_tasks_path(@project), target:'_blank', rel: 'noopener' %>

上のコードのオプションの「target: '_blank'」はリンクをクリックすると、新しいタブで開くなるようになるオプションだ.
このオプションを無効にすると動作するため、新しいタブで開くとうまく動かないようだ.
この結果から考えられるのは、テストを実行しているタブが異なっている.
だからブラウザを確認しても前のページのままなのでは?
つまり実際にはclick_linkの動作はしていたが、テストで実行しているブラウザが適切ではなかったということになる.
- 同じ現象の人

www.it-swarm.jp.net

解決方法

タブを切り替える処理をすれば解決する.
テストを実行するタブを変更するコード

  new_window = window_opened_by { click_link 'View Todos' }
  within_window new_window do
    #チェック項目が続く
      ・
      ・
      ・
  end

ちなみに1行でも切り替わる

switch_to_window(windows.last)

【中学英語】2限目be動詞例文、使い方

はじめに

プログラミング学習において、英語の必要性を感じたため英語を学習しています.
英語アレルギーですが、英語力を身に着けるためアウトプットします.
今回は少し長めです.(理解しながらだと1時間かかります.)
内容は↓サイトから抜粋しています
https://english.005net.com/yoten/be.php

概要

  • 前回の記事.初めての方はこちらから見てください.
    takishita0.hatenablog.com
  • 主語が何であるか(主語 + be動詞 + 名詞
  • 主語がどんな状態か(主語 + be動詞 + 形容詞)
  • 主語はどこにいるか(主語 + be動詞 + 場所を表す文)
  • be動詞疑問文(be動詞 + 主語 + ・・・?)
  • be動詞の否定文(be動詞 + not ・・・)
  • 練習問題(単語は調べてOK)
  • 理解度テスト

主語が何であるか(主語 + be動詞 + 名詞

  • 主語が何であるかを説明する用法
    「〜です」「〜である」といった具合に訳す
    日本語に訳すときは主語→名詞→be動詞で読むと自然になります.
英語
日本語訳
I am Shizuoka Hamako. わたしは静岡ハマコです.
You are our teacher. あなたは私達の先生です.
This is my bike. これは私の自転車です.

主語がどんな状態か(主語 + be動詞 + 形容詞)

  • be動詞のあとに置き、主語がどんな状態であるかを説明する.
    日本語に訳すときは主語→名詞→be動詞で読むと自然になります.
英語
日本語訳
I am Happy. 私は幸せです.
You are kind. あなたは親切です.
Your bike is nice. あなたの自転車は素敵です.

主語はどこにいるか(主語 + be動詞 + 場所を表す文)

  • 存在を表現する用法
    「〜(主語)が・・・(場所)にいる」「〜(主語)が・・・(場所)にある」

※場所を表す言葉の前には前置詞がつく(重要)

英語 日本語
in〜 〜に、〜の中に
under〜 〜の下に(接して)
on〜 〜のそばに
near〜 〜の近くに

日本語に訳すときは主語→名詞→be動詞で読むと自然になります.

英語
日本語訳
I am in Tokyo. 私は東京にいます.
We are near the station. 私達は駅の近くにいる
My book is on the desk. 私の本は机の上にある.

be動詞疑問文(be動詞 + 主語 + ・・・?)

  • be動詞の文を疑問文にするにはbe動詞を戦闘に出す.
    主語とbe動詞を入れ替える
普通の文 疑問文
This is your bike Is this your bike?
You are a student Are you a student?
  • 疑問文の答え方
    Yes, + 主語の代名詞 + be動詞
    No, + 主語の代名詞 + be動詞 + not
  • フローチャート(代名詞に迷ったら)
    疑問文フローチャートが表示されています.
    図1.疑問文フローチャート
    ※返答のbe動詞は省略形で記述しています.(わからなかったら調べてみてください.)
疑問文 返答
Is this your book? Yes, it is./No, it's not.
Are you Ken? Yes, I am,/No, I'm not
Is Ken form Tokyo? Yes he is/No he's not

be動詞の否定文(be動詞 + not ・・・)

be動詞の文を否定するにはbe動詞の直ぐ後ろにnotをいれる.

肯定文 否定文
We are students. We are not students
I am a student at Runteq I am not a student at Runteq
  • be動詞を含む短縮表現
    「be動詞 + not」はよく短縮して使われる.
not短縮ver 短縮ver
is not isn't
are not aren't
  • 「主語 + be動詞」の短縮もよく使われる.
not短縮ver 短縮ver
I am I'm
you are you're
he is he's
she is she's
it is it's
we are they're
that is that's

練習問題(単語は調べてOK)

  • 下の文章を英語で記述しなさい
    (a)グリーン先生は私達の先生ではない.
    (b)私達は幸せではない.
    (c)ヒロシは群馬出身ではない.
    (d)私は千葉出身ではない.
    (e)彼らは私の友達です.

理解度テスト

ここまでの内容で下のサイトのテストはすべて、解けます.
ぜひやってみてください.

中学・英語問題プリント be動詞の肯定文1

中学・英語問題プリント be動詞の肯定文2

中学・英語問題プリント be動詞の否定文1

中学・英語問題プリント be動詞の否定文2

中学・英語問題プリント be動詞の疑問文1

中学・英語問題プリント be動詞の疑問文2

中学・英語問題プリント be動詞の文1

中学・英語問題プリント be動詞の文2

ログインmoduleでDRYに

はじめに

10月からRunteqの課題取組中
駆け出しエンジニアです.
日々の学びをアウトプットします.
beforeに触れてますが、挙動までは触れません.

概要

  • ログイン処理で重複しがち
  • サポートモジュール作成
  • コードがスッキリ

    ログイン処理で重複しがち

  • コード例
require 'rails_helper'
RSpec.feature "Users", type: :feature do
  describe 'ログイン後' do
    let(:user) {build(:user)}
    describe 'ユーザー編集'  do
      context 'フォームの入力値が正常'  do
        it 'ユーザーの編集が成功する' do
          #ログイン処理 1回目
          visit root_path
          click_link 'Login'
          fill_in 'Email', with: user.email
          fill_in 'Password', with: 'password'
          click_button 'Login'
          #編集の処理・・・
        end
      end
      context 'メールアドレスが未入力'  do
        it 'ユーザーの編集が成功する' do
          #ログイン処理 2回目
          visit root_path
          click_link 'Login'
          fill_in 'Email', with: user.email
          fill_in 'Password', with: 'password'
          click_button 'Login'
          #編集の処理・・・
         end
      end
      context '登録済みのメールアドレスを使用' do
        it 'ユーザーの編集が失敗する' do
          #ログイン処理 3回目
          visit root_path
          click_link 'Login'
          fill_in 'Email', with: user.email
          fill_in 'Password', with: 'password'
          click_button 'Login'
          #編集の処理・・・
        end
      end
    end
  end
end
      

編集のテストを実行するたびに、ログイン処理でコードが重複してしまいます.
これでは記述するのも大変ですし、コードが重複します.

  • beforeを使ってDRYに
require 'rails_helper'
RSpec.feature "Users", type: :feature do
  describe 'ログイン後' do
    let(:user) {build(:user)}
    before do
      #ログイン処理
      click_link 'Login'
      fill_in 'Email', with: user.email
      fill_in 'Password', with: 'password'
      click_button 'Login'
    end
    describe 'ユーザー編集'  do
      context 'フォームの入力値が正常'  do
        it 'ユーザーの編集が成功する' do
          #編集の処理・・・
        end
      end
      context 'メールアドレスが未入力'  do
        it 'ユーザーの編集が成功する' do
           #編集の処理・・・
         end
      end
      context '登録済みのメールアドレスを使用' do
        it 'ユーザーの編集が失敗する' do
           #編集の処理・・・
        end
      end
    end
  end
end
      

これでもスッキリしたのですが、別のテストでもログイン処理は使いますよね...
例えば下のような実装がされているアプリがあったとします.

f:id:takishita0:20210221151553p:plain Project、Noteがログインしたユーザでなければ作成できないとすると、テストを書くたびにログイン処理のコードが重複してしまいます.
下のような共通で使えるメソッドあれば、便利ですよね!

def sign_in_as(user)
  visit root_path
  click_link 'Login'
  fill_in 'Email', with: user.email
  fill_in 'Password', with: 'password'
  click_button 'Login'
end

  #1行で済む
  sign_in_as user

サポートモジュール作成

  • 別ファイルにログイン処理を切り出す
    共通で使えるモジュールを作成します.
    spec/supportディレクトリにLogin_support.rbという名前のファイルを作成します.
    ファイルの中にログイン処理のコードを記述します.
#spec/support/Login_support.rb
module LoginSupport
  def sign_in_as(user)
    visit root_path
    click_link 'Login'
    fill_in 'Email', with: user.email
    fill_in 'Password', with: 'password'
    click_button 'Login'
  end
end

# Rspec設定に読み込ませる
RSpec.configure do |config|
  config.include LoginSupport
end

モジュールの定義のあとにあるコードはモジュールを読み込ませるコードです.
読み込ませる別の方法としてconfig.include LoginSupportをspec/rails_helper.rb内に記述する方法もあります.
最後にspec/rails_helper.rb内の以下のコードがコメントアウトされているので、有効化してください.

Dir[Rails.root.join('spec', 'support', '**', '*.rb')].sort.each { |f| require f }

これで準備が整いました.

コードがスッキリ

スッキリしました.
このモジュールは他のテストでも使い回せるので、コードの重複が少なくなりスッキリしますね.

require 'rails_helper'
RSpec.feature "Users", type: :feature do
  describe 'ログイン後' do
    let(:user) {build(:user)}
    before do
      #ログイン処理
      sign_in_as user
    end
    describe 'ユーザー編集'  do
      context 'フォームの入力値が正常'  do
        it 'ユーザーの編集が成功する' do
          #編集の処理・・・
        end
      end
      context 'メールアドレスが未入力'  do
        it 'ユーザーの編集が成功する' do
           #編集の処理・・・
         end
      end
      context '登録済みのメールアドレスを使用' do
        it 'ユーザーの編集が失敗する' do
           #編集の処理・・・
        end
      end
    end
  end
end 

テスト結果を見やすくする(documentation format)

はじめに

10月からRunteqの課題取組中
駆け出しエンジニアです.
日々の学びをアウトプットします.

概要

  • テスト結果すこし見ずらい
  • テスト結果を見やすく
  • 毎回長いコマンド打ちたくない方

    テスト結果少し見づらい

    テスト実行

 $ bundle exec rspec
............................

Finished in 9.92 seconds (files took 2.2 seconds to load)
28 examples, 0 failures

え・・?
情報量が少なく、テストがパスしたことしかわからない.
もう少し情報がほしい.

テスト結果を見やすく

テスト実行時にオプションとして「--format documentation」をつける.

$ bundle exec rspec --format documentation

すると下のようにパスしたテスト項目が直感的に理解できる

$ bundle exec rspec --format documentation

Task
  validation
    is valid with all attributes
    is invalid without a title
    is invalid without a status
    is invalid with a duplicate title
    is valid with another title

Tasks
  ログイン前
    タスク新規作成
      新規作成ページへアクセス
        新規作成ページへのアクセスが失敗する
    タスクの編集
      編集編集ページへアクセス
        編集ページへのアクセスが失敗する
    タスクの削除
      root_pathへアクセス
        タスクの削除ボタンがみつからない
  ログイン後
    タスク新規作成
      フォームの入力値が正常
        タスクの新規作成が成功する
      タイトルが未入力
        タスクの新規作成が失敗する
      内容が未入力
        タスクの新規作成が失敗する
    タスクの編集
      フォームの入力値が正常
        タスクの編集が成功する
      タイトルが未入力
        タスクの編集が失敗する
      内容が未入力
        タスクの編集が失敗する
      ほかユーザーの編集ページにアクセス
        タスクの編集ページへのアクセスが失敗する
    タスクの削除
      タスク消去処理 ajaxではない
        タスクの削除が成功する

UserSessions
  ログイン前
    フォームの入力値が正常
      ログイン処理が成功する
    フォームが未入力
      ログイン処理が失敗する
  ログイン後
    ログアウトボタンをクリック
      ログアウト処理が成功する

Users
  ログイン前
    ユーザー新規登録
      フォームの入力値が正常
        ユーザーの新規作成が成功する
      メールアドレスが未入力
        ユーザーの新規作成が失敗する
      登録済みのメールアドレスを使用
        ユーザーの新規作成が失敗する
    マイページ
      ログインしていない状態
        マイページへのアクセスが失敗する
  ログイン後
    ユーザー編集
      フォームの入力値が正常
        ユーザーの編集が成功する
      メールアドレスが未入力
        ユーザーの編集が失敗する
      登録済みのメールアドレスを使用
        ユーザーの編集が失敗する
      他ユーザーの編集ページにアクセス
        編集ページへのアクセスが失敗する
    マイページ
      タスクを作成
        新規作成したタスクが表示される

Finished in 9.6 seconds (files took 2.03 seconds to load)
28 examples, 0 failures

テスト実行中は下の通りで、今どこのテストを行っているのかが分かります. Image from Gyazo またパスしなかったテストがあると、赤く表示されます. Image from Gyazo

毎回長いコマンド打ちたくない方

.rspecというファイルに下のように追加します.

#.rspec

--require spec_helper
#追記
--format documentation

するとオプションを打たなくても良くなります.

 $ bundle exec rspec

Task
  validation
    is valid with all attributes
    is invalid without a title
    is invalid without a status
    is invalid with a duplicate title
    is valid with another title

Tasks
  ログイン前
         ・
         ・
         ・
         ・

参考記事

shinkufencer.hateblo.jp

relishapp.com