Electronに入門してGitHubログインするところまで

デスクトップアプリ作りたい欲が高まってきたので、Electron に入門した。

Hello

初めてのElectron! HTML5でデスクトップアプリを作成しよう – ICS LAB がわかりやすかった。

$ node -v
v0.12.7

$ npm install electron-prebuilt -g

$ electron -v
v0.30.0

これでひとまず環境は整う。

次は、

http://electron.atom.io/docs/v0.29.0/tutorial/quick-start/

のとおりに、

  • package.json
  • main.js
  • index.html

を作成。

$ electron .

したら動いた。

パッケージ化も、

$ npm install electron-packager -g
$ electron-packager . your-app --platform=darwin --arch=x64 --version=0.30.0 --overwrite
$ open your-app-darwin-x64/your-app.app/

で行けた。
これは確かにお手軽だ…。

GitHubログイン

作りたいものがOAuth認証を利用するアプリなので、GitHubで試して見た。

Electron. oAuth authentication with GitHub がとても参考になった。

ログイン部分のソースはこちら。
https://github.com/tnantoka/GitHubLogin/blob/master/auth.js

ポイントはredirectを監視して、queryにcodeがあったらそれを使ってアクセストークンを取得するところ。

無事に認証できたら、localStorageにtokenを入れてページをreloadするという手抜き実装にしている。

この規模でももう既に破綻の香りがするので、React・Fluxでの実装を勉強しようと思った。

メモ

TODO

  • アプリ閉じたあとdockアイコンクリックで復帰させる方法

Peepholeという怪しげな名前のgemを作った

https://github.com/tnantoka/peephole
Railsのログをそれなりに閲覧できる画面を追加するエンジン。

ちょっと複雑なテキスト処理をしているサービスがあって、「何か起きたらメールで通知しつつ、ユーザーには最低限の結果を返す」ということをやっている。

で、なぜか最近ヘビーなユーザーがいらっしゃるらしく、エラーがわりと来る。
そのたびに、「エラーの再現のためログからデータをサルベージして…」というのが面倒になってきたので、さくっとログを閲覧できるこいつを作った。

受託開発とかで、「お客さんに一応見れせるようにはなったけど、まだ細部は荒いですよ」的なフェーズにも役立つんじゃないかと思っている。
(ステージングサーバーへのアクセス許可を与えなくても、ログだけ開発メンバーに共有できる。どういう操作をされたかはやっぱりログを見るのが一番。)

類似gemはあるんだろうけど、久々にEngine作ってみたかったので、あえて調べてない。
昔作った時はいろいろハマった気がするけど、今回はスムーズに作れた。わりと満足。

oauth2 gemでアクセストークンをリフレッシュする

oauth2 を使った処理でOAuth2::Errorというふんわりしたエラーが発生したから何かと思ったら、アクセストークンの期限が切れてた。

READMEにはrefresh_token関連の記述はなさそうだったけど、メソッドは用意されている模様。
https://github.com/intridea/oauth2/blob/0ab3c213f7baa43f232eb18fa46301e1a9460f7d/lib/oauth2/access_token.rb#L80

こんな感じで更新できた。
(credentialsはomniauthのrequest.env['omniauth.auth'].credentialsを想定。)

  def initialize(credentials)
    self.client = OAuth2::Client.new(
      Settings.example.client_id,
      Settings.example.client_secret,
      site: Settings.example.site,
      ssl: { verify: false }
    )   
    self.access_token = OAuth2::AccessToken.new(
      client,
      credentials.token,
      refresh_token: credentials.refresh_token, # 追加
      expires_at: credentials.expires_at # 有効期限の判定のためこれも必要
    )   
    # トークンの有効期限が切れていたら更新する
    self.access_token = access_token.refresh! if self.access_token.expired?
    access_token
  end 

注意:access_tokenをDBとかに保存している場合は、更新した後のトークンを保存しておくこと。

Railsの中間テーブルの名前をどうするか

UserとTeamの関連をMember(ship)にするとか、適切な名前があればそれがいい。
問題なのは適切な名前がない場合。

昔、それぞれのテーブルの複数形をアルファベット順に繋げるという規約を聞いたことがあった。(teams_usersみたいにする)
ただ、ソースを覚えてなかったので改めて調べた。

日本語は、Railsの基礎知識 - - Railsドキュメント などすぐに見つかった。
これはどこから来てるのか?

公式ガイドのhas_and_belongs_to_manyのところに記述があった。
http://guides.rubyonrails.org/association_basics.html#creating-join-tables-for-has-and-belongs-to-many-associations
http://railsguides.jp/association_basics.html#has-and-belongs-to-many%E9%96%A2%E9%80%A3%E4%BB%98%E3%81%91%E3%81%AB%E5%AF%BE%E5%BF%9C%E3%81%99%E3%82%8B%E7%B5%90%E5%90%88%E3%83%86%E3%83%BC%E3%83%96%E3%83%AB%E3%82%92%E4%BD%9C%E6%88%90%E3%81%99%E3%82%8B

has_and_belongs_to_manyは純粋な結合用のテーブル(モデルを持たない)を使った関連。
:join_tableオプションで指定しなければ、先述のルールのテーブル名が利用される、と。

適切な名前がないようなケースでは、中間テーブルが情報を持つのはおかしいだろうから、そもそもhas_and_belongs_to_manyを使うべきだったのか…。

find_or_create_by!のblockにハマる

createした時だけじゃなく、見つかった時にもblock内を実行して更新してくれると勘違いしてた。

Railsのfind_or_create_byのblockはcreateした際にしか実行されない - Qiita
これと同じ。

tokenが更新されることを期待して、

def find_or_create_with_auth_hash!(auth_hash)
  find_or_create_by!(uid: auth_hash.uid, provider: auth_hash.provider) do |identity|
    identity.token = auth_hash.credentials.token
  end
end

みたいに書いてたんだけど、

Octokit::Unauthorized: GET https://api.github.com/user: 401 - Bad credentials

が出続けてハマった…。