Yanonoblog!

こつこつと

Rubyのハッシュとシンボルについて調べた内容

はじめに

Rubyのハッシュとシンボルについて調べた内容をまとめていきます。

ハッシュ

ハッシュはキーと値の組み合わせでデータを管理するオブジェクトです。

{ キー1 => 値1, キー2 => 値2, キー3 => 値3 }

要素の追加、変更、取得、繰り返し処理

ハッシュには要素を追加、変更、取得する方法や、要素を繰り返し処理する方法があります。

currencies = {'japan' => 'yen', 'us' => 'dollar', 'india' => 'rupee'}
# 追加・変更
currencies['italy'] = 'euro'
# 取得
currencies['india'] # => 'rupee'
# 繰り返し処理
currencies.each do |key, value|
    puts "#{key}: #{value}"
end

ハッシュの比較、要素数の取得、要素の削除

ハッシュの要素を比較したり、要素数を取得したり、特定のキーを持つ要素を削除する方法があります。

a = {'x' => 1, 'y' => 2}
b = {'x' => 999}

# 比較
a == b # => false

# 要素数の取得
a.size # => 2

# 要素の削除
a.delete('x') # => 1

シンボル

シンボルはコロンの後に名前を記述することで表現されます。

:apple
:japan

シンボルと文字列の違い

シンボルと文字列にはいくつかの違いがあります。

シンボルは内部で数値として管理されるため、処理が高速です。

シンボル 文字列
クラス Symbol String
中身の管理 整数として管理される 文字列
処理速度 早い(整数なので) シンボルより遅い
オブジェクトid(object_id) 同じシンボルなら同一 文字列ごとに異なる
破壊的変更(.upcase!など) できない できる

シンボルの特徴と用途

シンボルはメモリ効率が良く、値が変更されないため、ハッシュのキーなどによく使用されます。

# ハッシュのキー
currencies = { japan: 'yen', us: 'dollar' }

# 名前を識別する場合
status = :todo, :doing, :done

ハッシュのキーにシンボルを使う

ハッシュのキーとしてシンボルを使用する方法です。

currencies = { japan: 'yen', us: 'dollar', india: 'rupee' }
currencies[:us] # => "dollar"

メソッドのキーワード引数とハッシュ

メソッドの引数としてキーワード引数を使用する方法を示しています。

def method_name(param1: value1, param2: value2)
    # メソッドの内容
end

シンボルを%記法で表す

%記法を使用してシンボルを表現する方法です。

%i(apple orange melon) # => [:apple, :orange, :melon]

シンボルと文字列

文字列とシンボルを相互に変換する方法です。

# 文字列 → シンボル
"string".to_sym

# シンボル → 文字列
:symbol.to_s

おしまい

コメント

本記事の内容は以上になります!


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky

スプリント開発の基本概念、役割について

はじめに

本記事では、スプリント開発の基本概念をわかりやすく解説しまとめていきます。

スプリント開発の背景

現代のソフトウェア開発の現場ではスプリント開発という手法が用いられることか多いです。

これは、短期間での開発サイクルを重視し、迅速なフィードバックと改善を目指す手法です。

基本概念

スプリントは、一般的に2~4週間の期間で特定の目標を達成することを目指す手法です。

スプリントを用いることで、開発チームは迅速にアイデアを実現し、フィードバックを受け取り、改善を行うことができます。

アジャイル

アジャイルは、迅速な開発と顧客との継続的なコミュニケーションを重視するアプローチです。

このアプローチでは、開発チームは継続的に製品の改善と機能追加を行い、顧客とのコミュニケーションを密に行います。

スプリント

スプリント開発は、アジャイル開発の具体的な手法の1つで、短期間で開発プロジェクトを進めることを特徴としています。

スプリントの定義と目的

スプリントは、一般的に2~4週間の期間で特定の目標を達成することを目指す開発サイクルです。

このサイクルを通じて、特定のタスクを達成することを目指し、製品の迅速なリリースと改善を行います。

開発チームが迅速に製品の機能を開発・リリースし、フィードバックを受け取ることで、継続的な改善を行うことができる環境を整えることが目的です。

スプリントの流れ

