不格好エンジニア

wordpress.comから引っ越しました。

HerokuにDeploy Hooks を導入してデプロイ通知をHipChatで受け取る

※旧ブログからの転載記事です。

Deploy Hooksを導入する事により、Herokuへのデプロイ通知を受け取る事が可能になります。実際には、メール、BaseCamp、任意のHTTPエンドポイント等、いくつかの通知先を設定できます。

通知手順は、HipChatの公式ドキュメントが最も参考になりました。手順は次の通りです。

まず、ターミナルでアプリケーションのルートディレクトリへ移動します。

ルームIDとauth_tokenを入力します。


heroku addons:add deployhooks:http \
url="https://api.hipchat.com/v1/webhooks/heroku?auth_token=<token>&room_id=<room>"

<token>は.ご自分のAPI auth_tokenで置き換えて下さい。

<room>はメッセージを送信したい部屋のnameもしくはIDで置き換えて下さい。

API

あとは、デプロイしてHipChatのroomを確認してテストを行ってみて下さい。

[参考]

http://help.hipchat.com/knowledgebase/articles/64392-heroku-integration

RubyでTopCoderの問題を解いてみる(幅優先探索)

TopCoder SRM453.5 Div2 Level2を解いてみました。

※旧ブログからの転載記事です。

幅優先探索をはじめて実装しました。長くて見通しがよくない気がする。。。リファクタが必要。

[問題要約]
友人のjimに迷路を解かせたいと思っています。Jimの動き方は、move_row, move_colで指定されています。
障害物は'X'で表し、通行できる場所は'.'で表します。
出口をなるべくスタート地点から遠いところに置いて、出口に到達するまでのステップ数を返せ。
到達できない時は-1を返せ。


# coding: utf-8
# SRM453.5 Div2 Level2
# 幅優先探索
# 迷路を解いたり、最短経路のステップ数を知ることもできるアルゴリズム
# step1:ある出発点から1つ進んだ経路をすべて求める
# step2:これらの経路から1つ進んだ経路をすべて求める
# setp3:上記の作業をゴールに至るまで繰り返す

require 'pp'
class MazeMaker

def longest_path(maze, start_row, start_col, move_row, move_col)
max = 0 # 最大ステップ数
width = maze[0].size # 幅
height = maze.size # 高さ

board = Array.new(height).map{Array.new(width, -1)} # 盤面(すべての経路を初期化)

# スタート地点を選ぶ
#boardのスタート地点には0と書いておく、次の地点には1, その次の地点には2,...と順次増やす
board[start_row][start_col] = 0

# queueを用意する
queue_x = Array.new
queue_y = Array.new

queue_x.push(start_col)
queue_y.push(start_row)

while queue_x.size > 0 do
# 1つの地点を取り出す
x = queue_x.pop
y = queue_y.pop

# 選んだ地点から1つずつ進んだ経路を調べる
for i in 0..(move_row.size-1) do
next_x = x + move_col[i]
next_y = y + move_row[i]

# 以下の条件なら探索を続ける(queueに格納する)
# 盤面上にある場所
# まだ行ったことがない
# 通行可能な場所
#pp "next_x = #{next_x}, next_y = #{next_y}, x=#{x}, y=#{y}" # debug

next unless (0 <= next_x && next_x < width && 0 <= next_y && next_y < height)
next unless board[next_y][next_x] == -1
next unless maze[next_y][next_x] == '.'

board[next_y][next_x] = board[y][x] + 1 #移動先は、現在の地点から1加算した値を書いておく

queue_x.push(next_x)
queue_y.push(next_y)

end

end # end while

# 一通り、盤面を眺めて、まだ行ってない地点があるとしたら、それは到達できない地点だと言う事
for i in 0..(height-1) do
for j in 0 ..(width-1) do
if maze[i][j] == '.' && board[i][j] == -1 #到達していない点があった
return -1
else
max = [max, board[i][j]].max
end
end
end
return max

end
end


#
#== example 0
#
maze = [
['.', '.', '.'],
['.', '.', '.'],
['.', '.', '.']
]
start_row = 0
start_col = 1
move_row = [0,0,-1,1]
move_col = [-1,1,0,0]

ret = MazeMaker.new.longest_path(maze, start_row, start_col, move_row, move_col)
pp "correct!" if ret == 3

#
#== example 2
#
#
maze = [
['X','.','X'],
['.','.','.'],
['X','X','X'],
['X','.','X'],
]

