オブジェクトとは
はじめに
プログラミング学習中の方向けです。
オブジェクトの理解を深めたい方の手助けになれば幸いです。
オブジェクトについて説明している記事と一緒に見ていただけると理解が深まると思います。
本記事は書籍現場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
- 参考サイト
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の動作はしていたが、テストで実行しているブラウザが適切ではなかったということになる.
- 同じ現象の人
解決方法
タブを切り替える処理をすれば解決する.
テストを実行するタブを変更するコード
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 - フローチャート(代名詞に迷ったら) ※返答の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)彼らは私の友達です.
理解度テスト
ここまでの内容で下のサイトのテストはすべて、解けます.
ぜひやってみてください.
ログイン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
これでもスッキリしたのですが、別のテストでもログイン処理は使いますよね...
例えば下のような実装がされているアプリがあったとします.
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
テスト実行中は下の通りで、今どこのテストを行っているのかが分かります. またパスしなかったテストがあると、赤く表示されます.
毎回長いコマンド打ちたくない方
.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 ログイン前 ・ ・ ・ ・