2011年2月28日月曜日

UIWebView のスクロールを制御するためのプロパティを書いてみた

UIWebView にどうして scrollEnabled プロパティがついてねえんだ Apple のチンパンジー野郎!とお嘆きの全国1000万の iOS 開発者の皆様、こんばんわ。もちろん私もその一人であります。

嘆いていてもしょうがないので何とかスクロールを制御する方法を・・・と思って探していたら、すでに2009年の地点で @nakamura001 さんがこんなブログを書いてらっしゃいました。

http://d.hatena.ne.jp/nakamura001/20090520/1242837408

が、遷移先で詳解されている

http://praveenmatanam.wordpress.com/2009/04/03/how-to-disable-uiwebview-from-user-scrolling/

のコードが正直いまいちなのです。何がいまいちって、せっかくのCocoa環境であるにも関わらず、わざわざobjc/runtime.hなんていう低レベルなC言語の関数を使っています。別にパフォーマンスがタイトな場所でもないですし、かっこよくCocoaっぽく書き直してみました。ということで書き直したコードがこちら↓

https://gist.github.com/846258

で、このAdditionを導入するとですね、
UIWebView *webView = [[[UIWebView alloc] initWithFrame:frame] autorelease];
webView.webViewScrollEnabled = NO;
みたいな書き方ができてハッピーになれます。

内部的には NSInvocation を使っています。 Mac OS X 10.5 (iOS 2.0) から存在するこのクラス、本当に便利で、ぶっちゃけ呼び出し対象のシグネチャさえわかれば何でも呼び出せるスグレモノです。フレームワークを作るときなど、呼び出し先のシグネチャしかわからない状況下で対象のメソッドを呼び出す時などに便利な感じかもです。その上 NSInvocationOperation を使ってそのまま並列化もできたりして。
NSMethodSignature *sig = [subview methodSignatureForSelector:selector];
NSInvocation* invocation = [NSInvocation invocationWithMethodSignature:sig];
[invocation setTarget:subview];
[invocation setSelector:selector];
[invocation invoke];
BOOL result = YES;
[invocation getReturnValue:&result];
return result;

2011年2月20日日曜日

github で pull request をされたとき・するときの手順

github に自分のリポジトリを公開していると、たまに pull request をされることがあります。また逆に、他人のリポジトリのコードを使っていて、どうしても気になるバグを見つけて修正したときなど、相手に pull request を送りたいことがあります。こんなときにどうすればよいかをまとめてみました。


■pull request をしたいとき

pull request をしたいときは、まず相手のリポジトリを fork する必要があります。


このボタンをぽちっとな。

fork したら、 fork して自分の管理下に入ったリポジトリを clone して、コードを修正します。
git clone https://akisute@github.com/akisute/asi-http-request.git
コードの修正が終わったら、自分の fork したリポジトリに push しておきます。
git push origin master
ではコードの修正が終わったので pull request をします。


このボタンをぽちっとな。


するとこうなります。デフォルトでは相手の master に対して自分の master を pull request することになりますが、もちろんこの画面で変更可能です。 request をする先のリポジトリ・ブランチと、リクエストされるブランチをそれぞれ指定できます。それからコメントをつけて送れます。ここでつけたコメントは相手側のリポジトリの Pull Requests タブに記載されるので、それなりにかっこいい内容を書いておくと良いかと思います。あとは相手が受け入れてくれるのを待つばかりです。自分のコメントにコメントがついたらメールとかで通知が来ますんで、適当に返事して相手と連絡を取りながらやる感じになります。


■pull request をされたとき

逆に自分が pull request をされることもありますので、そのときの対処法も。


pull request されると、こんな風に Inbox の Notifications の中に通知が来ます。


対象のリポジトリの Pull Requests タブにもこんな具合でリクエストが入ります。


クリックしてリクエストの詳細を開きます。ファイルの diff 一覧とかどっからどこに対してリクエストが飛んでいるのよとか全部ここで見られます。相手のコメントに対してコメントを返したり、 diff に対してコメントをつけたりできます。 diff につけたコメントは相手にも公表されます。

