東銀座で 500円 のランチが食べられる、 まぐろナルド に行ってきました。 歌舞伎座から歩いてすぐです。 に確認したところ、ランチメニューは全品800円となっていました。
いただいたのは まぐろチャーシュー丼 です。 みそ汁もついてきます。 これで 500円 でした。
火の通ったまぐろと生卵をのせ、上からマヨネーズを大胆にかけたメニューです。 おいしくいただきました。
続きを読む 東銀座 800円 ランチ まぐろナルド東銀座で 500円 のランチが食べられる、 まぐろナルド に行ってきました。 歌舞伎座から歩いてすぐです。 に確認したところ、ランチメニューは全品800円となっていました。
いただいたのは まぐろチャーシュー丼 です。 みそ汁もついてきます。 これで 500円 でした。
火の通ったまぐろと生卵をのせ、上からマヨネーズを大胆にかけたメニューです。 おいしくいただきました。
続きを読む 東銀座 800円 ランチ まぐろナルドいいアルゴリズムとはどのようなアルゴリズムでしょうか。 アルゴリズムの良し悪しを決める基準のことをアルゴリズムの評価基準といいます。 ここではそのアルゴリズムの評価基準について考えてみましょう。
続きを読む アルゴリズムの評価Bitbucket で Pull Request や コメント、 Issue が追加・作成されたときに Slack に連携するコードを書きました。
Bitbucket で Issue 作成など が行われた際に 外部 に連携する仕組みは Bitbucket で提供されています。 それは 各プロジェクトの設定画面 Webhooks から 設定ができます。
Slack でも 設定画面から 簡単に Bitbucket と連携することができました。 しかし、 そのとき (頃) は Bitbucket の push しか Slack が対応していませんでした。
push よりも Issue 作成や Pull Request や コメント を連携してほしい と思った私は、 Google Apps Script を使って Bitbucket と Slack を繋ぐスクリプトを作ったのでした。
本当なら オブジェクトモデルを作って Factory を作ってとやりたいところだったのですが、 業務が忙しくてそんなことやってられなかったため 間に合わせの品質でコードを作りました。
下記のスクリプトを Google Apps Script で作成し、 メニュー Publish から Deploy as web app をクリックして公開します。 すると ウェブアプリ の URL が表示されるので、 それを Bitbucket の設定画面から Push 先 の URL として登録します。
Bitbucket で何らかの操作が行われるたびに Google Apps Script の処理が実行され、 Slack に 投稿されるようになります。
(コードは Github Bitbucket To Slack Gas にもあります。 Contribute 歓迎です。)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
function createSlackMessage(contents) { var message = {}; if (contents.hasOwnProperty('push')) { // Push message['text'] = 'pushed to ' + contents.repository.name; var info = ''; var l = contents.push.changes.length; for (var i = 0; i < l; ++i) { info += '\n'; if (contents.push.changes[i].old == null) { info += 'created new branch: ' + contents.push.changes[i]['new'].name; } else { // deleted if(contents.push.changes[i]['new']==null) { info += 'deleted branch: '+contents.push.changes[i]['old'].name; }else{ info += 'from ' + contents.push.changes[i]['old'].name + ' to ' + contents.push.changes[i]['new'].name ; } } } message['text'] += info; } else if (contents.hasOwnProperty('fork')) { message['fork'] = 'forked.'; } else if (contents.hasOwnProperty('pullrequest')) { // PullRequest var pr = contents.pullrequest; var to = pr.destination.repository.full_name + '/' + pr.destination.branch.name; var from = pr.source.repository.full_name + '/' + pr.source.branch.name; if (contents.hasOwnProperty('approve')) { // Approve var prLink = '<' + contents.pullrequest.links.html.href + '|' + contents.pullrequest.title + '>'; message['text'] = 'approved the PR.\n' + prLink; } else if (contents.hasOwnProperty('comment')) { // Comment var prLink = '<' + contents.comment.links.html.href + '|' + contents.pullrequest.title + ' comment>'; message['text'] = 'commented on the PR.\n' + contents.comment.content.raw + '\n' + prLink; } else { var prLink = '<' + contents.pullrequest.links.html.href + '|' + contents.pullrequest.title + '>'; if (pr.updated_on == null) { // Create message['text'] = 'created new PR[' + from + '->' + to + '].\n' + prLink; } else { // Update or Merge message['text'] = 'updated PR (' + pr.state + ') [' + from + '->' + to + '].\n' + prLink; } } } else if (contents.hasOwnProperty('issue')) { // Issue var issueLink = '<' + contents.issue.links.html.href + '|#' + contents.issue.id + ' ' + contents.issue.title + '>'; if (contents.hasOwnProperty('comment')) { if (contents.hasOwnProperty('changes')) { message['text'] = 'updated issue: ' + issueLink; } else { // Comment created message['text'] = 'commented on ' + issueLink + '\n' + contents.comment.content.raw + '\n<' + contents.comment.links.html.href + '|More Detail>'; } } else { // Created message['text'] = 'created new issue: ' + issueLink; } } message['username'] = contents.actor.display_name; return message; } function post(payload, url) { var options; options = { method: 'post', payload: payload }; return UrlFetchApp.fetch(url, options); } function doPost(e) { var contents = JSON.parse(e.postData.contents); var slackMessage = createSlackMessage(contents); var url = 'https://hooks.slack.com/services/XXXXXXXXX/XXXXXXXXX/XXXXXXXXXXXXXXXXXXXXXXXX'; post(JSON.stringify(slackMessage), url); } |
まず Bitbucket から通知(Post Request)が来ると、 doPost
が実行されます。 そして Post されたデータから、 Slack への ペイロード データ を作成します。 上では createSlackMessage
がその処理を行っています。
createSlackMessage
では、 届いたデータから 操作内容を割り出し、 通知したい情報をまとめます。
送信したいデータがまとまったら、 Slack に送信します。
createSlackMessage
では、 Issue の場合、 Pull Request の場合などパターン分けしていますが、 上で分けてある以上に 細かくパターンが分かれます。 今回は私の業務上必要だろうと思われる分岐にとどめています。 そのパターンを正確に判断するには Bitbucket から送信されるヘッダの中を確認するのがいいのですが、 Google Apps Script ではリクエストヘッダを確認することができないため ペイロード部分のデータで分岐を行っています。
実際のところ Pull Request の approved のあたりはまだ検証中のため、 正しく判別できているという保証がないです。
もし、 Heroku や AWS 、 その他レンタルサーバ など 自由に使えるサーバがある場合は、 PHP, Ruby 等 で作成したほうが リクエストヘッダも使えて便利だと思います。
東銀座で500円程度のラーメンが食べられる、 喜輪味ラーメン に行ってきました。 一番安いラーメンで 320円 です。
いただいたのは 塩ラーメン 470円 です。
驚きなのはマヨネーズラーメンです。 数少ない、 マヨネーズラーメンを提供しているお店です。
ラーメンだけでなく、カレーもあります。
券売機で券を買って渡すシステムです。
価格帯はだいたいが 500円 程度 です。 セットメニューもありますが、 それでもだいたい 500円 程度 です。
毎日11時から営業しています。
月曜は 350円 以上 なら 大盛無料 です。
Rails の Helper に書いた current_user
を使ったメソッドを RSpec でテストするときのやり方を書きます。