Objective-Cのカテゴリ使って既存クラスの拡張書いてみた
日付に関する処理ならNSDateにメソッドを追加して処理したいと思っていたのですが、
カテゴリという機能を使えばできるという事がわかったので作ってみました。
これを使って、NSStringにbase64エンコード処理するメソッドとかNSDateに5分単位に時間を丸める処理とかを追加すると
いちいち別のメソッドを作らなくても、自分自身で処理することができます。
下記のjson-frameworkとかはカテゴリを使って既存クラスを拡張していたりします。
stig/json-framework · GitHub
例えばこれを
NSDate *date = [NSDate date]; NSDate *roundDate = [DateUtils roundDateTo5Minutes:date];
こう書き換えらます。
NSDate *date = [NSDate date] roundDateTo5Minutes];
ソース
こんな感じで書けばOK
iPhone-GAE/Jで送信されたTimestamp(ミリ秒)のデータをiPhone側でNSDateに変換して表示する(書きかけ)
iPhone側で好きなタイムゾーンで時間表示したらいいじゃん
GAE/J側(Slim3)
- Date型を時間を保存
- JSONでiPhoneへデータを返す
- HashMapとか出力用ObjectとかにModelデータの必要なものを詰め込む
- JSONICで変換すると、Dateフィールド型の値が(1970年からのTimestamp[ミリ秒]=数値)に変換される
- JSONをParseする
- TimestampをNSNumber変数に代入
- [NSDate dateWithTimeIntervalSince1970:[timestamp doubleValue] / 1000.0]でNSDate型に変換
- ミリ秒なので秒にする
- @"yyyy-MM-dd HH:mm:ss"の日付フォーマットで文字列に変換(月2桁表示と時間24H表示なので大文字)
Slim3のUnitテスト
Slim3のプロジェクトについてるbuild.xmlを使ってmodel, service, controllerを生成すれば自動生成できるけど、Utilityクラスなど自分で作ったクラスに対するテストケースを作る場合のためのメモ
Controller
- ControllerTestCaseを継承する
- Datastore, MemcacheAPIが使えるようになる
- tester変数を使ってブラウザテスト的なことができる
import org.slim3.tester.ControllerTestCase; import org.junit.*; import static org.junit.Assert.*; import static org.hamcrest.CoreMatchers.*; public class MyControllerTest extends ControllerTestCase { //[...] }
EC2上でのMySQL Multi-masterフェイルオーバー、DynamicDNS(BIND)に対応させた
d:id:stanaka:20100223 EC2上でMySQL Multi-masterフェイルオーバー - 田中慎司のログ をみて、EC2上でMulti-masterのフェイルオーバーが可能なことを知りましたが、
EC2インスタンスを管理するDNSがDynamicDNSな環境なため、修正しないと使えないなと思ってns_agentを拡張して使えるようにしてみました。
事前準備
基本的な設定は参照元のブログと同じなのでそっちにあわせます。
オリジナルのns_agentはphpで動作するのですが、今回作成したものもphpで動作します。
1. pearをインストールして、Net_DNS2をインストールします。
$ pear list-upgrades $ sudo pear install Net_DNS2
2. mmm_ddns_agentをチェックアウトして、設定ファイルを作成します。
$ cd ~/utils $ git clone git://github.com/roothybrid7/mmm_ddns_agent.git
DNSサーバの設定とレコードの設定を行います。
$ cd mmm_ddns_agent $ cp mmm_ddns_agent.conf.sample mmm_ddns_agent.conf $ vim mmm_ddns_agent.conf
確認
参照元のブログと同様に各デーモンプロセスを起動します。
mmm_ddns_agentの起動は、下記の通りです。
$ php ddns_agent.php
本番運用の際は、DaemonToolsやinit.dスクリプトを使用した方がいいでしょう。
実際にMySQL multi-masterを使った確認は別の人がやったのですが、とりあえず問題なく動いたようです。
RightScaleで生成したEC2インスタンスを動的にCapistranoのRoleにセットする拡張書いた
CapistranoはDeployツールですが、これを使用すると複数のサーバを効率的に管理できます。
通常は設定ファイルに管理するサーバのホスト名またはIPアドレスをroleと呼ばれるものとセットで記述するのですが、
EC2インスタンスは意外とよく落ちるのでその度にホストを書き換えなければなりません。
EC2インスタンスをRightScaleというWebベースの管理ツールを使用して管理しているのですが、
これを使用すると、起動時の初期セットアップを自動化できたりインスタンスをグループ化したり、インスタンスに名前をつけたりすることが可能で管理がずいぶん楽になります。
また、APIも公開されているためこのAPIを使って管理を自動化することも可能です。
題名のCapistranoの拡張書いたのはずいぶん前なのですが、RightScaleを使ってEC2インスタンスを管理している場合
APIを使ってEC2インスタンスの一覧が取得できるのでこれを使用してCapistranoのRoleを動的にセットするような機能をつけました。
ここではその使い方を備忘録として記録しておきたいと思います。
前提
- RightScaleを使用してEC2インスタンスを管理していること
- それらのインスタンスは、RightScaleのDeploymentと呼ばれる単位でグループ化していること
- RightScaleのServerArray(Auto Scaling機能)の使用有無は問わない
- Capistranoをインストールしたホストから管理対象のインスタンスにSSH接続可能になっていること
環境
- CentOS5.4
- Capistrano v2.5.1(capistrano-extとかは必要ならインストール)
- Ruby v1.8.5
インストール
RightScaleのAMIを使用すれば必要なものはだいたいインストールされているので、足りないものをインストールします。
1. 必要なPackageのインストール
ruby-develが必要なのでインストール
$ sudo yum install ruby-devel
rubygemsはyumでインストールするよりも新しいバージョンがあらかじめインストールされているのでそっちを使います。
2. capistranoのインストール
capistrano本体と今回開発した拡張: cap-rightscaleをインストールします。
下記のコマンドで一緒に入ります。
$ sudo gem install cap-rightscale
$ sudo gem install capistrano-ext #必要であればインストール
動作確認
簡単な設定は下記の通りです。
- RightScale認証情報の設定
capistrano実行ユーザのホームディレクトリに''.rsconf''を作成し、下記の形式でファイルを作成します。
ツールで使用するRightScaleのユーザを別途作成した方がいいでしょう。
$ mkdir $HOME/.rsconf $ vim $HOME/.rsconf/rsapiconfig.yml # rsapiconfig.yml username: user@example.com #RightScaleのログインID password: yourpassword #RightScaleのログインパスワード account: 1 #RightScaleのAccountページのURL末尾の番号
- capifyを実行して必要なファイルの生成
$ cd work/cap_test
$ capify .
- deploy.rbの編集
$ vim config/deploy.rb
下記のように書き換えます。
# config/deploy.rb require 'rubygems' require 'cap-rightscale' require 'cap-rightscale/recipes' DEPLOYMENT_ID = xxxxx # RightScale Deployment IDを指定します。(RightScaleの該当のDeploymentページのURLの末尾の番号) SERVER_ARRAY_ID = xxxx # RightScale ServerArray IDを指定します。(RightScaleの該当のServerArrayページのURLの末尾の番号) # set roles nickname :web, :name_prefix => "lb", :deployment => DEPLOYMENT_ID server_array :app, :array_id => SERVER_ARRAY_ID tag :dbm, :tags => "xx_db:role=master", :deployment => DEPLOYMENT_ID tag :dbs, :tags => "xx_db:role=slave", :deployment => DEPLOYMENT_ID, :no_release => true
Roleをセットするメソッドを3種類あるのですが、
- nicknameで指定すると、指定したDevploymentの範囲内で、RightScaleで設定した名前(nickname)が:name_prefixに部分一致するインスタンス
- server_arrayで指定すると、RightScaleで作成した該当のIDを持つServerArrayの現在起動しているインスタンス
- tagで指定すると、指定したDevploymentの範囲内で、RightScaleでインスタンスにつけた指定のtagを持つインスタンス
が設定されます。
設定通りインスタンスがセットされるかどうかは、下記のコマンドで確認できます。
$ cap rs:none
使い方
通常のCapistranoの使い方と同じです。
RightScaleAPIから取得したインスタンスのリストをキャッシュしているのですが、そのキャッシュをクリアするTaskを追加しています。
キャッシュの有効期限はデフォルトでは1日ですが、設定で変更可能です。
キャッシュのクリア
$ cap rs:cache:clear OR $ cap rs:cc
キャッシュを使用しない
$ cap invoke COMMAND='hostname' RS_CACHE=false
設定など
Role定義
- RightScaleのnicknameでRoleをセット
# config/deploy.rb # Deployment ID:12345でグループ化しているインスタンスのうち、RightScaleのnickname: ''lb''に一致するものをRole '':web''にセットする nickname :web, :name_prefix => "lb", :deployment => 12345 #=> 通常のCapistranoの設定だと: role :web, *%w[lb-001 lb-002 lb-003]
- RightScaleのServerArray(Auto scaling)でRoleをセット
#RightScaleのServerArray(Auto scaling) ID:6789で管理しているインスタンスをRole'':app''にセットする server_array :app, :array_id => 6789, :backup => true #=> 通常のCapistranoの設定だと: role(:app, :backup => true) { %w[web-001 web-002 web-003] }
- RightScaleのTagでRoleをセット
#RightScaleのTag: "xx_db:env=prod", "xx_db:role=master"が設定されているインスタンスをRole'':dbm''にセットする tag :dbm, :name_prefix => "db", :tags => ["xx_db:env=prod", "xx_db:role=master"], :deployment => 12345, :primary => true #=> 通常のCapistranoの設定だと: role(:dbm, :primary => true) { %w[db-001 db-002] }^4
キャッシュ設定
下記の設定により、キャッシュの有効期限を変更することが可能です。
- キャッシュ保持時間変更
# config/deploy.rb set :rs_lifetime, 86400 # 1日(default) set :rs_lifetime, 86400 * 7 # 1週間 set :rs_lifetime, 7200 # 2時間 set :rs_lifetime, 0 # 無効 rs_disable :use_rs_cache # 同じく無効 set :rs_lifetime, -1 # 無期限
Roleにセットするホスト情報
デフォルトではAmazonEC2 Local IP address(10.から始まる)を使用します。
rs_enable :use_public_ip # EC2 Public IP addressを使用する場合 rs_enable :use_nickname # RightScaleのnicknameをそのまま使う(DNSやhostsファイルによる名前解決の設定が事前に必要)
ServerArray(Auto scaling機能)で起動する各インスタンスのnicknameの末尾には''[スペース]#番号''が付与されるので、nicknameをDNSホスト名に置き換えるには工夫する必要があります。
nickname: ''web #1'' => DNS hostname: ''web-001''に変換している場合は、Capistranoでは下記のように設定します。
rs_array_number_format "-%03d" # sprintf formatを使って変換後の書式を指定
おわりに
RightscaleAPIを使うとインスタンスの管理を自動化するツールを作成することが可能です。
このほかにも、Nagiosのホスト設定の自動化やPuppetのmanifest適用制御を行ったりと様々のことができます。
このcapistrano拡張で、自分で作成したRubyで書いたRightScaleAPIのWrapperライブラリを使用しているのですが、その頃はRubyとか全くわかっていなかった時期に作ったので
Mixinって何? メタプログラミングすぎて解読できなくてつらい...とかでいろいろ妥協した部分があるため、今度どっかで使用することになったら書き直したいなと思ってます。
参考
- RightScale
- Capistrano
- DNS for ec2 instances
Rails3+jQueryでデータ削除ができない
Rails3でjQueryを使った場合に、下記のリンクをクリックして、データを削除しようとしたら
なぜかPOSTではなく、GETでデータを取得してしまう問題がありました。
<a rel="nofollow" data-method="delete" data-confirm="Are you sure?" href="/foos/2">Destroy</a>
ダイアログも表示されないことからJavascriptが動いてないんでないかと思ってたら
同じような問題がありました。
rails3 + jqueryで DELETEやらPOSTのリンクががが。 | おれせか
上のサイトをみると、どうやら
$ rails g jquery:install
だけでは足りなくて、追加の設定が必要らしいというところまでわかりました。
以下は修正の手順です。
手順
1. githubにあるrails.jsをダウンロードして、`public/javascript`に配置
railsコマンドでjqueryをインストールすると、デフォルトのrails.js(prototype.js由来)は消されてしまうのですが、
jquery用のrails.jsを追加する必要があります。
$ cd public/javascript $ wget https://github.com/rails/jquery-ujs/raw/master/src/rails.js
2. `config/application.rb`に記述を追加
デフォルトでは空なので、jqueryとrailsを追加します。
config.action_view.javascript_expansions[:defaults] = %w(jquery rails)
これで動くはずです。
確認
$ rails g scaffold foo name:string invoke active_record create db/migrate/20110520140721_create_foos.rb create app/models/foo.rb invoke rspec create spec/models/foo_spec.rb route resources :foos invoke scaffold_controller create app/controllers/foos_controller.rb invoke haml create app/views/foos create app/views/foos/index.html.haml create app/views/foos/edit.html.haml create app/views/foos/show.html.haml create app/views/foos/new.html.haml create app/views/foos/_form.html.haml invoke rspec create spec/controllers/foos_controller_spec.rb create spec/views/foos/edit.html.haml_spec.rb create spec/views/foos/index.html.haml_spec.rb create spec/views/foos/new.html.haml_spec.rb create spec/views/foos/show.html.haml_spec.rb invoke helper create spec/helpers/foos_helper_spec.rb create spec/routing/foos_routing_spec.rb invoke rspec create spec/requests/foos_spec.rb invoke helper create app/helpers/foos_helper.rb invoke rspec invoke stylesheets identical public/stylesheets/scaffold.css $ rake db:migrate == CreateFoos: migrating ===================================================== -- create_table(:foos) -> 0.0017s == CreateFoos: migrated (0.0027s) ============================================ $ rails s
MacPortsをやめてHomebrewにしてみた
MacPortsアップデートに時間が(ry
`port list | wc -l`ってやって、8100くらいパッケージが入ってたみたいですが、これほとんどSystemのやつでいいじゃないかと
思ったので、MacPortsでインストールした奴は必要になったときに入れることにします。
事前準備
Java Developer Update
手順
Homebrewのインストール
インストールスクリプトがrubyスクリプトのようなので、事前確認で新規にシェルを立ち上げてsystemのrubyが使えることを確認します。
(rubyをMacportsでインストールしていたので)
$which ruby /usr/bin/ruby
で、インストール
$ ruby -e "$(curl -fsSLk https://gist.github.com/raw/323731/install_homebrew.rb)"
セットアップ
パッケージの管理にgitを使うらしいのでインストールします。
$ brew install git
これで使えるようにはなりましたが、このままだと、`brew update`がこけるので追加の設定を行います。
※追記
どうやら、一度`brew update`を実施してgit repositoryを作らせないといけないようです。
$ brew update
$ cd `brew --prefix` # Homebrewのgit repositoryを追加 $ git remote add origin git://github.com/mxcl/homebrew.git # 最新をダウンロード $ git fetch origin # 作業ツリーをリセットして最新のを反映 $ git reset --hard origin/master
updateできるか確認します。
$ brew update
参考
# Homebrew
https://github.com/mxcl/homebrew/wiki/installation