ここで相手とコメントやりとりとかして、じゃあ取り込もうか、となりましたら、実際に pull request を取り込む作業を行います。自分のリポジトリにマージ用のブランチを用意して、 pull して確認し、問題なければマージ用のブランチと本線をマージして終了。コマンドがよくわからなくても github が全てのコマンドを表示してくれるのでそれを見れば一発です。本当に親切。以下、 master ブランチに対して pull request があったとすると、
git checkout -b pull-request-master master
git pull http://github.com/applicant/his-repository
# 相手のコミットが自分のブランチに pull されてくるので、この状態で動作を確認する
# merge 作業が発生するならここで行う
# 問題がなさそうなら
git commit
git merge master
git push origin master
push まで完了したら先ほどの pull request のページから取り込み完了したよボタンを押しておきましょう。


■おまけ: 自分が fork しているコードの fork 元リポジトリが更新されたので、こちらも最新にしたい

実はこれは pull request をされたときとあんまり変わりません。対象の相手のブランチを自分の fork しているコードに pull すればよいのです。
git checkout -b merge-master master
git pull http://github.com/parent/parent-repository
# 相手のコミットが自分のブランチに pull されてくるので、この状態で動作を確認する
# merge 作業が発生するならここで行う
# 問題がなさそうなら
git commit
git merge master
git push origin master

2011年2月12日土曜日

Redmine を Debian 5.0 にゼロからインストールしてみた

あらかじめ注意: 下記のメモは、ruby, gem, rails, rack, redmineのいずれかのバージョンが0.0.1でも違うと動作しない可能性が高いので、当てにしないでください。


■顧客が説明した要件
  • 1つのサーバーに複数のプロジェクトのリポジトリとかリソースをおいているので、1プロジェクトにつき1個インスタンスが必要なtracは都合が悪い!
  • っていうかtrac飽きた!!古い!
  • 複数プロジェクト扱えるBTSが欲しい
  • 見た目クールだといいね、カスタマイズとかできるとすごくいい!
  • Wikiは絶対必須
  • Google Appsと連携できると素敵だな!
  • 簡単にインストールしたい、時間かけたくない


■プロジェクトリーダーの理解
  • https://www.gravitydev.com/ はすごくいいんだけれど許可下りなさそうだなぁ。そもそもWikiがないから却下。
  • となるとやっぱりRedmineかな!あれすごくいいよね!
  • Redmineに移行しようかみたいな話も社内で出てたし、先んじて導入してノウハウ作るのはありだな!


■アナリストのデザイン
[11/02/10 9:24:53] akisute: redmineのインストールが超面倒くさいんだけれど
[11/02/10 9:24:54] akisute: なんとかならんのこれ
[11/02/10 9:25:02] wozozo ( ゚Д゚)y─┛~~: rails
[11/02/10 9:25:19] tokibito: rails
[11/02/10 9:25:20] 文 殊堂: まいんちゃん
[11/02/10 9:26:39] akisute: http://redmine.jp/guide/RedmineInstall/
[11/02/10 9:26:43] akisute: これ見てるとアホかと言いたくなってくる
[11/02/10 9:26:50] akisute: Ruby 1.9には対応していません。 上記の表に示したバージョンのRuby 1.8.xをインストールしてください。
RubyGems 1.3.1以上が必要です。
Rake 0.8.3以上が必要です。
Rack 1.0.1が必要です。1.0.1がインストールされていない場合、データベースマイグレーションが失敗します。
[11/02/10 9:27:25] wozozo ( ゚Д゚)y─┛~~: aptでいれたgemをupdateしようとすると、
[11/02/10 9:27:34] wozozo ( ゚Д゚)y─┛~~: おい待てって言われるし
[11/02/10 9:27:49] aodag: Redmineってライトニングなのないの?
[11/02/10 9:27:53] tokibito: rubyはaptで入れたら死亡する可能性
[11/02/10 9:28:04] aodag: rvmっしょ
[11/02/10 9:28:04] tokibito: 自分でビルドしたほうが無難とかいう
[11/02/10 9:28:11] tokibito: rvmで。


