#はじめに
この記事は、以下の記事の続きです。
http://qiita.com/testnin2/items/6be9b87571a99e01002a
Step6 relational propertyのネスト
relational propertyが取得できることで出来ることが広がりますが、更にネストして利用できるところが、更に便利なところです。例えば、
acct = client['Account'].getObject(mask='id, virtualGuests')
だけでは、Accountデータ型オブジェクトのうち、local propertyのidとrelational propertyのvirtualGuests(Virtual_Guestデータ型オブジェクト)を取得しているだけになりますが、当然virtualGuestsオブジェクト自身もlocalプロパティ、relationalプロパティ、countプロパティを持っているので、
acct = client['Account'].getObject(mask='id, virtualGuests.id, virtualGuests.location')
と書くことで、
- Accountデータ型オブジェクトのlocal propertyであるid
- Accountデータ型オブジェクトのrelational propertyであるvirtualGuests(これはVirtual_Guestデータ型オブジェクト)の、そのまたlocal propertyであるidとrelational propertyのlocation
が一気に取得できます。この考え方を更に深めていくと、単にデータを参照するだけであれば、時には直接methodを順次呼び出すより強力な使い方が可能になります。例えば、
import SoftLayer
import pprint
pp = pprint.PrettyPrinter(indent=4)
client = SoftLayer.create_client_from_env()
acct = client['Account'].getObject(mask='id, virtualGuests.billingItem.orderItem.order.userRecord.username')
pp.pprint(acct)
のように記述することで、
virtualGuests(Virtual_Guestデータ型オブジェクト)
-> billingItem(Billing_Item_Virtual_Guestデータ型オブジェクト)
-> orderItem(Billing_Order_Itemデータ型オブジェクト)
-> order(Billing_Orderデータ型オブジェクト)
-> userRecord(User_Customerデータ型オブジェクト)
-> username
と関連するデータ型オブジェクトを参照していくことで、virtual serverの作成者にアクセスすることができます。まとめると、
「ルール5: method実行時にmaskを指定してlocal propertyやrelational propertyを"."で辿っていくことで、互いに関連するオブジェクトを取得できる」
ということです。これはすごく便利ですよね!
ちなみに、初回のルール2にて、methodの返り値はServiceオブジェクトにならない(methodoを含むオブジェクトにはならない)ので、getXXX().getYYY().getZZZ()
みたいに奥に奥にと辿っていくことができないことを書きましたが、この考え方を補完してくれるのがmaskによるpropertyのネストなのでしょう。
Step 7 maskの様々な表現方法
##その1
acct = client['Account'].getObject(mask='id')
は、
acct = client['Account'].getObject(mask='mask.id')
のように紹介されていることもあります。多分、mask.idのmaskの部分がmethodで取得したobjectを指し示しているのでしょう。好みが分かれますが、冗長な気がするので、私は付けない派です。
唯一mask.propertyのように書くと良いケースは、取得したオブジェクトに対して明確な型を宣言したい時ですが、これを使うケースは稀だと思うので、ここでは紹介しません。詳細な具体例を知りたい場合は、http://qiita.com/testnin2/items/2e97b8701b8029bbca20 を参考にして下さい。
##その2
acct = client['Account'].getObject(mask='id, virtualGuests.id, virtualGuests.datacenter')
は
acct = client['Account'].getObject(mask='id, virtualGuests[id, datacenter]')
と書いても良いです。後者の方が可読性が高いと思うので好みです。
##その3
maskはある程度長くなると見辛くなるので、以下のように段組みをした方が更に可読性が上がります。例えば、以下は単なるgetObject()
一発で、仮想サーバーのFQDN,費用、作成者などが取得できます。methodは1つしか実行していないように見えますが、maskで関連データを掘り下げて取得しています。
import SoftLayer
import pprint
pp = pprint.PrettyPrinter(indent=4)
client = SoftLayer.create_client_from_env()
objectmask = """
id,
virtualGuests[
id,
fullyQualifiedDomainName,
billingItem[
id,
recurringFee,
orderItem[
id,
description,
order[
id,
userRecord[
id,
username
]
]
]
]
]
"""
acct = client['Account'].getObject(mask=objectmask)
pp.pprint(acct)
#おわりに
いかがでしたでしょうか?一連の記事で使っていたmethodは、ほぼgetObject()
だけです。それにも関わらず、最後の例のように次々と関連する情報が取得できることを考えると、SoftLayerにおけるpropertyの奥深さを実感していただるのではないでしょうか?
とりあえず、「ShinobiLayer: SoftLayer API 次の一歩: データ型オブジェクト」については、ここでいったん終了としたいと思います。
参考文献
http://sldn.softlayer.com/article/SoftLayer-API-Overview
http://sldn.softlayer.com/article/Object-Masks
http://softlayer-python.readthedocs.org/en/latest/index.html
https://gist.github.com/underscorephil
(もし希望があれば)続編予告
ちなみに、「これだと全部maskを使って取得すればいいから、methodなんて大して重要じゃないんじゃないの?」っていう人がいるかもしれませんが、、、実はmethodはmethodで便利な使い方があるのです。。。が、意外に書くのが疲れました。もし希望があれば、続編も頑張って書いてみたいと思います。