スプリント開発は以下のステップで構成されています。

  1. 計画段階:期間と目標を設定し、取り組むタスクを選定。
  2. 実行段階:タスクの進行状況を日々共有し、問題を迅速に解決。
  3. レビュー段階:成果を評価し、フィードバックを収集。
  4. 反省段階:過去のスプリントの振り返りを行い、改善点を特定。

スプリント開発の役割

開発者

スクラムにおける「開発者」は、リリース可能な成果物を作成する役割を指します。

  • 主な責任
    • スプリントの計画を作成
    • 品質を保ちながら完成の定義を守る
    • スプリントゴールに向けて計画を調整
    • 専門家としての責任を共有

プロダクトオーナー

プロダクトの価値を最大化する役割です。プロダクトの改善に必要な要件を作成・管理します。

  • 主な責任

スクラムマスター

おしまい

コメント

本記事の内容は以上になります!


RSpecによるテストの種類とその特徴

はじめに

本記事では、RSpecのテストの種類とその特徴についてまとめています。

単体テスト (ユニットテスト)

  • 1つのクラスやメソッドが正しく動作するかを確認するテスト。
  • テストの実行速度が速い。

# spec/models/fruit_spec.rb
RSpec.describe Fruit, type: :model do
  it "名前が存在する場合、有効である" do
    fruit = Fruit.new(name: "apple")
    expect(fruit).to be_valid
  end
end

結合テスト (インテグレーションテスト)

概要

  • 複数のコンポーネントや機能が連携して正しく動作するかを確認するテスト。
  • APIのレスポンスや、特定の画面の動作をテストすることが多い。

rubyCopy code
# spec/requests/shop_spec.rb
RSpec.describe "Shop Management", type: :request do
  it "店舗情報を取得する" do
    get shop_path(id: 1)
    expect(response.status).to eq 200
  end
end

システムテスト

概要

  • ユーザーの操作を模倣して、アプリケーション全体が正しく動作するかを確認するテスト。
  • Capybaraなどの外部ライブラリを使用してブラウザ上での操作をシミュレートする。

rubyCopy code
# spec/system/order_spec.rb
RSpec.describe "Order Process", type: :system do
  it "商品をカートに追加して注文する" do
    visit item_path(id: 1)
    click_on "カートに追加"
    click_on "注文を確定する"
    expect(page).to have_content "注文が完了しました"
  end
end

その他のテスト

  • Viewテスト: ビューの表示内容をテストする。
  • Helperテスト: ヘルパーメソッドの動作をテストする。
  • Routingテスト: ルーティングの設定をテストする。
  • Jobテスト: バックグラウンドジョブの動作をテストする。
  • Mailerテスト: メール送信の動作をテストする。

ディレクトリ構造例

RSpecでのテストのディレクトリ構造は、テストの種類に応じて整理されています。

以下は、上記で紹介されたテストの種類に基づくディレクトリ構造とその解説です。

spec/
│
├── models/               # モデルのテストを配置するディレクトリ
│   ├── fruit_spec.rb    # Fruitモデルのテスト
│   └── ...
│
├── requests/            # APIのレスポンスや特定の画面の動作など、複数のコンポーネントが連携して動作する部分の結合テストを配置するディレクトリ
│   ├── shop_spec.rb     # Shopに関する結合テスト
│   └── ...
│
├── system/              # ユーザーの操作を模倣して、アプリケーション全体の動作を確認するシステムテストを配置するディレクトリ
│   ├── order_spec.rb    # Orderに関するシステムテスト
│   └── ...
│
├── views/               # ビューの表示内容やレイアウトなど、ビューの表示に関するテストを配置するディレクトリ
│   └── ...
│
├── helpers/             # ヘルパーメソッドの返り値や動作に関するテストを配置するディレクトリ
│   └── ...
│
├── routing/             # ルートの解決やリダイレクトなどのルーティングテストを配置するディレクトリ
│   └── ...
│
├── jobs/                # ジョブの実行や結果などのバックグラウンドジョブのテストを配置するディレクトリ
│   └── ...
│
└── mailers/             # メールの送信や内容などのメーラーのテストを配置するディレクトリ
    └── ...

おしまい

コメント

本記事の内容は以上になります!


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky

RSpecにおける特定のディレクトリを除外する方法、設定について

はじめに

テストの実行時に特定のディレクトリやファイルを除外する方法を解説します。