■プログラマのコード
  1. redmine:redmine ユーザーを新規に作成する
    • 以下の作業はすべてredmineユーザーで行う
  2. rvmの最新をインストールする
    • http://rvm.beginrescueend.com/rvm/install/
    • curl と git-core のインストールが必要。aptitude経由で実施
    • /home/redmine/.bashrcの追記を忘れないように
    • source ~/.rvm/scripts/rvm も忘れないように
  3. rvmに必要なパッケージをインストールする
    • こんなんデフォルトで用意しろよ・・・いいかげんにしろ・・・
    • rvm package install readline
    • rvm package install iconv
    • rvm package install zlib
    • rvm package install openssl
    • この順番で入れないと依存関係の問題で怒られます (opensslがzlibを使うとか)
  4. ruby 1.8.7 をrvm経由でインストールする
    • 参考は http://d.hatena.ne.jp/masasuz/20100720/1279635055
    • 先に rvm package install しないとgemが使えない, zlibがないので
    • ビルドオプションを付けることでopensslとzlibを有効にすること
    • rvm install 1.8.7 -C --with-openssl-dir=$HOME/.rvm/usr -C --with-zlib-dir=$HOME/.rvm/usr
    • rvm use 1.8.7
    • ruby --version
    • gem --version
  5. gemのバージョンを 1.3.7 に戻す
  6. 本当にopensslとかzlibとかインストールされているかをチェックする
    • ruby -r openssl -e ""
    • エラーになった場合はopensslの再ビルドを行う。opensslを使えるようにしないとのちのちrakeを実行するところでエラーが発生して先に進めなくなる
    • cd ~/.rvm/src/ruby-1.8.7-p330/ext/openssl
    • ruby extconf.rb --with-opt-dir=$HOME/.rvm/usr/
    • make
    • make install
    • ruby -r openssl -e "" を再度実行してエラーにならない事を確認
  7. rails 2.3.5 をgem経由でインストールする
    • gem install rails -v=2.3.5
    • rails 2.3.5をインストールすると自動的にrack 1.0.1が入るが、先にrack 1.0.1をインストールしておいたほうが良いかも
  8. rack 1.0.1 をgem経由でインストールする
    • gem install rack -v=1.0.1
  9. sqlite3-ruby 1.2.3 をgem経由でインストールする
    • 参考は http://d.hatena.ne.jp/modka/20101208
    • sqlite3-devel (sqlite3.h) が見つからないとインストール出来ないので注意
    • 最新のsqlite3-ruby は sqlite3 3.6.3 が必要で、Debianのaptitudeでは3.5.9までしか無いので、バージョンを指定して古いsqlite3-rubyを入れる
    • sudo aptitude install sqlite3
    • sudo aptitude install libsqlite3-dev
    • gem install sqlite3-ruby -v=1.2.3
  10. i18n 0.4.2 をgem経由でインストールする
    • rakeの実行に必要
    • rakeお前依存関係に含めろや・・・アホか・・・><
    • gem install i18n -v=0.4.2
  11. redmine のリリース版の最新をダウンロードする
  12. データベースの設定を行う
    • 参考は http://redmine.jp/guide/RedmineInstall/
    • 今回はsqlite3
    • cd ~/redmine-1.1.1/config
    • cp database.yml.example database.yml
    • vim database.yml
    • cd ~/redmine-1.1.1
    • rake generate_session_store
    • rake db:migrate RAILS_ENV="production"
    • rake redmine:load_default_data RAILS_ENV="production"
  13. メールの送信設定を行う
    • 不要と思われる。メールが飛ばないだけで済む
  14. 起動する
    • cd ~/redmine-1.1.1/
    • ruby script/server webrick -e production
    • http://localhost:3000/ が立ち上がるので、 admin/admin でログインする
    • 適切にadminのパスワードを変更すること
  15. ログの設定を行う
    • やっとかないとログが溜まりまくって死ぬらしいので
    • cd ~/redmine-1.1.1/config
    • cp additional_environment.rb.example additional_environment.rb
    • vim additional_environment.rb
    • http://redmine.jp/guide/RedmineInstall/ のログの設定セクションのとおりに設定しておく
  16. Passengerをインストールする
    • 参考は http://d.hatena.ne.jp/Umeyashiki/20100131/1264948069
    • gem install passenger
    • passenger-install-nginx-module
    • ここまでの手順どおりに進めていると、大体以下のものが足りないはず
      • Curl development headers with SSL support... not found
      • OpenSSL development headers... not found
      • Zlib development headers... not found
    • 一旦abortしてそれぞれインストールすること
      • sudo aptitude install zlib1g-dev
      • sudo aptitude install libssl-dev
      • sudo aptitude install libcurl4-openssl-dev
    • nginxの再ビルド(ないしソースコード)が必要になるので、すでにapt-getしたnginxがある場合には使えない。その場合はpassengerをstandaloneで起動して、そこに対してnginxからproxy-passなりなんなりする。
    • 以下、passengerスタンドアロンで起動し、redmineはすべてpassengerにやらせる場合を考えます。ただしpassengerのスタンドアロンは内部的にはnginxを使っているので、いずれにせよ上記のインストールは必要になります。
    • cd ~/
    • mkdir log run
    • passenger start redmine1.1.1 -d -a 0.0.0.0 -p 3000 -e production --log-file=log/passenger.log --pid-file=run/passenger.pid
    • ってやると何故か/tmp以下にlogファイルをつくろうとしていみわからないエラー吐いて死ぬので中止
    • cd ~/redmine1.1.1
    • passenger start -d -e production
    • 最低限のオプションだけで起動すれば起動できた


