Showing posts with label Ruby/ Ruby on Rails. Show all posts
Showing posts with label Ruby/ Ruby on Rails. Show all posts

20 Sept 2015

1行で複数の変数を設定するのは気をつけよう

`a, b = b, a`と`a = b; b = a;`って違うんですね。

```ruby
> a, b, c = 'a''b''c'
=> ["a""b""c"]

> a = b; b = a;
> [a, b, c]
=> ["b""b""c"]

# リセット
> a, b, c = 'a''b''c'
=> ["a""b""c"]

> a, b = b, a
> [a, b, c]
=> ["b""a""c"]
```

つまり1行の場合はそれ以前の行の変数の状態を保持した状態でそれぞれの変数へ同時に代入が行われる。

1 Jan 2014

has_and_belongs_to_many associationで counter_cacheを有効にする

has_and_belongs_to_many associationで counter_cacheを有効にするサンプル。

以下は Category has_and_belongs_to_many Website な関係が成立しています。HABTMでcounter_cacheを実施するには has_and_belongs_to_manyに:after_add, :after_removeなどのオプションを渡してフックするメソッドをしてあげれば良いです。

そうすることで website.categries = [category_foo, category_bar] としたときに以前のcategoriesとの差分についてcounter_cacheをincrement/decrementしてくれる。

Website自身のフック :after_save, :after_create, :after_destroyは関連を更新したときにはトリガーされないです。

*. #make!はmachinistからデータを作成しています

Rails 4 エラーメッセージを完全に上書きする

メッセージを上書きしたいときはオプションで presence: { message: 'Select at least one category' } の様にメッセージを渡してあげれば良いです。
だけど、それだと主語が先頭に来てしまい"Category Select at least one category"というエラーメッセージになってしまう。

全てのメッセージを上書きしたいときはlambdaを渡してあげればよい。

validates :categories, presence: { message: -> {|location, error| raise [location, error].inspect }  }

# => [:"activerecord.errors.models.website.attributes.categories.blank", {:model=>"Website", :attribute=>"Categories", :value=>#<ActiveRecord::Associations::CollectionProxy []> }]


6 Mar 2013

Railsはどうやってコネクションをプールしているの?


- Rackがコネクションをプールしている
- 一個のスレッドは一個のコネクションしか持てない
http://stackoverflow.com/questions/5131772/how-does-the-rails-connection-pooling-work


- Rails2.2以前
  Rails2.2以前のスレッドとコネクションの関係であればこちらの記事が分かりやすいです。良記事!
  http://fmkt.blog65.fc2.com/blog-entry-138.html

7 Feb 2013

Capistrano関係のリンク

- Wiki home
https://github.com/capistrano/capistrano/wiki

- よく使う変数
https://github.com/capistrano/capistrano/wiki/2.x-Significant-Configuration-Variables

- CapistranoのTask一覧
https://github.com/capistrano/capistrano/wiki/Capistrano-Tasks

- Capistranoの予約変数
http://theadmin.org/articles/capistrano-variables/

24 Jan 2013

RSpecのベストプラクティス

オンライン上のRSpecのベストプラクティスって結構限られていますよね。Specの書き方の基本が分かると”ControllerのexampleでViewやModel出力のバリエイションを担保しない。”といったような一定のノウハウにそってスペックを書きつつコーディングもきれいに整頓していきたくなるところ。

- Better Specs
Specそのものの書き方を学ぶならここ。Githubの議論付きで紹介しています。

- RSpec Rails in Relish
ベストプラクティスと銘打っているわけではありませんがRailsのMVCHのスペックの書き方をここで学ぶことができます。

8 Jan 2013

[Sass] @extendの覚えておくべき動作とplaceholder seloctorの使い道

以前から疑問に思っていたSassのplaceholder selectorの使い道がひとつ見つかりました。それは既存の継承の定義を汚さずに拡張を行うというものでした。といっても例をあげないことにはぱっと伝わらないと思います。以下のような順番でおさらいをしながら話を進めます。

