each_with_indexの開始を任意の数値から

each with indexは0始まりでインデックスが使える。

1
["a","b"].each_with_index{|elem,i| puts i} #=> 0 1

でも連番降ったりとか1始まりが欲しい場合がある。
そんな場合。

1
["a","b"].each.with_index(1){|elem,i| puts i} #=> 1 2

もちろん数値変えればスタートの値も変わる。


rails console

rails consoleで

1
ActiveRecord::Base.logger = Logger.new(STDOUT)

って書くとSQLが吐かれるようになります。

1
2
User.first
User Load (0.1ms)  SELECT `users`.* FROM `users` WHERE (users.deleted_at IS NULL) LIMIT 1


2012年4月2日追記。

whereつけると戻り値がrelationになるから、to _sqlが使える。
scoped使うとrelation取れる。

1
User.unscoped.to_sql #=> "SELECT `users`.* FROM `users`"

アソシエーション参照時のrailsで発行されるSQLを取得

まぁ、ログ見りゃいいんだけど。デバッグで止めてちょっとずつ条件変えながらSQL見たい時とかデフォルトスコープを確認したいけどモデル見るの面倒な時とか。

環境は引き続き
ruby 1.9.2
rails 3.0.5

まず、ActiveRecordにto _sqlってのがあります。
これ使うとSQL文を確認できる。

ちなみにモデルにはact as paranoid使ってdestroyは全て論理削除状態。
デフォルトのスコープでdeleted _at is nullの条件がつく状態。

1
User.where("created_at > ?",Date.yesterday).to_sql # => "SELECT `users`.* FROM `users` WHERE (users.deleted_at IS NULL) AND (created_at > '2012-03-08')"

whereの後に使えば、とりあえずは使えるみたい。
んでuserクラスにimagesがhas _manyで宣言されている場合。

1
2
user = User.find(1)
user.images.to_sql #=> NoMethodError: undefined method `to_sql'

whereを付ければto _sql使えたのでwhereつける。

1
user.images.where("").to_sql #=> "SELECT `user_images`.* FROM `user_images` WHERE (user_images.deleted_at IS NULL) AND (`user_images`.user_id = 1) ORDER BY position ASC, `sequence` ASC"

とれた。


radio_button_tagとradio_button

なんかよくわからん。

環境は引き続き
ruby 1.9.2
rails 3.0.5

まずはradio button tag

1
2
<%= radio_button_tag :foo,1,true %>
<%= radio_button_tag :foo,0,false  %>

checkedのon offは第3引数にbooleanを渡す。
第3引数はデフォルトでfalse

んで、radio _button

1
2
3
4
<%= f.radio_button :web_nomination_system_disp, 1, :checked => true %>
<%= f.radio_button :web_nomination_system_disp, 1, :checked => nil %>
<%= f.radio_button :web_nomination_system_disp, 1, :checked => "" %>
<%= f.radio_button :web_nomination_system_disp, 1, :checked => false %>

radio _buttonは非チェックはnilと"“とfalseでもいけた。
詳しくはこれ以上調べない!(`・∀・´)

間違っていたので一部修正しました。
すいません



before_filterのメソッドを引数付きで呼びだしたいよね

そんなあなたに。

ruby 1.9.2
rails 3.0.5

で確認しました。

ここを参考にしました。

1
2
3
4
5
6
7
before_filter :display_list, :only => ['top'] do |controller|
  controller.display_list('index')
end

def display_list(list)
 p list #=> 'index'
end

ちなみにこれでも動きました。でもなんかこの書き方怖い。

1
  before_filter "display_list('index')".to_sym

ある特定のオブジェクトにメソッドを追加する

前に書いたオープンクラスでは、クラスを再オープンしてメソッドを追加した場合に。
同じクラスから生成されたオブジェクト全てにメソッドが追加されました。
もう一回やってみましょう。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
class Hoge
  def aaa
    p 'aaa'
  end
end

hoge1 = Hoge.new
hoge2 = Hoge.new


hoge1.methods.grep(/aaa|bbb/) # => [:aaa]
hoge2.methods.grep(/aaa|bbb/) # => [:aaa]

class Hoge
  def bbb
    p 'bbb'
  end
end

hoge1.methods.grep(/aaa|bbb/) # => [:aaa, :bbb]
hoge2.methods.grep(/aaa|bbb/) # => [:aaa, :bbb]

生成されたオブジェクトがメソッドを呼ぶとき。
オブジェクトはクラスにメソッドを探しにいき、クラスに定義したメソッドがあった場合にそれを実行します。
つまりクラスのメソッドに対する変更はそのクラスから生成された全オブジェクトに影響があるということです。

でも実際には特定のオブジェクトにのみ処理を追加したい場合があります。
特異なんとかを使います。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
class Hoge
  def aaa
    p 'aaa'
  end
end

hoge1 = Hoge.new
hoge2 = Hoge.new

hoge1.methods.grep(/aaa|bbb/) # => [:aaa]
hoge2.methods.grep(/aaa|bbb/) # => [:aaa]

def hoge1.bbb
  p "bbb"
end

hoge1.methods.grep(/aaa|bbb/) # => [:bbb,:aaa]
hoge2.methods.grep(/aaa|bbb/) # => [:aaa]

hoge1のみにメソッドbbbが追加されました。
他にinstance _evalも使えます。

1
2
3
  hoge1.instance_eval {  def ccc; p "ccc";end}
  hoge1.methods.grep(/aaa|bbb|ccc/) # => [:bbb, :ccc, :aaa]
  hoge2.methods.grep(/aaa|bbb|ccc/) # => [:aaa]

蛇足ですが。class _eval

1
2
3
  Hoge.class_eval {  def ddd; p "ddd";end}
  hoge1.methods.grep(/aaa|bbb|ccc|ddd/) # => [:bbb, :ccc, :aaa, :ddd]
  hoge2.methods.grep(/aaa|bbb|ccc|ddd/) # => [:aaa, :ddd]

class evalはclassのメソッドなのでHoge.class evalで呼びます。
全オブジェクトに影響しています。

class _eval(classのメソッド)はクラスのコンテキスト内で評価されるので、クラスメソッドとして追加されます。
これはオープンクラスで追加したのと処理と同じような動きです。


instance_evalを引数つけて実行

ruby1.9からです。

1
2
3
4
5
6
7
8
9
10
11
class Foo
  def initialize
    @v = 2
  end
end

foo = Foo.new
foo.instance_exec(2) do |bar|
  p @v * bar
end
# => 4