■営業の表現、約束
  • お客様、 redmine をお求めですか?ご安心ください! gem install redmine で一発に決まってますよ!簡単です!
    • そんなものはない
  • それなら sudo apt-get install redmine で一発です!猿でもインストールできます!!
    • Debian では無理
  • それなら最初から redmine がインストールされている vm イメージがあります!こちらを使えば一発です!
    • Ubuntu と SUSE しかない
  • Trac Lightning とかゆとり。真のエンジニアは ruby の configure & build から自分でやって当然(キリッ
    • そんな業務と関係ないところに何時間(何万円)使うつもり?
    • アップデートどうすんの?何時間(何万円)使うつもり?


■プロジェクトの書類

http://redmine.jp/guide/


■実装された運用

http://www.redmine.org/projects/redmine


■顧客への請求金額

akisute の実働5時間分 = 数万円 = https://www.gravitydev.com/pricing のスタンダードプラン数年分


■得られたサポート

http://redmine.jp/guide/RedmineInstall/


■顧客が本当に必要だったもの

http://twitter.com/shin_no_suke/status/35632371084562433
http://twitter.com/hirokinko/status/36307730025156608
http://twitter.com/hirokinko/status/36310634127695872


■元ネタ

http://ryonoda.wordpress.com/2008/09/26/


■一応補足

Redmine自体はすごく良いアプリだと思います。ええ。いま使ってますが、とっても助かってます。

bitnamiの配布しているパッケージが対話環境でもインストールできるというのは知りませんでした。っていうかbitnamiのページのどこにも書いてないんですが・・・><
wget http://bitnami.org/files/stacks/redmine/1.1.1-0/bitnami-redmine-1.1.1-0-linux-installer.bin
chmod +x bitnami-redmine-1.1.1-0-linux-installer.bin
./bitnami-redmine-1.1.1-0-linux-installer.bin --mode text
でうまくいくようです。

しかしこの方法を使うと勝手にApache, MySQL, Ruby, Subversionをインストールされてしまうみたいなので、きちんと管理したいとなるとちょっと不向きかなと。