start_row = 0
start_col = 1
move_row = [1,0,-1,0]
move_col = [0,1,0,-1]

ret = MazeMaker.new.longest_path(maze, start_row, start_col, move_row, move_col)
pp "correct!" if ret == -1

Herokuを用いて、ひとりでWeb APIを構築した時にやった事、やるべき事

※旧ブログからの転載記事です。

まえがき
最近、個人でもWebAPIと連携するiPhoneアプリの開発を進めており、サーバサイドではHerokuを利用していました(現在は、さくらVPSに移行しています)。これから、個人開発や小規模チームでの開発を始めようと思っている方に、必要となりそうな情報や、
記事をまとめてみました。

まずHerokuで公開してみる

プロトタイプでも何でも、まずは数時間程度で、サクッと公開できないとモチベーションが上がりません。
環境構築で悩みすぎると、Herokuのメリットも感じられません。
とりあえず、この2つの記事とgoogle先生を駆使して、サンプルアプリをherokuで公開するところまでやってみると、取っつきやすいのではないでしょうか。

HerokuでWebアプリ開発を始めるなら知っておきたい10のこと
紹介されているリンクがすばらしいです。Herokuに少し触れ始めた時に、読んで、非常に為になりました。

Ruby on Rails 4 でアプリを新規作成してherokuで公開するまで
Railsにある程度、触れている方なら、問題なく環境構築できるかと思います。

Getting Started With Heroku
Herokuの公式チュートリアルです。運用上、必要なHerokuの独自コマンドなども記載されています。一通り目を通しておくと良いと思います。
heroku login, heroku open, などなど。。。

個人開発でHerokuを使うメリット
 インフラやミドルウェアの導入にかかる経費(というより時間)が圧倒的に削減できる事がメリットになると思います。
個人的には、ソースから色々コンパイルしてミドルウェアを導入してみたりする事も、勉強にはなると思います。
そういう勉強も必要だとは思います。
 ただ、やってみるとわかりますが、ちょっとした環境構築だけでも、ハマると半日くらい費やしてしまいます。こうなると、個人開発のスピード感は大きく失わます。
 このような背景があり、優秀なインフラエンジニアをひとり雇うような感覚で、Herokuの採用に踏み切りました。また、社内では制約が大きくて触れられないような技術にも、いち早く触れる事ができるため、「その技術で何が出来るのか」考えるきっかけになるように思います。

ソースコードの公開について
 基本的には、サーバサイドのソースコードや、サーバと連携するようなネイティブアプリのソースコードGitHubで公開しないようにしています。
configファイルなど、おいそれと公開できないものもあるためです。
 機密情報のみ、非公開にしてGitHubに公開するような手法も色々とあるようですが、そういった作業に慣れていない為、現在はこのようなスタンスで開発を進めています。

無料で、どこまでの機能を使用できるのか
 基本的には、個人開発で小規模なWebアプリケーションを作成して、ひとつのdynoで動かす分には、ほぼ無料で使用できます(2014年8月現在)。
ただ、スケジューラによるバッチ処理や本番環境でのコマンド実行を行いまくっていると、知らず知らずのうちに課金される事もあるようです。
このあたりは注意が必要です。

学習コスト
Dyno, Slugなどの用語はHeroku独自のものだとおもいますが、それ以外のものは、Heroku独自の用語や技術というものは、あまりないように思います。ですから、別のフレームワークやプラットフォームでお仕事をする際にも、勉強した事は無駄にはならないと思います。

優良アドオン
未使用のものも含まれます。良さげなものをリストアップしてみました。

Deploy Hooks
これは指定したサービスのデプロイ時に通知を行うものです。通知方法はHipChat, IRC, Email, HTTP Postなどが選べるようです。

New Relic
モニタリング、トラブルシュート、チューニングなどに用います。

Logentries
ログをWeb上でグラフィカルにエラー表示をしたり、検索機能を提供してくれるようです。

https://addons.heroku.com/scheduler
事前登録した処理を指定した時間帯に実行させるためのスケジューラです。バッチ処理の実行に用いています。

BitbucketとWerckerを用いた継続的インテグレーション
Bitbucketと連携できて、しかも無料、セットアップが簡単なCIサービスを探していたところ、こちらの記事にたどり着きました。手順もわかりやすく記載されているので、おすすめです。

Githubのプライベートリポジトリでも無料で使えるCI、Werckerを使ってrails newからHerokuのデプロイまでやってみる


今後、やっていきたい事
独自ドメイン
Memcachedの使用
・ステージング環境の構築

