Subscribed unsubscribe Subscribe Subscribe

スキーマレスなMongoDBでmethod_missingを避ける

mongoid

MongoDBです。ORMにMongoidです。
ご存知の通り、スキーマレスなわけですよ。スキーマレスということはあれですよ、ドキュメントによってフィールドがあったりなかったりしちゃうわけです。

通常、Modelの各フィールドに対してはMongoidがうまいことやってくれるアクセサをとおしてやりとりします。

class Person
  include Mongoid::Document
  field :name, type: String
end

上記のようなドキュメントのフィールドに対して、次のようにアクセスできちゃうのです

person.name

ところが、例えばfirst_nameがnilの場合、メソッドチェーンなんかしてしまうとmethod_missingとなることがあります。
アプリ側で例外処理をしてもいいのですが、DB側でうまいことやってほしい場合もあります。
そんなとき、Mongoidならこんな手があります。

If the attribute does not already exist on the document, Mongoid will not provide you with the getters and setters and will enforce normal method_missing behavior. In this case you must use the other provided accessor methods: ( and =) or (read_attribute and write_attribute).

# Raise a NoMethodError if value isn't set.
person.gender
person.gender = "Male"

# Retrieve a dynamic field safely.
person[:gender]
person.read_attribute(:gender)

# Write a dynamic field safely.
person[:gender] = "Male"
person.write_attribute(:gender, "Male")
http://mongoid.org/docs/documents/dynamic.html

[] あるいは read_attribute、write_attribute を使うことで、method_missingを避けられます。