extend => placeholder selector => codeschoolの応用問題



@extendの基本的な使い方


@extendの基本的な使い方はこのようにクラスを拡張して他の要素(この例だとborder-with)を付け足すことだ。
.error {
  border: 1px #f00;
  background-color: #fdd;
}

.seriousError {
  @extend .error;
  border-width: 3px;
}

>>

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.seriousError {
  border-width: 3px; }



出力結果はもともと定義されていたCSS上の.error{} にセレクタである.seriousErrorを追加して同じスタイルを適応している。さらに.seriousError{ border-width: 3px; } を単体で宣言することで拡張という概念を実現している。

では、上記の例のように既に.errorsが拡張されている場合に、.errorsを別のところでも定義したらどうなるだろうか?
.error {
  border: 1px #f00;
  background-color: #fdd;
}
.error.intrusion {
  background-image: url("/image/hacked.png");
}
.seriousError {
  @extend .error;
  border-width: 3px;
}

>>

.error, .seriousError {
  border: 1px #f00;
  background-color: #fdd; }

.error.intrusion, .seriousError.intrusion {
  background-image: url("/image/hacked.png"); }

.seriousError {
  border-width: 3px; }

出力結果には.error.intrusion だけでなく.seriousError.intrusion もできるんですね。


実はこれ本家のリファレンスにある基本的なextendの例なんです。


placeholder selector


Placeholder selectorはそれそのものの定義は何も出力されませんが、それをextendするとextendした先の定義が出力されます

// This ruleset won't be rendered on its own.
#context a%extreme {
  color: blue;
  font-weight: bold;
  font-size: 2em;
}

//However, placeholder selectors can be extended, just like classes and ids. The extended selectors will be generated, but the base placeholder selector will not. For example:

.notice {
  @extend %extreme;
}

>>

#context a.notice {
  color: blue;
  font-weight: bold;
  font-size: 2em; }

僕はこれの使い道がいまいち分かりませんでした。


Codeschool


以下は僕がCodeschoolで遭遇した問題です。


= 問題本文 =
Whoops - we've discovered an alteration to .blueprint later in our stylesheet, and extending .blueprint with .surveyor is creating extra selectors in .factory that aren't needed. Create a placeholder selector called container to hold the shared properties and extend it with .blueprint and .surveyor to remove the extra .factory .surveyor selector.

???なんじゃそりゃ。と初見だと文の意味すらよく理解できなかったです。
でも上記のコンテキストを踏んでいるのでもうお分かりじゃないかと思います。

意訳するとこういうことですね。

最初に .blueprint を定義して .factoryでextendした。
.blueprint {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px;
}
.factory {
  background: #fff;
  .blueprint {
    margin-bottom: 20px;
  }
}


だけど、変更が必要で .surveyor を作って extend した。

.blueprint {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px;
}
.surveyor {
  @extend .blueprint;
  color: #fff;
}

.factory {
  background: #fff;
  .blueprint {
    margin-bottom: 20px;
  }
}

そしたら、出力結果に予期せぬ余分な .factory .surveyor が入ったのでこれを取り除きたい。
.blueprint, .surveyor {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px;
}

.surveyor {
  color: #fff;
}

.factory {
  background: #fff;
}
.factory .blueprint, .factory .surveyor {
  margin-bottom: 20px;
}

Placeholder selectorを作って余分な .factory .surveyorセレクタを削除してください。

どうでしょう、make senseしましたか?すでに定義済みの継承関係.factory{ .blueprint{} }を汚さないように拡張をするのにplaceholder selector使ってくださいと言っています。こういうケースならplaceholder selectorが使えるのかもしれません。


では以下が問題全文です。回答もありますので併せて参考にしてみてください。

Whoops - we've discovered an alteration to .blueprint later in our stylesheet, and extending .blueprint with .surveyor is creating extra selectors in .factory that aren't needed. Create a placeholder selector called container to hold the shared properties and extend it with .blueprint and .surveyor to remove the extra .factory .surveyor selector.