RubyでTopCoderの問題を解いてみる(深さ優先探索)

TopCoder SRM425 Div2 Level1を解いてみました。

※旧ブログからの転載記事です。

[問題要約]
東西南北自由に動き回るロボットが指定回数動いたときに、同じ地点に戻ってこない確率を求めよ。

ここでは深さ優先探索を用いてロボットの歩行パターンを列挙し、最後に結果をまとめています。
深さ優先探索を、はじめて実装しました。

class CrazyBot
# class variable
@@grid = Array.new(100).map{Array.new(100, false)}
@@vx = [1,-1,0,0]
@@vy = [0,0,1,-1]
@@prob = Array.new(4).map{0}


#
#= 成功する確率を求める
#
def get_probability(n, east, west, south, north)

@@prob[0] = east / 100.0
@@prob[1] = west / 100.0
@@prob[2] = south / 100.0
@@prob[3] = north / 100.0

pp @@prob

return dfs(50,50,n)

end

#
#= 深さ優先探索
#
def dfs(x, y, n)
return 0 if @@grid[x][y] # 既に通過している
return 1 if n == 0 # 探索しつくした

#pp "dfs x=#{x}, y=#{y}, n=#{n}"

@@grid[x][y] = true # 通過したら印をつける
ret = 0

for i in 0..3 do
ret += dfs(x+@@vx[i], y+@@vy[i], (n-1)) * @@prob[i]
end

@@grid[x][y] = false # 探索が終わって、上に戻ったら印を消す
return ret

end

end

crazy_bot = CrazyBot.new
# example1
pp "correct" if 1.0 == crazy_bot.get_probability(1,25,25,25,25)

# example2
pp "correct" if 0.75 == crazy_bot.get_probability(2,25,25,25,25)

# example3
pp "correct" if 1.0 == crazy_bot.get_probability(7,50,0,0,50)

初心者がiOSアプリと連携する自社サービスを"浅く"チューニングしてみた話

※旧ブログからの転載記事です。

最近、お仕事ではiPhoneアプリとそのAPIRailsで作っておりました。

それなりに多数のアクセスが見込まれるフェーズになってきたため、サーバサイドでの高速化に着手し、その中で得られた知見を社内で共有しました。


cocoa podsとparse sdkを使用した時のUndefined symbols for architecture ...を解消した話

※旧ブログからの転載記事です。

parseのQuickstart tutorialに従って、CocoaPodsを使用した既存のプロジェクトに Parse ios SDKを組み込んでいたところ、Linker errorが多数発生しました。


Undefined symbols for architecture i386:
"_FBTokenInformationExpirationDateKey", referenced from:
-[PFFacebookTokenCachingStrategy cacheTokenInformation:] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
-[PFFacebookTokenCachingStrategy expirationDate] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
-[PFFacebookTokenCachingStrategy setExpirationDate:] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
"_FBTokenInformationTokenKey", referenced from:
-[PFFacebookTokenCachingStrategy accessToken] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
-[PFFacebookTokenCachingStrategy setAccessToken:] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
"_FBTokenInformationUserFBIDKey", referenced from:
-[PFFacebookTokenCachingStrategy facebookId] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
-[PFFacebookTokenCachingStrategy setFacebookId:] in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
"_OBJC_CLASS_$_FBAppCall", referenced from:
objc-class-ref in ParseFacebookUtils(PFFacebookAuthenticationProvider.o)
"_OBJC_CLASS_$_FBRequest", referenced from:
objc-class-ref in ParseFacebookUtils(PFFacebookAuthenticationProvider.o)
"_OBJC_CLASS_$_FBSession", referenced from:
objc-class-ref in ParseFacebookUtils(PFFacebookAuthenticationProvider.o)
"_OBJC_CLASS_$_FBSessionTokenCachingStrategy", referenced from:
_OBJC_CLASS_$_PFFacebookTokenCachingStrategy in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
"_OBJC_METACLASS_$_FBSessionTokenCachingStrategy", referenced from:
_OBJC_METACLASS_$_PFFacebookTokenCachingStrategy in ParseFacebookUtils(PFFacebookTokenCachingStrategy.o)
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

現時点での最善の選択肢は、Facebook SDKをCocoaPodsに追加するか、Objc linker flagを削除するか、どちらかになるそうです。僕は前者を選択してPodfileに下記を追記して、pod installしました。
pod 'Facebook-iOS-SDK'

ありがとう、stackoverflow!

[参考]
How to use cocoa pods and the parse sdk without getting linker errors