OmniDiskSweeperが便利

f:id:y_310:20121102234814p:plain

なんだかディスク容量がやけに少ないように思って内訳を確認したところ「その他」が肥大化していることがわかった。

その他って何だって話で地道にduしたりしてたけど埒が明かないのでちょっと調べてみたらOmniDiskSweeperというツールを見つけた。OmniGraffleなどの高いツールで有名なOmni社の製品だけどこれは無料。

f:id:y_310:20121102235334p:plain

こんな感じでディレクトリごとに容量を表示してくれるのでどこに巨大なデータが眠っているのかすぐわかる。

今回は以前試しにmysqlにインポートしたWikipediaのデータが25GBもあったのが原因だった。もう不要なのでさくっとdropして解決。

edge rails(3.2.0.beta)に上げてみた

戯れに手元のrailsをmasterを見るようにしてみたらサーバが起動しなくなった。

hamlのエラー

#gem 'rails', '3.0.9'
# Bundle edge Rails instead:
gem 'rails', :git => 'git://github.com/rails/rails.git'
$ bundle exec rails s
=> Booting WEBrick
=> Rails 3.2.0.beta application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Exiting
/Users/y_310/work/sample_prj/vendor/bundle/ruby/1.9.1/gems/haml-3.1.2/lib/haml/template/patch.rb:16:in `alias_method': undefined method `delegate_template_exists?' for class `ActionView::Base' (NameError)

エラーをぐぐってみるとどうやらhamlのバグっぽい。
https://github.com/nex3/haml/issues/395
そしてこの問題はここですでに修正済。
https://github.com/nex3/haml/pull/398

ただ普通にgem installして入るバージョンは3.1.0でギリギリこの修正コミットは入っていないみたい。
f:id:y_310:20110818070801p:image
仕方ないのでhamlもedgeを見るようにする。

gem 'haml', :git => 'git://github.com/nex3/haml.git'

rjsのエラー

hamlを最新にして再度サーバを起動しようとするとまたエラーが出た。

=> Booting WEBrick
=> Rails 3.2.0.beta application starting in development on http://0.0.0.0:3000
=> Call with -d to detach
=> Ctrl-C to shutdown server
Exiting
/Users/y_310/work/sample_prj/vendor/bundle/ruby/1.9.1/bundler/gems/rails-3b5eb11664b8/actionpack/lib/action_view/railtie.rb:34:in `block (3 levels) in <class:Railtie>': undefined method `debug_rjs=' for ActionView::Base:Class (NoMethodError)

これもググッてみるとこのページがヒットした。
http://weblog.rubyonrails.org/2011/4/21/jquery-new-default

rails3.1で標準のJSライブラリがprototype.jsからjQueryになった際に、rjsもデフォルトで入らなくなったらしい。
rjsは必要ないので書いてあるとおりにconfig/environments/development.rbから以下の行を削除

# remove next line
config.action_view.debug_rjs = true

これで無事にサーバが起動した。

propertyとretainとautoreleaseと

Objective-Cの@property (retain)なプロパティへのautoreleaseされているオブジェクトの代入ではまったのでメモしておく。

自分のクラスの中ではselfを使わないとプロパティ経由にはならない

@interface MyClass {
  SomeObject *_prop;
}
@property (nonatomic, retain) SomeObject *_prop;
@end
@implementation MyClass
@synthesize _prop;

  - (void) func:(SomeObject *) prop {
    self._prop = prop; //propのretainCountが+1される
    _prop = prop; //propertyのsetterを経由しないで_propにアクセスするためretainされない
  }
@end

autoreleaseされているオブジェクトを継続的に使う場合は自分でretainする必要がある

@interface MyClass2 {
  SomeObject *_prop2;
}
@end

- (void) func2 {
  _prop2 = [[SomeClass getAutoreleaseObj] retain]; //自分のクラス内で使い続けることをretainで明示する
  _prop2 = [SomeClass getAutoreleaseObj]; //この場合イベントループに戻ったときに解放されてしまう
}

retainしないで代入した場合はautorelease poolが解放されるタイミングで解放されてしまう。
感覚的にはfunc2メソッド内でしか使えないと思ったほうがいい。

retainするpropertyにautoreleaseされたオブジェクトを代入する

最後にこの2つを合わせるとどうなるか。

@interface MyClass3 {
  SomeObject *_prop3;
}
@property (nonatomic, retain) SomeObject *_prop3;
@end
@implementation MyClass3
@synthesize _prop3;

  - (void) func3 {
    self._prop3 = [SomeClass getAutoreleaseObj]; //propertyのsetterでretainされる
    _prop3 = [[SomeClass getAutoreleaseObj] retain]; //直接メンバ変数にアクセスするので自分でretainする必要がある
  }
@end

プロパティ経由なら自分でretainを書いてはいけないし、直接メンバ変数に代入する場合はretainする必要がある。
個人的にはクラス内での代入は下のパターン(自分でretainを書く方法)の方が分かりやすいと思っている。
とはいえselfを付けないとsetterを経由しない、ということを知らないと「なんでpropertyでretainしてるのにさらにretainする必要があるの??」と誤解する僕のような人がいるかもしれないのでまとめてみた。

Rails3でjQueryを使う方法

前回の記事の続きでjQueryも使えるようにする。

インストール

Gemfileにjquery-railsを追加

gem 'jquery-rails'

jQueryをインストール。(prototype.js関連のファイルが削除される)

$ bundle install
$ rails g jquery:install
      remove  public/javascripts/controls.js
      remove  public/javascripts/dragdrop.js
      remove  public/javascripts/effects.js
      remove  public/javascripts/prototype.js
      create  public/javascripts/jquery.min.js
      create  public/javascripts/jquery.js
    conflict  public/javascripts/rails.js
   Overwrite  public/javascripts/rails.js? (enter "h" for help) [Ynaqdh] y
       force  public/javascripts/rails.js

