query: tag:ext

最近は、自分用にRailsの挙動を拡張するために書いた
lib/xxxx_ext.rbが増えてきました。
こういったファイルはconfig/initializer/の直下に
置いても良いのですが、ON/OFFを切り替えやすいので、
config/initializer/libs.rbの中から、require "xxxx_ext"
を呼ぶようにしています。

さて、今回はActiveRecordをさらに便利に使うために、
僕が行っている拡張を紹介します。

lib/active_record_ext.rb

rails>>
module ActiveRecord
class Base
def self.[](arg, *args)
case arg
when Range
find arg.to_a
when Hash
find :all, arg
when :first, :all
find arg, *args
when :last
find(:all, *args).last
when Symbol
send "find_#{arg}", *args
else
find arg, *args
end
end

def update_counters(counters)
  self.class.update_counters id, counters
end

end
end
<<--

どうでしょう、お分かりだと思いますが、ARクラスに
インデクサ (rb_aref) を定義しています。こんな感じに動作します。

pre>>

Site[1].uri
=> "http://www.google.com/"

Site[1,2].map &:uri
=> ["http://www.google.com/", "http://www.wikipedia.org/"]

Site[1..2].map &:uri
=> ["http://www.google.com/", "http://www.wikipedia.org/"]

Site[:last].title
=> "Ruby/Tk チュートリアル"

Site[:by_uri, "http://www.google.com/"].uri
=> "http://www.google.com/"
<<--

実際のアプリケーションコードの中ではあまり使っていないですが、
script/consoleの中で使うのには大変便利です。

最後に、update_countersは、インスタンスメソッドとして
欲しかったので追加しています。
Rails 2.0から仕様が変わった counter_cache については、
日比さんがこちらに記事
既存のモデル/テーブルでcounter_cacheを使う:update_counters
を書いているので参照してみてください。

posted by genki genki on Tue 15 Jan 2008 at 06:20 with 0 comments

RJSテンプレートは、RubyコードからJavaScriptコードを生成
するための仕組みです。
今回は、RJSテンプレートの中でJavaScriptの条件分岐を
簡潔に記述するために、PrototypeHelperを拡張する方法を紹介します。

以下のようなファイルを作成して、config/initializersの下に
設置します(Rails 2.0以降の場合)

prototype_helper_ext.rb

rails>>
module ActionView
module Helpers
module PrototypeHelper
class JavaScriptGenerator
def if(condition, &block)
page << "if(#{condition}){"
block.call if block
page << '}'
end

    def elsif(condition, &block)
      page << "else if(#{condition}){"
      block.call if block
      page << '}'
    end

    def else(&block)
      page << "else{"
      block.call if block
      page << '}'
    end
  end
end

end
end
<<--

これによって、こんな感じに条件分岐を記述できるようになります。

rails>>
render :update do |page|
page.if "$$('#posts .post').length == 0" do
page.remove 'posts'
end
end
<<--

最初から用意されててもいい気がする。

posted by genki genki on Sat 5 Jan 2008 at 16:49 with 0 comments