.blueprint {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px;
}
.surveyor {
  @extend .blueprint;
  color: #fff;
}

.factory {
  background: #fff;
  .blueprint {
    margin-bottom: 20px;
  }
}

>>

.blueprint, .surveyor {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px;
}

.surveyor {
  color: #fff;
}

.factory {
  background: #fff;
}
.factory .blueprint, .factory .surveyor {
  margin-bottom: 20px;
}



回答;
%container {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px;
}

.blueprint {
  @extend %container;
}
.surveyor {
  @extend %container;
  color: #fff;
}

.factory {
  background: #fff;
  .blueprint {
    margin-bottom: 20px;
  }
}

>>

.blueprint, .surveyor {
  background: blue;
  border-radius: 5px;
  margin-bottom: 15px;
  padding: 10px; }

.surveyor {
  color: #fff; }

.factory {
  background: #fff; }

 .factory .blueprint {
   margin-bottom: 20px; }


まずは.blueprintに親になる %containerを定義して拡張することで出力結果の .blueprint{} と .factory .blueprint{} を実現します。.surveyor{} には color: #fff; という拡張を入れたいので別途 %containerをextendしています。そうすると、.factory { .blueprint{} } は .blueprint だけに適用されますから余分な .factory .surveyerは出力されません。

7 Jan 2013

CodeSchoolを試してみてる

最近いろいろなタイプのオンラインの学習サイトが乱立していることは皆さんもご存知のことと思います。

お手軽にプログラミングを学習したい人のための厳選5サイト

その中にはあまりにも一般化しすぎているものや、”やりたいことはあるけど使い勝手がいまいち。。”的なものなどあって、試してみるまでなかなかどれが良いか分かりません。そんな中周りの評判が良かったのと、自分で使った感じも良かったのでCodeSchoolを使い始めています。


コードスクールの良さ


コードスクールが良いのは、書きながら覚えていくことにラーニングのアプリケーションが特化しているので知識の吸収効率が良いこと、それから、ながーーいリファレンスから必要な情報を抽出する手間を省いてくれていることなどです。

Webのエンジニアリングの世界って分量的にカバーしておくべきが多いですよね?CodeSchoolは月$50と割高な感じなんですが、全ての技術に分厚い本を買って望む暇は無いけれど体系化した知識を付けてないと業務上の実践では不安というケースには有効です。

コースはこんな感じのがあります。今のところRuby on Rails界隈のスタックが多いけど、徐々に汎用的なコースが増えてきている感じがします。

Git, Sass, CSS, Mobile, HTML5, Coffeescript, jQuery, iOSなんかのコースがあるのもうれしいですね。
- Javascript
- デザイン
- Web tools



始めた理由


- 以前iKnowを毎日やって成果が出たので感覚的にこういう感じのタイプの公文式みたいに繰り返しやって覚えるオンラインラーニングに慣れている
- 毎日2時間の学習時間は取れないけど、30分なら取れる。週に一日2時間よりも、毎日30分x5日の方が頭に定着する
- $50は高いけど本の料金やWeb上のドキュメントとそれにかける時間を考えるとまあ良いかなと思える。仕事への投資と思えば安い。


迷っている人は全てのコースの1個目のチャレンジは無料なのでものの試しにやってみることをお勧めします。ユーザ登録しておくとたまにディスカウントのメールが来るので良いですよ。



以上、また一ヶ月後に使った感想を書くかも!

25 Dec 2012

lightwindowのHTMLを:js => trueなexampleで試験するのはwithin_frameが良いけどissues #365に遭遇した

Integration testを書いていたらlight windowの中にIframeでレンダリングされるHTML pageがあって、testにはCapybaraのwithin_frameが良いことを発見した。within_frameはSeleniumにもWebkitにもある。

ただし、lightwindowに親のURLを変えるようなjavascriptがありこのissue #365に遭遇してしまった。

そもそもAjaxでリクエストした結果をIframeに描写するという実装は複雑すぎるしあんまりテストフレンドリーじゃないからやめたい。ということで結局は実装を変えることにした

12 Sept 2012

Rubyでインスタンスの属性にクラス内からメソッドを追加する

Stackoverflowで`Rubyでインスタンスの属性にメソッドを追加する`方法を聞いたら、ボヘミアの田舎町から解答が付いた

題名が何いってるかわからんかもしれないのでどういうことか説明します。
ちょいちょいActiveRecord::Baseのattributeだけにメソッドを足してこういう風に書きたいことがあった。
html_snippet = HtmlSnippet.find(1)
html_snippet.content = "Link to http://stackoverflow.com"
html_snippet.content.replace_url_to_anchor_tag!
# => "Link to http://stackoverflow.com"

これを実現するのにそのクラス定義内にcontentにreplace_url_to_anchor_tag!を追加するメソッドを定義したかった。

ActiveRecordのクラスはこんなかんじ
# app/models/html_snippet.rb
class HtmlSnippet < ActiveRecord::Base    
  # I expected this bit to do what I want but not
  class << @content
    def replace_url_to_anchor_tag!
      matching = self.match(/(https?:\/\/[\S]+)/)
      "#{matching[0]}"
    end
  end
end

↑あきらかにClass classの@content(常にnil)にメソッドを定義してるため動かない。

1つの解;
頂いた回答によると、インスタンスメソッドの中で変数にメソッドを追加すればいい。ここでいうと`decorate_it`
class HtmlSnippet < ActiveRecord::Base

  # getter is overrided to extend behaviour of freshly loaded values
  def content
    value = read_attribute(:content)
    decorate_it(value) unless value.respond_to?(:replace_url_to_anchor_tag)
    value
  end

  def content=(value)
    dup_value = value.dup
    decorate_it(dup_value)
    write_attribute(:content, dup_value)
  end

  private
  def decorate_it(value)
    class << value
      def replace_url_to_anchor_tag
        # ...
      end
    end
  end
end

なんかやりたいことに対してコーディング量がtoo muchじゃないかなとか思うんだけど、万が一もっと簡潔な方法があったら教えてください。

17 Jun 2012

RSpecのequal, eql, eq, be の違い

RSeqでshould equalと書くべきかeqlと書くべきか、それともbeと書くべきか時々混乱するのでこの際覚えてしまおうと意味で何がちがうんだろうと見てみた。それによるとごく簡単にまとめると以下のような結果だった。

二つの変数を比較するとき;


  • 変数の値だけを比べる
  • eql eq
  • 変数の値だけでなく、インスタンスのobject_idまで比べる
  • equal be
と、ここまで覚えておけばSpec書くのに支障はない。


もう少し掘り下げると、それぞれ以下のような仕組みになっている。

eql

Matcherの場所はここ。実際にはObject#eql?を呼んでいる。

> arr.eql? :a => 1, :b => 2
=> true


equal

Matcherの場所はここ。実際にはObject#equal?を呼んでいる

> arr.equal? :a => 1, :b => 2
=> false


eq

eqの定義はDSLの方にあるらしい。


be

Matcherの定義はここ。beに引数があればBeSameAs#matches?がshouldによって呼ばれる仕組みになっている。




整理して実際に試してみよう。以下のようにString, Array, Fixnumの型のインスタンスについてそれぞれeq, eql, equal, beのマッチャでSpecを実施してみた。

# ./tmp_spec.rb
require 'rspec'

describe 'eq' do
  it('should find two strings are equal') { "".should eq ""}
  it('should find two Arrays are equal') { {:a => 1}.should eq :a => 1 }
  it('should find two Fixnums are equal') { 1.should eq 1 }
end

describe 'eql' do
  it('should find two strings are equal') { "".should eql ""}
  it('should find two Arrays are equal') { {:a => 1}.should eql :a => 1 }
  it('should find two Fixnums are equal') { 1.should eql 1 }
end

describe 'equal' do
  it('should find two Strings are equal') { "".should equal ""}
  it('should find two Arrays are equal') { {:a => 1}.should equal :a => 1 }
  it('should find two Fixnums are equal') { 1.should equal 1 }
end

describe 'be' do
  it('should find two strings are equal') { "".should be ""}
  it('hould find two Arrays are equal') { {:a => 1}.should be :a => 1 }
  it('should find two Fixnums are equal') { 1.should be 1 }
end


結果は以下のとおり。equalとbeでは String, Arrayではobject_idまで同じかチェックしている。
$ rspec tmp_spec.rb -f doc

eq
  should find two strings are equal
  should find two Arrays are equal
  should find two Fixnums are equal

eql
  should find two strings are equal
  should find two Arrays are equal
  should find two Fixnums are equal

equal
  should find two Strings are equal (FAILED - 1)
  should find two Arrays are equal (FAILED - 2)
  should find two Fixnums are equal

be
  should find two strings are equal (FAILED - 3)
  hould find two Arrays are equal (FAILED - 4)
  should find two Fixnums are equal

Failures:

  1) equal should find two Strings are equal
     Failure/Error: it('should find two Strings are equal') { "".should equal ""}
       
       expected # => ""
            got # => ""
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       'actual.should == expected' if you don't care about
       object identity in this example.
     # ./tmp_spec.rb:16:in `block (2 levels) in '

  2) equal should find two Arrays are equal
     Failure/Error: it('should find two Arrays are equal') { {:a => 1}.should equal :a => 1 }
       
       expected # => {:a=>1}
            got # => {:a=>1}
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       'actual.should == expected' if you don't care about
       object identity in this example.
       
       
       Diff:{:a=>1}.==({:a=>1}) returned false even though the diff between {:a=>1} and {:a=>1} is empty. Check the implementation of {:a=>1}.==.
     # ./tmp_spec.rb:17:in `block (2 levels) in '

  3) be should find two strings are equal
     Failure/Error: it('should find two strings are equal') { "".should be ""}
       
       expected # => ""
            got # => ""
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       'actual.should == expected' if you don't care about
       object identity in this example.
     # ./tmp_spec.rb:22:in `block (2 levels) in '

  4) be hould find two Arrays are equal
     Failure/Error: it('hould find two Arrays are equal') { {:a => 1}.should be :a => 1 }
       
       expected # => {:a=>1}
            got # => {:a=>1}
       
       Compared using equal?, which compares object identity,
       but expected and actual are not the same object. Use
       'actual.should == expected' if you don't care about
       object identity in this example.
       
       
       Diff:{:a=>1}.==({:a=>1}) returned false even though the diff between {:a=>1} and {:a=>1} is empty. Check the implementation of {:a=>1}.==.
     # ./tmp_spec.rb:23:in `block (2 levels) in '

