目的 |
メソッド |
例 |
結果例 |
メソッド関連 |
|
|
|
インスタンスメソッド一覧 |
Class.instance_methods(false) |
User.instance_methods(false) |
[:name, :email, :save_user] |
クラスメソッド一覧 |
Class.methods(false) |
User.methods(false) |
[:find_by_email, :active] |
メソッドの定義場所 |
obj.method(:name).source_location |
user.method(:save).source_location |
["/path/file.rb", 10] |
メソッドの存在確認 |
obj.respond_to?(:method) |
user.respond_to?(:email) |
true |
クラス・継承関連 |
|
|
|
継承チェーン |
Class.ancestors |
String.ancestors |
[String, Comparable, Object, ...] |
混入モジュール |
Class.included_modules |
User.included_modules |
[ActiveRecord::Base, ...] |
オブジェクトのクラス |
obj.class |
"hello".class |
String |
型チェック |
obj.is_a?(Class) |
"hello".is_a?(String) |
true |
変数・定数関連 |
|
|
|
インスタンス変数 |
obj.instance_variables |
user.instance_variables |
[:@name, :@email] |
クラス変数 |
Class.class_variables |
User.class_variables |
[:@@count] |
定数一覧 |
Class.constants |
Math.constants |
[:PI, :E] |
class User
def instance_method; end
def self.class_method; end
private
def private_method; end
end
# インスタンスメソッド(自分で定義したもののみ)
User.instance_methods(false)
# => [:instance_method]
# インスタンスメソッド(継承含む全て)
User.instance_methods(true)
# => [:instance_method, :class, :nil?, :===, :=~, ...]
# クラスメソッド(自分で定義したもののみ)
User.methods(false)
# => [:class_method]
# プライベートメソッドも含む
User.private_instance_methods(false)
# => [:private_method]
user = User.new
# メソッドオブジェクトを取得
method_obj = user.method(:save)
# 定義場所の確認
method_obj.source_location
# => ["/path/to/activerecord/base.rb", 123]
# メソッドのarity(引数の個数)
method_obj.arity
# => -1 (可変引数の場合)
# メソッドの所有者(定義されているクラス/モジュール)
method_obj.owner
# => ActiveRecord::Base
# メソッドの存在確認
user.respond_to?(:save)
# => true
user.respond_to?(:save, true) # プライベートメソッドも含む
# => true
# 特定のパターンにマッチするメソッドを検索
User.instance_methods.grep(/save/)
# => [:save, :save!, :save_user]
# 大文字小文字を無視して検索
User.instance_methods.grep(/SAVE/i)
# => [:save, :save!]
# ActiveRecord関連のメソッドを検索
User.instance_methods.grep(/^find/)
# => [:find_by, :find_by!, :find_each, ...]
# 動的に生成されたメソッドの確認(Rails)
User.instance_methods.grep(/_attributes/)
# => [:nested_attributes_options, :posts_attributes=, ...]
# クラスの継承チェーン
String.ancestors
# => [String, Comparable, Object, Kernel, BasicObject]
# 直接の親クラスのみ
String.superclass
# => Object
# 継承しているか確認
String < Object
# => true
String <= String # 自分自身も含む
# => true
class MyClass
include Enumerable
extend Forwardable
end
# 混入されているモジュール
MyClass.included_modules
# => [Enumerable, Kernel]
# 特定モジュールが混入されているか
MyClass.included_modules.include?(Enumerable)
# => true
# extend されたモジュールは特別な方法で確認
MyClass.singleton_class.included_modules
# => [Forwardable, ...]
user = User.new
# 基本的な型確認
user.class
# => User
user.class.name
# => "User"
# 継承関係の確認
user.is_a?(User)
# => true
user.is_a?(ActiveRecord::Base)
# => true (Userが継承している場合)
user.kind_of?(User) # is_a? の別名
# => true
# 厳密な型確認(継承関係を考慮しない)
user.instance_of?(User)
# => true
user.instance_of?(ActiveRecord::Base)
# => false
class User
def initialize(name, email)
@name = name
@email = email
@created_at = Time.now
end
end
user = User.new("田中", "[email protected]")
# インスタンス変数一覧
user.instance_variables
# => [:@name, :@email, :@created_at]
# インスタンス変数の値取得
user.instance_variable_get(:@name)
# => "田中"
# インスタンス変数の値設定
user.instance_variable_set(:@age, 30)
# インスタンス変数が定義されているか
user.instance_variable_defined?(:@name)
# => true
class User
@@count = 0
MAX_USERS = 1000
DEFAULT_ROLE = 'user'
end
# クラス変数一覧
User.class_variables
# => [:@@count]
# クラス変数の値取得
User.class_variable_get(:@@count)
# => 0
# 定数一覧
User.constants(false) # 自分で定義したもののみ
# => [:MAX_USERS, :DEFAULT_ROLE]
User.constants(true) # 継承したものも含む
# => [:MAX_USERS, :DEFAULT_ROLE, :ActiveSupport, :ActiveRecord, ...]
# 定数の値取得
User.const_get(:MAX_USERS)
# => 1000
# 定数が定義されているか
User.const_defined?(:MAX_USERS)
# => true
# ActiveRecordで動的生成されたメソッドを調査
def analyze_dynamic_methods(model_class)
puts "=== #{model_class} Dynamic Methods ==="
# enum関連のメソッド
enum_methods = model_class.instance_methods.grep(/\?$|!$/).select do |method|
model_class.defined_enums.keys.any? { |enum| method.to_s.include?(enum) }
end
puts "Enum methods: #{enum_methods}"
# association関連のメソッド
association_methods = model_class.instance_methods.grep(/_ids$|_attributes=$/)
puts "Association methods: #{association_methods}"
# scope関連のメソッド
scope_methods = model_class.methods(false).grep(/^[a-z]/)
puts "Possible scopes: #{scope_methods}"
end
analyze_dynamic_methods(User)
def method_location_map(obj, pattern = /.*/)
methods = obj.methods.grep(pattern)
methods.map do |method_name|
location = obj.method(method_name).source_location
[method_name, location]
end.select { |_, location| location }.group_by { |_, location| location[0] }
end
# 使用例:saveに関連するメソッドの定義場所
method_location_map(User.new, /save/)
def class_analysis(klass)
puts "=== #{klass} Analysis ==="
puts "Superclass: #{klass.superclass}"
puts "Ancestors: #{klass.ancestors.join(' -> ')}"
puts ""
puts "Own instance methods: #{klass.instance_methods(false).count}"
puts "All instance methods: #{klass.instance_methods(true).count}"
puts "Own class methods: #{klass.methods(false).count}"
puts ""
puts "Included modules:"
klass.included_modules.each { |mod| puts " #{mod}" }
puts ""
puts "Constants: #{klass.constants(false).count}"
if klass.constants(false).any?
puts " #{klass.constants(false).join(', ')}"
end
end
class_analysis(User)
# メソッドがどのように定義されたかを調査
def method_definition_analysis(klass, method_name)
if klass.instance_methods(false).include?(method_name)
method_obj = klass.instance_method(method_name)
location = method_obj.source_location
if location
puts "#{method_name}: Explicitly defined at #{location}"
else
puts "#{method_name}: Dynamically generated (no source location)"
end
else
puts "#{method_name}: Not found in #{klass}"
end
end
# Rails の動的メソッドを調査
method_definition_analysis(User, :email) # 通常の属性
method_definition_analysis(User, :active?) # enum メソッド
def module_inclusion_analysis(klass)
puts "=== #{klass} Module Inclusion ==="
# include されたモジュール
included = klass.included_modules - klass.superclass.included_modules
puts "Included: #{included.join(', ')}" if included.any?
# extend されたモジュール(singleton class に include)
extended = klass.singleton_class.included_modules -
klass.superclass.singleton_class.included_modules
puts "Extended: #{extended.join(', ')}" if extended.any?
# prepend されたモジュール
prepended = klass.ancestors.take_while { |ancestor| ancestor != klass }
puts "Prepended: #{prepended.join(', ')}" if prepended.any?
end
module_inclusion_analysis(User)
# メソッド呼び出しをトレース
trace = TracePoint.new(:call) do |tp|
puts "#{tp.defined_class}##{tp.method_id} called"
end
trace.enable do
user = User.new
user.save
end
def object_state_analysis(obj)
puts "=== Object State Analysis ==="
puts "Class: #{obj.class}"
puts "Object ID: #{obj.object_id}"
puts "Frozen: #{obj.frozen?}"
puts "Tainted: #{obj.tainted?}" if obj.respond_to?(:tainted?)
puts "\nInstance variables:"
obj.instance_variables.each do |var|
value = obj.instance_variable_get(var)
puts " #{var}: #{value.inspect}"
end
puts "\nResponds to common methods:"
[:save, :valid?, :errors, :id].each do |method|
puts " #{method}: #{obj.respond_to?(method)}"
end
end
object_state_analysis(User.new)
def unknown_object_analysis(obj)
puts "=== Unknown Object Analysis ==="
puts "Class: #{obj.class}"
puts "Ancestors: #{obj.class.ancestors.first(5).join(' -> ')}..."
puts "\nInteresting methods:"
interesting_methods = obj.methods.grep(/^[a-z]/).reject do |method|
[:class, :nil?, :respond_to?, :send, :object_id].include?(method)
end.first(20)
interesting_methods.each do |method|
begin
arity = obj.method(method).arity
arity_info = arity == 0 ? "(no args)" : "(#{arity} args)"
puts " #{method} #{arity_info}"
rescue
puts " #{method} (unknown arity)"
end
end
puts "\nInstance variables:" if obj.instance_variables.any?
obj.instance_variables.each do |var|
puts " #{var}"
end
end
# 使用例
unknown_object_analysis(some_mysterious_object)
# Rails モデルの動的メソッド一覧
User.instance_methods.grep(/_attributes|_ids/).sort
# 特定パターンのメソッドとその定義場所
User.instance_methods.grep(/save/).map { |m| [m, User.instance_method(m).source_location] }
# クラス階層の簡潔表示
User.ancestors.map(&:name).join(' -> ')
# ActiveRecord で生成されたメソッドの検出
User.instance_methods.select { |m| User.instance_method(m).source_location.nil? }
# モジュールの混入チェック
User.included_modules.map(&:name).grep(/Active/)
# 定数の値一覧
User.constants(false).map { |c| [c, User.const_get(c)] }.to_h
# インスタンス変数とその値
user.instance_variables.map { |v| [v, user.instance_variable_get(v)] }.to_h
# 引数なしメソッドの一覧
user.methods.select { |m| user.method(m).arity == 0 }.first(10)