プロジェクト作成時にprototype.jsが不要だと分かっている場合は-Jで生成を抑止できる。

$ rails new APP_NAME -J

動作確認

views/samples/index.html.hamlに以下の記述を追加。

  3 %table#fade_table
(snip)
 19 :css
 20   #fade_table {
 21     display: none;
 22   }
 23 :javascript
 24   window.onLoad = (function(){
 25     $('#fade_table').fadeIn('slow');
 26   })();

これでサーバを再起動して/samplesにアクセスするとデータのtableがフェードインしながら表示されます。
内の読み込むjsもprototypeからjQueryに変わっています。

Rails3でRspecを使う方法

Haml、Sassを使えるようになったので今度はRspecを使えるようにします。

インストール

Rails3ではデフォルトでTest::Unit用のディレクトリやファイルが生成されるのですが、これは不要なのでプロジェクト作成時にTest::Unitを使わないようにします。

$ rails new rails3_rspec -T #-TでSkip Test::Unit

次にGemfileに必要なgemを記述します。
※同時にHaml、Sassを使う方法については以前の記事を参照のこと
Rails3とRuby1.9.2でHamlを使う方法
Rails3でSassを使う方法

gem 'haml-rails'

group :development, :test do
  gem 'rspec-rails', '>= 2.0.0.beta.20'
  gem 'autotest'
  gem 'webrat'
end

Gemfileができたらインストール

$ bundle install vendor/bundle
$ rails generate rspec:install

動作確認

動作確認のためにscaffoldで一通りのファイルを生成してテストを実行

$ rails generate scaffold sample
$ rake db:migrate
$ rake db:test:prepare #テスト用DBを作成
$ rake spec
...............**............
(省略)
29 examples, 0 failures, 2 pending

こんな感じでRspecが使えるようになります。
また、autotestを使うとファイルに変更があったときに自動でテストが走るようになります。

$ bundle exec autotest

Rails3でSassを使う方法

せっかくHamlを使えるようにしたのでSassも使えるようにしたいところ。
とはいってもSassはHamlに同梱されているので前回の記事の手順でインストールまでは既に済んでいます。

設定

config/initializers/sass_config.rbを作成して以下の記述を追加。

#デフォルトのスタイルシートパスを削除
Sass::Plugin.remove_template_location("./public/stylesheets/sass")
#app/stylesheetsをSass用のディレクトリに設定
Sass::Plugin.add_template_location("./app/stylesheets")
#最小サイズのCSSに変換する
Sass::Plugin.options[:style] = :compressed

デフォルトのパスでも問題ないのですが、Sassは.sassファイルから.cssファイルへコンパイルする仕組みのためソースファイルと生成されたCSSの場所を分離しておいたほうがスッキリすると思います。
またSassの変換結果のスタイルは以下のドキュメントに書かれていますので好きなものを設定してください。
http://sass-lang.com/docs/yardoc/file.SASS_REFERENCE.html#output_style

動作確認

Sass用のディレクトリとファイルを作成

$ mkdir app/stylesheets
$ vim app/stylesheets/sample.sass

以下の記述をsample.sassに追加

h1
  :font
    :size 200%
    :weight bold
  :border 16px solid #DD66CC
  :width 400px
  :padding 5px 
p
  :font-weight bold
  :border 16px solid #6666DD
  :width 400px
  :padding 5px 
$ rails server
$ open http://localhost:3000/sample/index

こんな画面が表示されたら動作確認OK。public/stylesheets/sample.cssが生成されているはず。
f:id:y_310:20100906005347p:image

Rails3とRuby1.9.2でHamlを使う方法

会社でRails3とHamlを使っているんですが、既に他の方が環境を作った上でコードを書いていたので、勉強のために一から環境構築をやってみました。

Rails環境構築

$ rvm 1.9.2
$ gem install rails
$ rails new rails3_haml
$ cd rails3_haml
$ bundle install vendor/bundle #必要なgemをvender/bundleに一括インストール
$ rails server

これでブラウザからhttp://localhost:3000にアクセスして動作していればひとまず最低限のRailsの環境構築はOK.

Hamlインストール

Gemfileにhaml-rails*1を追加。

gem 'haml-rails'

haml-railsはRails3にHaml Generatorを追加するためのプラグインです。
元々はrails3-generatorsだったものがHaml部分だけ分離したものらしいです。

もう一度bundle install

$ bundle install

これで準備は完了。
config/application.rbにg.template_engine :hamlのような記述を追加する必要はありません。

あとは試しにcontrollerをgenerateして動作確認してみましょう。

$ rails g controller sample index
      create  app/controllers/sample_controller.rb
       route  get "sample/index"
      invoke  haml     #template_engineがhamlに変わっている
       exist    app/views/sample
      create    app/views/sample/index.html.haml
      invoke  test_unit
      create    test/functional/sample_controller_test.rb
      invoke  helper
   identical    app/helpers/sample_helper.rb
      invoke    test_unit
   identical      test/unit/helpers/sample_helper_test.rb
$ rails server

これでhttp://localhost:3000/sample/indexにアクセスしてこんな画面が表示されればhamlが動作しています。
f:id:y_310:20100831005131p:image

*1:haml-railsを入れずにgem 'haml'だけでもHamlを使うことはできますが、rails gでファイルをgenerateする際にerbファイルが生成されてしまいます。これを手動で書き換えるか自分でファイルを作成する場合はhaml-railsは必要ありません。