今回の例では、spec/animalsディレクトリを通常のテスト実行時に除外し、カスタムのrakeタスクでのみ実行する方法を示します。

RSpecの設定変更

設定ファイルの編集

spec_helper.rbまたはrails_helper.rbに以下の設定を追加します。

# 通常のテスト実行時にspec/animalsディレクトリを除外
RSpec.configure do |config|
  config.filter_run_excluding animals: true unless ENV['CUSTOM_TEST_EXECUTION']
end

filter_run_excludingRSpecの設定メソッドの一つで、指定したメタデータを持つテストを実行から除外するために使用されます。

filter_run_excluding の基本的な使い方

RSpecのテストにはメタデータを指定することができます。このメタデータを利用して、特定のテストのみを実行したり、特定のテストを実行から除外したりすることができます。

filter_run_excluding は、指定したメタデータを持つテストを実行から除外するためのメソッドです。

例えば、以下のように設定すると、slow: true というメタデータを持つテストは実行から除外されます。

RSpec.configure do |config|
  config.filter_run_excluding slow: true
end

この設定がある場合、以下のように slow: true というメタデータを持つテストは実行されません。

it "does something slow", slow: true do
  # このテストは実行されない
end

テストファイルへのタグ追加

タグの追加

spec/animalsディレクトリ内の各テストファイルにタグを追加します。

# spec/animals/cat_spec.rb
RSpec.describe Cat, animals: true do
  # テスト内容
end

Rakeタスクの作成

カスタムRakeタスク

カスタムのrakeタスクを作成し、このタスクを実行する際にのみspec/animalsディレクトリのテストを実行します。

# lib/tasks/custom_test.rake
namespace :custom_test do
  desc '特定のディレクトリのテストを実行する'
  task :animals do
    ANIMALS = [:cat, :dog]

    ANIMALS.each do |animal|
      begin
        # 環境変数を設定
        ENV['CUSTOM_TEST_EXECUTION'] = 'true'

        # テストの実行
        Rake::Task["spec"].clear
        RSpec::Core::RakeTask.new(:spec) do |t|
          t.pattern = "./spec/animals/#{animal}_spec.rb" # テストファイルの指定
        end
        Rake::Task["spec"].execute
      rescue => e
        puts "エラー: #{animal}のテスト中に問題が発生しました。エラー詳細: #{e.message}"
      end
    end

    # 環境変数のリセット
    ENV['CUSTOM_TEST_EXECUTION'] = nil
  end
en

上記の手順に従うことで、通常のテスト実行時にはspec/animalsディレクトリのテストが除外され、カスタムのrakeタスクを実行したときのみ該当のテストが実行されるようになります。

おしまい

コメント

本記事の内容は以上になります!


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky

GraphQL - スキーマとタイプ

はじめに

GraphQLのドキュメントを読んでまとめていきます。

ところどころ気になった部分を調べて補足したり解釈を入れています。

https://graphql.org/learn/schema/

スキーマとタイプ

GraphQLのスキーマとタイプに関するこのセクションでは、GraphQLのタイプシステムと、データのクエリに関する情報の記述方法について学びます。

タイプシステム

GraphQLのクエリは、基本的にオブジェクト上のフィールドを選択することに関連しています。

サンプルコード

{
  # heroフィールドを選択
  hero {
    # heroによって返されるオブジェクトのnameとappearsInフィールドを選択
    name
    appearsIn
  }
}

このクエリの形状は結果に密接に一致するため、サーバーについてあまり知らなくても、クエリが何を返すかを予測できます。

スキーマの役割

すべてのGraphQLサービスは、そのサービスでクエリできる可能なデータのセットを完全に記述するタイプのセットを定義します。

その後、クエリが入ってくると、スキーマに対して検証および実行されます。

タイプ言語

GraphQLサービスは任意の言語で書かれています。

特定のプログラミング言語の構文に依存することなく、GraphQLスキーマについて話すため、独自のシンプルな言語を定義します。

オブジェクトタイプとフィールド

サンプルコード