Finished in 0.01339 seconds
12 examples, 4 failures

Failed examples:

rspec ./tmp_spec.rb:16 # equal should find two Strings are equal
rspec ./tmp_spec.rb:17 # equal should find two Arrays are equal
rspec ./tmp_spec.rb:22 # be should find two strings are equal
rspec ./tmp_spec.rb:23 # be hould find two Arrays are equal


でもこのFixnumの比較に関しては Specが成功してしまう。
describe 'be' do
  it('should find two Fixnums are equal') { 1.should be 1 }
end

これはFixnumのidがrubyを起動時に実行されて既に予約済みだからのようだ

irb/ pry
[28] pry(main)> 1.object_id
=> 3
[29] pry(main)> 2.object_id
=> 5
[30] pry(main)> 3.object_id
=> 7
[35] pry(main)> 1.object_id
=> 3


[32] pry(main)> 1.0.object_id
=> 105431370

このようにFixnumのインスタンスはシングルトンで定義されているようだ。

15 Jun 2012

ひとりごと on RSpec

ああ かれこれ1時間くらい CapybaraのRSpec上でActioveRecord::Baseなクラスの値がchangeしないパターンにはまってた。

こんな場合;
ユーザのパスワードリセッタを実装するときにone_time_tokenを発行してメールを送信する。メール中のtokenとデータベイスに保存されたtokenが一緒かチェック。同じだったら、パスワードを再設定する画面に進む。他にもセキュリティを守るための処理はあるけど基本的な処理はそんなかんじ。

