- 更新日: 2014年10月2日
- Ruby
instance_variable_set, instance_variable_getでレシーバのインスタンス変数を設定・取得
Ruby の instance_variable_set, instance_variable_get を使ったので忘れないようにまとめときます。Rails でユーザーのタイムゾーン管理絡みで使ったのですが、Rails で多言語・他地域のローカライズを行う場合、タイムゾーンの管理を以下の方針としています。
Rails でのタイムゾーン管理の方針 | EasyRamble
簡単に言うと、DB 内では全て UTC に統一して時刻を保存する方針。そして、時刻を出力する際に in_time_zone メソッドで、ユーザーのタイムゾーンに合わせて時刻を変換する。
instance_variable_set でレシーバにインスタンス変数の値を設定
上記方針でタイムゾーンを管理していたのですけど、一時的にユーザーのタイムゾーンに合わせて変換した時刻を、レシーバのオブジェクトに保持させたいケースに遭遇しました。ここで、レシーバにインスタンス変数の値を設定する instance_variable_set を使った。以下、pry での例です。
“user has_many posts” という関係のモデルで、user の最初の post オブジェクト(first_post)に、タイムゾーン変換後の時刻のインスタンス変数の値を instance_variable_set で設定します。first_post が作成されたタイムゾーン変換後の時刻として、@created_at_utz というインスタンス変数の値を設定している。
1 2 3 4 5 |
pry(main)> user = User.find_by(email: "username@example.com") pry(main)> first_post = user.posts.first pry(main)> first_post.instance_variable_set( :@created_at_utz, first_post.created_at.in_time_zone(user.time_zone) ) |
これで、first_post に @created_at_utz というインスタンス変数の値が設定されました。
1 2 3 4 5 6 |
pry(main)> first_post.instance_variables => [... ... :@created_at_utz] |
instance_variable_get でレシーバのインスタンス変数を取得
first_post の UTC 時刻。普通にモデルの属性にアクセスすれば良い。
1 2 3 4 |
pry(main)> first_post.created_at => Thu, 02 Oct 2014 20:25:30 UTC +00:00 |
first_post のタイムゾーン変換後の時刻(Tokyo/JST)を取得するには、instance_variable_get で先ほど設定した @created_at_utz インスタンス変数の値を取得できます。
1 2 3 4 |
pry(main)> first_post.instance_variable_get( :@created_at_utz ) => Fri, 03 Oct 2014 05:25:30 JST +09:00 |
一応これでやりたいことは実現できたのですけど、まだ良い方法がある気がするので、メタプログラミングRubyを読みなおそう。メタプログラミングRubyは、あと10回くらい読み直さないといけませんね。
- Ruby の関連記事
- Gemの作り方(Ruby Gem)
- ローカル開発中のgemをGemfileに書いてインストール
- 熊本地震の余震が夜に多いのは本当か?Rubyプログラムで検証してみた
- El Capitanでgemのnative extensionビルド失敗に対応
- Rubyで親クラスから子クラスの定数を参照
- MacabをRubyで使う
- rbenv/ruby-buildでRuby最新バージョンをインストール
- Rubyでクラスインスタンス変数にインスタンスメソッドからアクセス
- 距離1kmあたりの緯度・経度の度数を計算(日本・北緯35度)
- Google Maps Geocoding APIで住所から緯度・経度を取得するRubyコード
Leave Your Message!