# Character ・・・ GraphQLのオブジェクトタイプ
type Creature {
  # nameはフィールドで、String型のデータを返す。"!"はそのフィールドがnullでないことを意味する。
  name: String!
  # livesInはEpisodeオブジェクトの配列を返す
  livesIn: [Location!]!
}
  • name と livesIn・・・Creatureタイプのフィールドで、動作するGraphQLクエリの任意の部分に表示できます。
  • String・・・組み込みのスカラータイプの1つで、これらのタイプは単一のスカラーオブジェクトに解決され、クエリでサブセレクションを持つことはできません。
  • [Location!]!・・・これはLocationオブジェクトの配列を表します。 これもnull不可なので、livesInフィールドをクエリするときには常に配列(0項目以上)を期待できます。 また、Location!もnull不可なので、配列の各項目がLocationオブジェクトであることを常に期待できます。

おしまい

コメント

本記事の内容は以上になります!


GraphQL - ディレクティブとミューテーション

はじめに

GraphQLのドキュメントを読んでまとめていきます。

ところどころ気になった部分を調べて補足したり解釈を入れています。

https://graphql.org/learn/queries/

ディレクティブの使用

ディレクティブは、クエリの実行方法を動的に変更するためのものです。

フィールドの取得を条件付きで制御したり、特定の操作を実行する前後にカスタムのロジックを追加するために使用されます。

サンプルコード

サンプルコードの中でディレクティブが使用されている部分は、@include(if: $withDetails) です。

query GetAnimal($type: AnimalType, $withDetails: Boolean!) {
  animal(type: $type) {
    name
    habitat @include(if: $withDetails) {
      location
    }
  }
}

このディレクティブは、$withDetails の値が true の場合にのみ habitat フィールドをクエリの結果に含めるように指示しています。

もし $withDetailsfalse であれば、habitat フィールドは結果に含まれません。

ミューテーション

GraphQLでは、データの変更や新しいデータの追加を行うために「ミューテーション」を使用します。

サンプルコード

このミューテーションは、指定されたpostIdの投稿に対して新しいコメントを作成し、そのコメントのtextauthorを返すことを意図しています。

# mutationキーワードで、データの変更を行うミューテーションを宣言
mutation CreateCommentForPost($postId: ID!, $comment: CommentInput!) {

  # 実際にデータを変更するミューテーションの関数
  createComment(postId: $postId, comment: $comment) {

    # ミューテーションの結果として取得したいデータのフィールドを指定
    # この例では、新しく作成されたコメントの `text` と `author` を取得
    text
    author
  }
}

インラインフラグメント

インターフェースやユニオンタイプを返すフィールドをクエリする場合、具体的なタイプのデータにアクセスするためにインラインフラグメントを使用します。

サンプルコード

# queryキーワードで、データの取得を行うクエリを宣言
query GetVehicle($id: ID!) {

  # 指定されたIDに関連する車両の情報を取得するクエリの関数
  vehicle(id: $id) {

    # 全ての車両タイプで共通のnameフィールドを取得
    name

    # インラインフラグメントを使用して、返される車両が「Car」タイプの場合のみアクセスするフィールドを指定する
    ... on Car {
      # 車のドアの数を取得
      numberOfDoors
    }

    # 同様に、返される車両が「Bike」タイプの場合のみアクセスするフィールドを指定する
    ... on Bike {
      # 自転車のタイプ(例: ロードバイク、マウンテンバイクなど)を取得
      type
    }
  }
}

メタフィールド

GraphQLでは、__typenameなどのメタフィールドを使用してオブジェクトタイプの名前を取得します。

これによって、返されるオブジェクトがどのタイプであるかをクライアントが知ることができます。

サンプルコード

# この場合は "book"に関連する情報を取得
{
  # findは、指定されたアイテムに関連する情報を取得するクエリの関数名
  find(item: "book") {

    # __typenameはメタフィールドで、現在のオブジェクトのタイプ名を取得する
    __typename

    # インラインフラグメントを使用して、返される書籍が「Novel」タイプの場合のみアクセスするフィールドを指定する
    ... on Novel {
      # 小説のタイトルを取得
      title
    }

    # 同様に、返される書籍が「Magazine」タイプの場合のみアクセスするフィールドを指定する
    ... on Magazine {
      # 雑誌の発行日を取得
      issueDate
    }
  }
}

おしまい

コメント

本記事の内容は以上になります!


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky

RSpecで特定のディレクトリのテストのみを実行する方法

はじめに

