カテゴリー別アーカイブ: Ruby

Ruby リフレクション メソッド名の取得

class ParentClass
  def super_public_method
  end

  def super_private_method
  end
  private :super_private_method

  def super_protected_method
  end
  protected :super_protected_method
end

class ChildClass < ParentClass
  def public_method
  end

  def private_method
  end
  private :private_method

  def protected_method
  end
  protected :protected_method
end

child = ChildClass.new

def child.singleton_method
end
child.methods  # => [:singleton_method, :public_method, :protected_method, :super_public_method, :super_protected_method, ...]
child.public_methods  #=> [:singleton_method, :public_method, :super_public_method, ...]
child.private_methods  # => [:private_method, :super_private_method, ...]
child.protected_methods  # => [:protected_method, :super_protected_method]
child.singleton_methods  # => [:singleton_method]

Ruby リフレクション インスタンス変数の取得・設定

class Clazz
  def initialize
    @foo = 1
    @bar = 2
  end
end

clazz = Clazz.new

インスタンス変数の取得には, Object#instance_variable_get を利用します. 定義されていないインスタンス変数の場合には, nilが返ります.

clazz.instance_variable_get(:@foo)    # => 1
clazz.instance_variable_get(:@bar)    # => 2
clazz.instance_variable_get(:@bazz)  # => nil

インスタンス変数の設定には, Object#.instance_variable_set を利用します. 定義されていないインスタンス変数の場合には, 新たに定義されます.

clazz.instance_variable_set :@foo, 3
clazz.instance_variable_get(:@foo)  # => 3
clazz.instance_variable_set :@bazz, 4
clazz.instance_variable_get(:@bazz)  # => 4

Ruby リフレクション インスタンス変数名の取得

インスタンス変数名を配列で取得するには, Object#instance_variables を利用します.

class Clazz
  def initialize
    @foo = 1
    @bar = 2
  end
end

clazz = Clazz.new

clazz.instance_variables  # => [:@foo, :@bar]

また, インスタンス変数が定義されているかどうかを調べるには, Object#instance_variable_defined? を利用します.

clazz.instance_variable_defined?(:@foo)       # => true
clazz.instance_variable_defined?(:@bar)        # => true
clazz.instance_variable_defined?(:@barbaz)  # => false
clazz.instance_variable_defined?(:foo)           # => NameError

RSpecによるユニットテスト

1. bundlerのインストール

$ gem install bundler

2. Gemfileの生成

$ bundle init

3. Gemfileを以下のように修正

# A sample Gemfile
source "https://rubygems.org"

# gem "rails"

->

# A sample Gemfile
source "https://rubygems.org"

gem "rspec", ">= 3.0.0"

4. RSpecのインストール (Gemfile.lockが生成される)

$ bundle install

5. .rspecとspec/spec_helper.rbの生成

$ bundle exec rspec --init

6. spec/spec_helper.rbの修正 (=beginと=endの消去)

=begin
  # These two settings work together to allow you to limit a spec run
  # to individual examples or groups you care about by tagging them with
  # `:focus` metadata. When nothing is tagged with `:focus`, all examples
  # get run.
  config.filter_run :focus
  config.run_all_when_everything_filtered = true

  # Allows RSpec to persist some state between runs in order to support
  # the `--only-failures` and `--next-failure` CLI options. We recommend
  # you configure your source control system to ignore this file.
  config.example_status_persistence_file_path = "spec/examples.txt"

  # Limits the available syntax to the non-monkey patched syntax that is
  # recommended. For more details, see:
  #   - http://rspec.info/blog/2012/06/rspecs-new-expectation-syntax/
  #   - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/
  #   - http://rspec.info/blog/2014/05/notable-changes-in-rspec-3/#zero-monkey-patching-mode
  config.disable_monkey_patching!

  # This setting enables warnings. It's recommended, but in some cases may
  # be too noisy due to issues in dependencies.
  config.warnings = true

  # Many RSpec users commonly either run the entire suite or an individual
  # file, and it's useful to allow more verbose output when running an
  # individual spec file.
  if config.files_to_run.one?
    # Use the documentation formatter for detailed output,
    # unless a formatter has already been configured
    # (e.g. via a command-line flag).
    config.default_formatter = 'doc'
  end

  # Print the 10 slowest examples and example groups at the
  # end of the spec run, to help surface which specs are running
  # particularly slow.
  config.profile_examples = 10

  # Run specs in random order to surface order dependencies. If you find an
  # order dependency and want to debug it, you can fix the order by providing
  # the seed, which is printed after each run.
  #     --seed 1234
  config.order = :random

  # Seed global randomization in this process using the `--seed` CLI option.
  # Setting this allows you to use `--seed` to deterministically reproduce
  # test failures related to randomization by passing the same `--seed` value
  # as the one that triggered the failure.
  Kernel.srand config.seed
=end

RSpecでユニットテストができる環境が構築できました.

テストコード例

RSpec.describe "add" do
  it "should return 2" do
    expect(1 + 1).to eq 2
  end
end

テスト実行

$ bundle exec rspec