« 2013年6月 | メイン | 2013年8月 »

2013年7月

2013年7月24日 (水)

herokuにSQLを実行するプラグインを作成する

こんにちは

今朝herokuからwebinarの案内が来ていました。日本時間だと午前2時からのWebinarなんで多分スルーなんですが(^^;;;、アジェンダの中にたまたま目にとまった1行がありました。

 

•Using heroku-pg-extras to gain visibility into database performance

 

「heroku-pg-extras」って何じゃい?と思って検索したところ予想通りGitHubでソースが見つかりました。(^^v

 

https://github.com/heroku/heroku-pg-extras

 

ふむふむ。postgresqlの統計情報ビューからSELECTした結果をコマンド一発で表示するプラグインなのね。

ここで実行されているSQLがどういう時に有用なのかはよくわかりませんが。。。(^^;

ソースの方も見ましたが中身は単純にSQLを発行しているだけなんで、自分用にカスタマイズするのも簡単そうです。

□□□□

だいたい内容はわかったので、興味を失いかけたところでふと気がつきました。

あれ?これちょっとカスタマイズすれば。。。

 

heroku myapp:user_count
heroku myapp:sales

 

みたいな感じで個別案件で欲しい情報がコマンド一発でとれるプラグインが作れるんじゃね?

改めてソースを眺めてみたところ多分簡単にできるんじゃないかと思ったので、ちょっと試してみました。

 

★gitリポジトリをコピる

herokuコマンドのプラグイン拡張は直接gitから必要なモジュール一式を引っこ抜くという大胆な構成をしています。つまり、pluginを作成するにはgitリポジトリが必要です。

通常ならGitHubを使えば良いんですが、今回は個別案件専用のプラグインなのでBacklogのgitを使いました。

 

git clone git@github.com:heroku/heroku-pg-extras.git
git remote rm origin
git remote add origin xxx@xxx.git.backlog.jp:/xxx-project/myapp-sqlplugin.git
git push origin master
heroku plugins:install xxx@xxx.git.backlog.jp:/xxx-project/myapp-sqlplugin.git

heroku pg:cache_hit

 

pluginのインストールがGitHub以外からでも行えるかどうかイマイチ確信がなかったんですが、特に問題ないようです。

ちなみにプラグイン名はGitのリポジトリ名(上の例の場合は「myapp-sqlplugin」)になるようです。

 

★案件用にカスタマイズする

とりあえずpg-extrasを別の名前でプラグインとしてインストールすることに成功したのでここから案件用にカスタマイズしていきます。

pg-extrasは「heroku pg」にコマンドを追加するという形で実装されているんですが、個別案件用の名前として「pg」はふさわしくないのでまずはコマンド名を変更してみます。

 

class Heroku::Command::Pg < Heroku::Command::Base
↓
class Heroku::Command::Myapp < Heroku::Command::Pg

 

クラス名がコマンド名だろうというのは単なる勘です。消去法でここしかそれらしいところが無いので多分そうだろうという。。。(^^;;;

最初は継承元のクラスをBaseのままにして試しましたが、それだと動きませんでした。まぁpostgresqlを使うためのするためのprivateメソッドが何かあるんでしょう。継承元をPgに変更したところ見事「heroku myapp:cache_hit」というコマンドで動作するようになりました。(^^v

 

★pluginsディレクトリで直接修正してみる

ところで先の修正は最初にcloneしたgitリポジトリで行っていました。これはherokuコマンドの参照するプラグイン本体ではないので修正内容をプラグインに反映させるためには以下のコマンドを叩く必要があります。

 

git add .
git commit -m "Modify class name"
git push origin master
heroku pugins:update myapp-sqlplugin

 

一度修正内容をgitにpushして「heroku plugins」コマンドでそれを取り直す必要があるわけです。まぁめんどくさいです。

トライ&エラーで修正している時にはこんな手順踏んでられないので、Herokuのプラグインディレクトリで直接修正することにしました。

Windowsの場合はHerokuプラグインは

 

<ユーザーホーム>/.heroku/plugins

 

にあります。「heroku plugins:update」コマンドは要するにここで「git pull」を実行しているだけなので、ここを修正のワークにしても特に問題ないはずです。

これでソースを修正したらすぐに動作確認ができるようになりました。(^^v

 

★案件用のコマンドを追加してみる

ソース眺めると一目瞭然でコマンド追加方法は見当がつくんですが、例えばユーザー数をカウントするコマンドの追加は以下のようになります。

 

  def user
    sql = %q(
      SELECT count(*) AS user_count FROM user_table
    )
    puts exec_sql(sql)
  end

 

要するにpublicメソッドがそのままコマンドになって、putsで結果を出力しているだけなんですね。

コマンド追加で修正するのはほとんどSQLだけなので、僕のようにRubyにあんまり詳しくなくても特につまることなく修正、動作確認までできました。(^^v

元々あるcache_hitなどのコマンドは使わないのであれば削除してしまってOKです。

 

★オプション引数を追加してみる

例えば売上取得のSELECT文なんかでは年、月をパラメータで指定したいわけですよ。

ここまですこぶる快調に実装できてきたので、あとはパラメータを使用するサンプルだけ書いて、残りは案件担当者に自分で必要なSQLを追加してもらえば良いかと思っていたんですが、最後の最後ではめられました。(--

というか、やり方が分かった時には「こんなんアリかよ。。。」とかなりの衝撃を受けたんですが、これがRuby界隈ではわりと普通のことなのかそれともHerokuの独自仕様なのかを是非とも知りたいです。

□□□□

以下、その内容です。ソース見てると引数は「option[:xxxx]」または「shift_argument」で取得するらしいということはすぐにわかりました。

前者はオプション引数「--xxxx」で指定した内容に相当し、後者はオプションなしの引数に相当します。(「shift_」の名前が示すように実行するとポインタがずれるので2回目の実行では2つ目の引数が取れ最後はnilになります。)

今回の場合はオプションで年、月を指定したかったのでとりあえずこんなコードを書いてみました。

 

  def test
    month = options[:month]
    puts month
  end

 

引数「month」を出力しているだけ。

これで「heroku myapp:test --month 7」と叩いた時に「7」が出力されるかなぁと期待したんですが。。。

残念ながら何も出力されません。どうやらどこかで有効なオプションを登録する必要があるようです。

まぁlogsコマンドの「--tail」みたいに引数を取らないオプションもあるわけだし、それは予想の範疇です。

。。。が!

どこのソースを見てもGREPかけてもどうにもそれらしいところが見つかりません。

また、調べているうちにさらなる疑問もわいてきました。

例えば「--tail」はエイリアスとして「-t」としてもOKですが、この情報もどこにも書かれていない気がするんですよね。。。

確かに各種コマンドのコメントには引数として何が使えるかということが全部書かれて入るんですが。。。

。。。コメント。。。

コメントはコメントですよ。。。

しかし他にそれらしいところが無い。。。

 

  #   -m, --month MONTH  # month
  def test
    month = options[:month]
    puts month
  end

 

heroku myapp:test --month 7

りたーん

7

マジでかーーーー!!!

heroku myapp:test -m 7

りたーん

7

本気かーーーー!!!!

気付くか!?こんなもーーーん!!!(--

□□□□

。。。Rubyな人達はこれ見当つくもんなんでしょうか。。。(--

それともDSLとかそっち系の文化???

いずれにしても結構な衝撃でした。コメントはコメントではないかもしれない。ということをこれからは頭に入れておくべき???(いや、ないだろ。。。(--)

さらにざっと調べたところ「heroku help」コマンドが出力しているヘルプがメソッドのコメントをそのまま出力しているだけということがわかりました。多分その辺りのコードでオプション引数を解析して登録しているんでしょうね。

これで引数つきのSQL実行コマンドもめでたく作成できたわけですが、そこはもはやどうでもいい気がするので割愛します。

今回SELECTしか試してませんが多分INSERTやUPDATEも問題ないでしょう。

ちなみにこれに関するドキュメント(というかプラグイン開発全般)はDevCenterのどこにもない気がします。

2013年7月 2日 (火)

Google Spreadsheetで特定のシートに直リンクする

こんにちは

昨日からGoogle Spreadsheet APIで作成したシートに直リンクするURLを生成したくて色々調べてました。

「API使うならそれくらい簡単にできるんじゃないの?」って思うでしょ?えぇ、僕もそう思いました。

しかし、これが。。。(--

一応最終的にはできたんですが、その方法が「マジですか?!」とかなり愕然とするものだったのでここにメモとして残しておきます。

 

★Google SpreadsheetのURL

実際にシートを作ってみながらブラウザのアドレスバーを確認するとすぐにわかりますが、GoogleSpreadsheetのURLは以下のような形式となっています。

 

https://docs.google.com/spreadsheet/ccc?key=xxxxxxxx#gid=1

 

アカウントが組織に属している場合は若干URLのパスが変わりますが、ここで重要なのは

  • URLパラメータの「key」がスプレッドシートを特定するキーとなっている
  • URLパラメータの「gid」がワークシートを特定するキーとなっている

という点です。ちなみにgidはおそらく単純にシートの作成順による連番です。途中でワークシートの削除や移動があった場合でもgidが振り直されることはなく単純なインクリメントで生成されます。

要するにAPIでこのkeyとgidが取得できれば、URLを組み立てることができるわけです。楽勝です。

 

★Google Spreadsheet APIを使う

今回アプリはPlay2で作成しているのでJavaのAPIを使用しました。Google Spreadsheet APIの使い方については良記事がたくさんあるので割愛しますが、スプレッドシート、ワークシートの情報はそれぞれ、

  • SpreadsheetEntry
  • WorksheetEntry

というクラスから取得できます。

これらのAPIリファレンスを眺めると目的とする情報はそれぞれ

  • SpreadsheetEntry#getSpreadsheetLink
  • WorksheetEntry#getId

というメソッドから取得できそうです。楽勝です。

 

★gidが取れないことに気がつく

さて、ここまで来たら後は試すだけですがまず、SpreadsheetEntry#getSpreadsheetLinkは完全に目的にマッチするものでした。keyだけでなくスキームから始まる完全なURLとして取得できます。楽勝楽勝(^^v

が、WorksheetEntry#getIdの方はgidではなく、こちらも「https://...」で始まるURIでした。そもそもgetIdメソッドはWorksheetEntryクラスのメソッドではなく、その基底クラスであるBaseEntryクラスのメソッドなのでSpreadsheetだけでなく他のGoogle Appsオブジェクトまで全部含めたIdentifierになっているわけです。同一のスプレッドシート内でのみユニークとなるgidとは意味合いが異なります。

それではgidはどうやって取得するのかと言うと。。。これはいろいろと試行錯誤したんですが、どうもそのためのメソッドは無いようでした。(--

最終的にはRESTのレスポンスXMLの中にそれっぽい値が入っていないことから、どうやら本当に無いらしいと結論しました。

 

★シート名でのリンクを試みる

APIでgidが取れないとなると、どうやって直リンクすれば良いのでしょうか?シートの削除や移動があるのでgidは単純な連番とはなりません。世の中にGoogleSpreadsheetの特定シートに直リンクしたい人は山ほどいるはずです。

。。。と、あおってはみたものの実際のところはここまでにさんざん検索をかけているのでシート名でリンクする( = URLパラメータに「sheet=xxxxx」を指定する)方法があるらしいことはわかってはいたんです。

が、これ途中でも試してたんですが何故かうまく動きません。検索結果にも「動かねー」という怨嗟の声が山ほどあるし、公式ドキュメントにもそれができるという記述が見つけられないので結局この方向もあきらめました。。。(--

 

★できないはずがないとあがく

手詰まりです。

絶対に必要と言う機能でもないし、もうあきらめようかとも思ったんですがこんな簡単なことができないということがどうしても信じられず検索を続けました。

そして。。。ついに、見つけた解答がこれです。

http://stackoverflow.com/questions/11290337/how-to-convert-google-spreadsheets-worksheet-string-id-to-integer-index-gid

一番最後にコード例が載っていますが、要約するとこうです。

 

  1. WorksheetEntry#getIdから最後の「/」以降の3桁を取得する
  2. その文字列を36進数として数値に変換する
  3. その数値と31578のXORを取るとgidが取得できる

 

。。。(--

。。。。。(--;;;

。。。できた。。。できたけどっ!

36進数って何だよ?!31578は一体どこから出てきた???

長くこの業界にいるけど、こんなの初めて見たよ!!!

動きはしたけどなんだか全然釈然としない。誰かこのアルゴリズムの根拠の分かる人がいたら教えてください。m(_ _)m

2013年7月 1日 (月)

FLECT OSS Libraryが公開になりました。

こんにちは

なんと、今日から7月です。つまり2013年ももう半分終わってしまいました。。。(--

そして、小西がFLECTに入社してからちょうど1年半たったということでもあります。
はやっ!年々時が経つのが速くなっているようでかないませんな。(--

ちなみにこのブログを書き始めたのは2012年の5月末です。1年1カ月で記事数31件。
さぼっている時期もありますがだいたい月に2回位書いている計算ですね。もうちょっと頑張ります。

 

★FLECT OSS Libraryとは

これです。

http://oss.flect.co.jp/

この1年半で僕が作ったものがあらかた入っている感じですね。内容はかなり雑多な感じです。なんでこういうものを作ろうと思ったかは以前にも書いたので割愛します。

個人的に汎用性の高いモノ、開発者にとって有益なモノを作りたいという志向性が強いのでこういう形での開発はテンションがあがります。(^^;

 

★Salesforce関連

思い起こせば1年半前、Salesforceを外部からAPI連携するのをやりやすくするライブラリを整備してほしいというお題に対して、いきなりSOAPClientから作り始めたのがFLECTでのキャリアの始まりでした。

それをベースにして作成したSalesforce APIのラッパーがSalesforceClientで、これでどれ位のことができるかを示すために作成したアプリが、Salesforce Explorerです。

完全に上司の想像のナナメ上をいっていたと思います。(^^;

Salesforceを使う開発者ならそれなりに便利に使えると思うので興味ある人は触ってみると良いかもしれません。(多分)

 

★Excel関連

excel2canvasはHTML5Canvasの調査をしている時に「絵心無いし、Canvasにテスト描画する適当なものが思いつかねー(--」と困ったあげくなんとなくExcelをそのまま描画してみようと思い立ったのが最初です。凝り性なのでやり始めると最初のお題からまったく関係ないシロモノになっていきましたがそこはそれ。(^^;R&Dとはそういうものです。(キッパリ)

これ、何気にSlideも結構なViewを稼いでいるし少なくとも日本では絶対うける思うんですけどね。どの位Excelを再現できるかはサービス化を目論んで開発したExcelReportで確認できるので、なんか適当な帳票フォーマットをExcelで持っている人はアップロードしてみてください。

 うまくブラウザで描画されないという場合は連絡くれれば可能な限り直します。(多分)

 

★その他

あとはHeroku上で動かすことを前提として作成したアプリをいくつか公開しています。

ちなみに最近作っているアプリは全部Play2で開発しています。社内のHerokuチームが使用している言語はPlay1なんですが、最近はメンテもされてないようなので次期主力言語として使えるかどうかを評価するという目的も兼ねています。

ちなみにPlay2の評価は。。。うーん、どうなんだろう?(--
まだまだベストプラクティスを模索している状態なので、書いていてももっと良い書き方があるんじゃないの?とか、本当にこんなめんどくさいことを毎回書かないといけないのか?とか思うこともしばしばです。

(↑もっとも、Scalaのおかげで圧倒的に楽になっている部分もあるので、このように不満点だけをあげるのは正当な評価ではありません。Play2については近日資料にまとめるつもりです。)

とにかく最近はHerokuが面白くてしょうがないので、Herokuを便利に使うための小物ツールをもうちょっと作っていこうかなと思っています。まだOSS Libraryにはリストされてませんが現在つくっているものもHerokuユーザーにとってはかなり便利です。(多分)

 

会社としても絶賛Herokuエンジニア募集中なので興味ある人は覗いてみてください。

採用情報

株式会社フレクトでは、事業拡大のため、
Salesforce/Force.comのアプリケーション
開発
HerokuやAWSなどのクラウドプラッ
トフォーム上でのWebアプリケーション開発

エンジニア、マネージャーを募集中です。

未経験でも、これからクラウドをやってみた
い方、是非ご応募下さい。

フレクト採用ページへ

会社紹介

株式会社フレクトは、
認定コンサルタント
認定上級デベロッパー
認定デベロッパー
が在籍している、
セールスフォースパートナーです。
heroku partnersにも登録されています。
herokuパートナー
株式会社フレクトのSalesforce/Force.com
導入支援サービス
弊社の認定プロフェッショナルが支援致します。
・Visualforce/Apexによるアプリ開発
・Salesforceと連携するWebアプリ開発
も承っております。
セールスフォースご検討の際は、
お気軽にお問合せください。
Powered by Six Apart