Specはこんな感じ
let(:user) { User.make } # => machinist/acive_record

 it "user's token should be updated" do
  expect{ click_button 'メール送信' }.to change{ user.one_time_token }
end

expect{ click_button 'メール送信'; user.reload }.to change{ user.one_time_token }
# => Got: one_time_token is still ""


正しくはuser.reloadを追加しないといけない。
it "user's token should be updated" do
  expect{ click_button 'メール送信'; user.reload }.to change{ user.one_time_token }
end

changeの中は遅延評価されたuser を参照しているからRSpecの空間で故意にreloadしないと one_time_tokenがActiveRecord上では変わらない。普通の人はすぐ気づくのかなあ?

10 Jun 2012

Rubyに優しいキーバインディングのセッティング

Linuxで '-'と'_'、':'と';'をスワップしておくとコード書くとき便利です。

# ~/.bashrc

# Key bindings
xmodmap -e 'keycode 47 = colon semicolon'
xmodmap -e 'keycode 20 = underscore minus underscore minus backslash questiondown'

4 Jun 2012

RSpecのshouldは何をしてるの? RSpecの仕組み

RSpecのshouldはどうやって動いているのか?..という仕組みについてpaperboy&co.の方が既にcodeを読んで解説されているスライドを見つけました。

まずshouldが全てのinstaceで実効可能なのはKernel classに対して定義されているからです。

