LoginSignup
20
16

More than 5 years have passed since last update.

RubyのHash要素にドット記法でアクセスさせる(Hashクラス拡張せずに特定のオブジェクトにのみ適用する)

Last updated at Posted at 2015-02-14

Goal

  • hash['key']ではなく、hash.keyでアクセスさせる
  • クラス拡張の影響を特定の範囲内におさえるため、Hashクラス拡張せずに対応する
  • hashインスタンスに拡張モジュールをextendする

Code

hash_ext.rb
require 'pp'

module HashExtension
  def method_missing(method, *params)
    if method.to_s[-1,1] == "="
      # シンボルキーに優先的に書き込む
      key = method.to_s[0..-2].gsub(':', '')
      key = self.has_key?(key.to_sym) ? key.to_sym :
        ( self.has_key?(key.to_s) ? key.to_s : key.to_sym )
      self[key] = params.first
    else
      # シンボルキーとストリングキー両方存在する場合、
      # シンボルキーを優先的に返す
      key = self.has_key?(method.to_sym) ? method.to_sym : method.to_s
      self[key]
    end
  end
end

hash1 = { name: 'Isaac Newton', age: 372 }
hash2 = { name: 'Carolus Fridericus Gauss', age: 237 }

##
## hash1のオブジェクトのみmethod_missing機能拡張する
## 
hash1.extend HashExtension

## 
## hash1オブジェクトはメソッドよびだしでハッシュ要素にアクセスできるが、
## HashExtensionをextendしていないhash2オブジェクトには拡張の影響が及んでいないことを確認
## 
p hash1.name
  # "Isaac Newton"
p hash2.name
  # hash_ext.rb:17:in `<main>': undefined method `name' for {:name=>"Carolus Fridericus Gauss", :age=>237}:Hash (NoMethodError)

## 
## 代入時はキーが存在すれば上書き、存在しなければ追加することを確認
## 

hash1.name = "Sir Isaac Newton"
hash1.role = "physicist"

pp hash1
  # {:name=>"Sir Isaac Newton", :age=>372, :role=>"physicist"}

Environment

% uname -a
Linux *** 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/Linux

% ruby -v
ruby 2.1.1p76 (2014-02-24 revision 45161) [x86_64-linux]

% cat /etc/issue
CentOS release 6.5 (Final)
Kernel \r on an \m
20
16
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
20
16