Rakeタスクは、Rubyのプログラムで構成されるビルドツールであるRake (Ruby Make) の一部です。

今回はRakeタスクとRSpecを使用して特定のディレクトリのテストのみを実行、自動化する方法を紹介します。

Rakeタスクのカスタマイズ

Rakeタスクを使用して、特定のディレクトリのテストのみを実行する方法をカスタマイズすることができます。

以下は、その一例です。

namespace :custom_test do
  desc '各職種ごとの動作を確認するためのテストを実行する'
  task :positions do
    POSITIONS = [
      :position_manager,
      :position_employee,
    ]

    POSITIONS.each do |position_name|
      begin
        ENV['CURRENT_POSITION'] = position_name.to_s
        ENV['RAKE_TASK_EXECUTION'] = 'true'
        puts "#{position_name}のテストを実行開始..."

        # /spec/positions ディレクトリ配下のspecファイルのみを読み込むように指定
        Rake::Task["spec"].clear # 既存のタスクの定義をクリア
        RSpec::Core::RakeTask.new(:spec) do |t|
          t.pattern = './spec/positions/**/*_spec.rb'
        end
        Rake::Task["spec"].execute
      rescue => e
        puts "エラー: #{position_name}のテスト中に問題が発生しました。エラー詳細: #{e.message}"
      end
    end

    ENV['CURRENT_POSITION'] = nil
    ENV['RAKE_TASK_EXECUTION'] = nil
  end
end

Rakeタスクのカスタマイズにおける詳細解説

Rake::Task["spec"].clear

Rakeモジュールに含まれるTaskクラスのクラスメソッド [] を使用しています。

このメソッドは、タスク名を引数として受け取り、その名前に対応するタスクオブジェクトを返します。

"spec"というタスクオブジェクトのclearメソッドで、現在の定義をクリアします。

Rakeタスクは一度定義されると、その後の実行で再定義することができません。

しかし、clearメソッドを使用することで、既存のタスクの定義を削除し、新しい定義を追加することができます。

RSpec::Core::RakeTask.new(:spec)

RSpecのコアモジュールに含まれるRakeTaskクラスを使用して、新しいRSpecのテストを実行するためのRakeタスクのインスタンスを生成しています。

:specは、新しく定義するRakeタスクの名前を示しています。

RSpec::Core::RakeTaskクラスを使用することで、RakeのタスクとしてRSpecのテストを簡単に実行することができます。

do |t|

この部分は、新しく定義するRakeタスクの設定を行うためのブロックを開始しています。|t|は、新しく定義するRakeタスクのインスタンスを参照するための変数です。

t.pattern = './spec/positions/*/_spec.rb’

この行は、Rakeタスクが実行する際に読み込むテストファイルのパターンを指定しています。

./spec/positions/ディレクトリ以下のすべての*_spec.rbという名前のファイルを対象としています。

*/は任意のサブディレクトリを示し、_spec.rb_spec.rbで終わる任意のファイルを示しています。

Rake::Task["spec"].execute

上で新しく定義した"spec"という名前のRakeタスクを実行します。

このタスクは、上で指定したパターンに一致するテストファイルを対象としてRSpecのテストを実行します。

RSpecのテスト実行時の読み込み内容

通常のRSpecのテスト実行時には、デフォルトの設定やspec_helper.rbrails_helper.rbなどの設定に基づいて、/specディレクトリ配下のすべての*_spec.rbファイルが読み込まれます。

したがって、特定のRakeタスク内でRSpecのタスクを再定義して特定のディレクトリやファイルのみを読み込むように指定した場合、そのRakeタスクを実行したときだけその指定が適用されます。

公式ドキュメントの参照

RSpecやRakeタスクの詳細な使い方やオプションについては、公式ドキュメントを参照してください。

おしまい

コメント

本記事の内容は以上になります!


プログラミングスクールのご紹介 (卒業生より)

お世話になったプログラミングスクールであるRUNTEQです♪

https://runteq.jp/r/ohtFwbjW

こちらのリンクを経由すると1万円引きになります。

RUNTEQを通じて開発学習の末、受託開発企業をご紹介いただき、現在も双方とご縁があります。

もし、興味がありましたらお気軽にコメントか、TwitterのDMでお声掛けください。

https://twitter.com/outputky