shouldの居場所
# spec/expectations/extensions/kernel.rb
def should(matcher=nil, message=nil, &block)
  Spec::Expectations::PositiveExpectationHandler.handle_matcher(self, matcher, message, &block)
end

PositiveExpectationHandler#handle_matcherの居場所
# spec/expectations/handler.rb
match = matcher.matches?(actual, &block)



RSpecの構造

/lib
└── spec
    ├── expectations
    │   └── extensions
    └── matchers
        └── extensions

expectations/extensionsはその名のとおり拡張を行う。spec/expectations/extensions/にはkernel.rbのみがある

RSpecの構造
spec/matchersには見慣れた名前が。。

ずっとshouldはきっと variable.be_a Stringてかくと variable.is_a? Stringって変えてくれると想像して信じていたけど、実際の条件は逐一Matcherに書いてあるらしい。例えばbe_kind_of matcher
def be_a_kind_of(expected)
  Matcher.new :be_a_kind_of, expected do |_expected_|
    match do |actual|
      actual.kind_of?(_expected_)
    end
  end
end

be Matcherには僕が想像していたような機能がある

§

Matcherを自作したい時は Object.should be_fine => Object.fine?の法則に当てはまるfine? methodを持つObject定義してあげるか、matches?にrespondするMatcherを書いてmatcher.rbみたいに requireしてあげればいいはず。


§


蛇足だけど

上記 kernel.rbのとおり引数にmessageを渡してfailure時に何が失敗したのかわかりやすくすることもできる

別のshould、Subject#shouldの居場所
これは以下の用に書いたときのshouldにちがいない(と信じてる)
let(:int) { 16 }
subject { int }

it "should be even" do
  should be_even
end


Change

例えばこんな感じに書いたときは
expect{ array << 42 }.to change{ array.size }.from(0).to(1)
initializeで @value_proc に{ array << 42 }が代入されてfrom methodで@fromに0が、to methodで@to に1が代入される。比較は他のmatchers同様matches?で @beforeと@afterを比較して行われる。event_procには array.sizeが代入される。
@before = evaluate_value_proc
event_proc.call
@after = evaluate_value_proc
スライドすばらしいので全部読むべし


30 May 2012

最近なんかマイクロブログみたいになってるけど。。
RailsがIf-None-Match headerを公式にサポートしているのを発見。実際に使われているプロジェクトに出会ったことはない。

