Rubyのクラスで定義されたattr_accessor一覧をそのクラスのインスタンス変数から取り出す方法
一応題名の通りで「Rubyのクラスで定義されたattr_accessor一覧をそのクラスのインスタンス変数から取り出す方法」なのだが、何を言ってるのか書いた本人でも「?」となりがちなのでまずはやりたかったことから説明する。
例えばBookクラスがあって、そこに attr_accessorが定義されている。
class Book
attr_accessor :id, :title, :author
end
Bookクラスを作ってインスタンス変数を作る。
@book = Book.new
attr_accessorに定義されているように以下のように変数にアクセスできる。
> @book.title "STAR WARS"
やりたかったのはこの@bookを使って中で定義されているattr_accessorの一覧を取り出すこと。
こんな感じ。
> @book.something\_something [:id, :title, :author]
結果的にできた方法はこれ
class BaseModel
def self.attr_accessor(*vars)
@@attributes ||= []
@@attributes.concat vars
super
end
def attributes
@@attributes
end
end
class Book < BaseModel
attr_accessor :id, :title, :author
end
こうしておくと以下のように一覧が出る。やってみれば単純だけど、最初ちょっと悩んだ。
> @book.attributes [:id, :title, :author]
解説
クラスメソッドのattr_accessorの処理を上書きし、クラス変数として@@attributesを定義して、そこに一覧を格納しておくようにする。
def self.attr_accessor(*vars)
@@attributes ||= []
@@attributes.concat vars
super
end
インスタンス変数@bookからインスタンスメソッドのattributesが呼ばれたら、クラス変数を返す。
def attributes
@@attributes
end
もっといい方法をご存知でしたらぜひコメントください。
なんでこんなことをやっているのかというと個人プロジェクトで作っているRailにGoogle Cloud Datastoreをつなげようとしたのがことの始まり。Google Cloud PlatformはJavaやGo、Pythonなんかには初期から対応していたのにRubyはかなり後回し。最近になってやっと対応してくれたと思ったら、その公式サイトから出ているコードがなんとも微妙。
例えばGoogle Cloud DatastoreをつなげたRailsのModelのコード例がこんな感じ。
class Book
attr_accessor :id, :title, :author, :published_on, :description
# [START to_entity]
# ...
def to_entity
entity = Google::Cloud::Datastore::Entity.new
entity.key = Google::Cloud::Datastore::Key.new "Book", id
entity["title"] = title
entity["author"] = author if author
entity["published_on"] = published_on if published_on
entity["description"] = description if description
entity
end
# [END to_entity]
end
Bookクラスが1つだけならいいけど、後から作るモデルクラスにも全部いちいちentity[“なんやら”]って定義する訳にいかない。
初心者向けチュートリアルでわかりやすいといえばわかりやすいけど。
関連記事
海外移住のQ&Aサイト シティーズ
海外移住向けのQ&Aサイトを運営しています。現在、海外にお住まいの方、これから海外移住や留学、転職をお考えの方はぜひご参加ください。 登録はもちろん無料です。
シティーズ https://www.cityz.jp/