Rails Guide: Conditional GET support

Ajax requestなんかでresponseが空だった場合は画面に対して何もしない。キャッシュも返さないからサーバ側の負担を軽減する。とかいうのが使いどころなのかな。

If_None_Match headerについての解説記事
If-None-Matchに仕込んであるEtagが更新されテイルかチェックするためにはActionController#stale?を使う

23 May 2012

RSpec evidence with progress bar

Just found that 'rspec' takes multiple options to specify formats like I do in the following snippet.


'-f Fuubar' to show a progress bar.
I do test all specs of thousands in a project I'm currently working on. So, better have a progress bar.

'-f doc' to generate sentences according to specs.
I use methods 'let', 'subject', 'shared_examples_for' make output of 'rspec' self-explanatory.


22 May 2012

TextMateでハイフンとアンダーラインを変更する

Mac初心者の私ですが、会社でMacBook Proを与えられたのでちょっとずつ自分仕様にしていくつもりです。

今日はTextmateでハイフンとアンダーラインを交換する方法です。今日の設定はCoccoaを使っているアプリに有効みたいだけど、TextMate、Emacsあたり意外でどのアプリに有効になるかは今のとこわからないです。

$ vim ~/Library/KeyBindings/DefaultKeyBinding.dict
{
  /* "変更元" = ("命令", "値");  */
  "-" = ("insertText:", "_");
  "$_" = ("insertText:", "-");
  ";" = ("insertText:", ":");
  "$:" = ("insertText:", ";");
}

ちなみに英語ではハイフンはdash、アンダーラインはunderscoreと一般的に呼ばれています。

参考:
http://blog.macromates.com/2005/key-bindings-for-switchers/

http://xahlee.org/emacs/osx_keybinding_key_syntax.html

どういうコマンドがあるかはここを参考にしてください。

27 Apr 2012

Accessing ActionView::Base in a ActionController in Rails 2.3

just came accross an instance variable of an ActionView::Base in ActionController, which is @template;
class AnyController < ApplicationController
  def index
    logger.debug @template.inspect #=> #
  end
end

22 Apr 2012

Note: How to show SQL in Rails Console

Just add the following lines into  config/environment.rb. This switches default logger to STDOUT.

# Render SQL in Rails Console
if "irb" == $0
  require 'logger'
  if ENV.include?('RAILS_ENV')&&
  !Object.const_defined?('RAILS_DEFAULT_LOGGER')
     Object.const_set('RAILS_DEFAULT_LOGGER', Logger.new(STDOUT))
  else
     ActiveRecord::Base.logger = Logger.new(STDOUT)
  end
end

8 Apr 2012

script/consoleでhelper, routing

- 下記に追記
いつのバージョンからか(少なくとも2.3.14からは)名前付きルートはscript/consoleを立ち上げた時点でlink_to はhelperというActionView::Baseのインスタンスからアクセスできて、ダイナミックルートはappというActionController::Integration::Sessionのインスタンスからアクセスできるようになっていました。

http://blog.p.latyp.us/2008/03/calling-helpers-in-rails-console.html


--------------------------------
- コンソールで名前付きルート
Testing Named Routes in the Rails Consoleからまんま拝借。

include ActionController::UrlWriter 
default_url_options[:host] = 'whatever'


default_url_optionsは名前のとおり、/parent_controller/:host/child_controller/:idといった定義に対して以下の用にコンソールで名前付きパスのデフォルトのオプションを指定してくれる。
action_controller_path(:id => 23)
=> "/parent_controller/watever/child_controller/23"
belong_toなんかでリソースがネストしてる時に便利。

rs = ActionController::Routing::Routes
rs.recognize_path action_controller_path(:id => 23), :method => 'GET'
とかで、params => {:host => 'whatever', :id => '23'}とかがパラメータとして渡ってくるはず。試してない。


- Helperをコンソールで
  include HelperYouWantToRun #使いたいhelperをincludeする。
  helper.method_you_want_to_run