Amazon EC2でmod_railsを使ってサーバ構築を行う記事をOpenServiceにて記述しました。mod_railsに興味のある方はぜひご覧ください。

元々はCentOSを使おうと思ったのですが、Rubyが1.8.5であったため+色々あったので断念しました。そこでUbuntuを使って構築を行っています。所用時間は待つ時間を入れても20〜30分あれば完了できます。ごく手軽です。

mod_railsを使った場合、HTMLやJavaScript、CSSファイルなどの静的ファイルにはApacheからレスポンスを返してくれます。この点がごく気軽に使えていいですね。レスポンスもそこそこです。

 

Open Service » Blog Archive » Amazon EC2を使ってWebサービスを公開する「インスタンス編」
 http://openservice.jp/2008/04/using_amazon_ec2_2/

MOONGIFTでも紹介したmod_railsと呼ばれるPassenger。Creative Commonsによるオープンソース・ソフトウェアです。

今回はその導入方法を書きたいと思います。インストールは簡単で、gemを使って行えます。

$ sudo gem install passenger
Password:
Bulk updating Gem source index for: http://gems.rubyforge.org
Building native extensions. This could take a while...
Successfully installed passenger-1.0.1
Installing ri documentation for passenger-1.0.1...
Installing RDoc documentation for passenger-1.0.1...

次に、Apacheに組み込むためのコマンドを実行します。詳細は以下にて。

(続きを読む…)

ピクチャ 11.png
xmlcacheプラグインのプロジェクトページ

 

RailsでRSSやAtomを出力する際に利用するAtomFeedHelperがあると思いますが、これは通常のキャッシュが使えません。普通にcacheを使うと、

undefined local variable or method `_erbout' for #<ActionView::Base:0x24dde68>

というエラーが出てしまいます。

そこで利用するのがxmlcacheプラグインです。インストールは、

ruby script/plugin install http://xmlcache.googlecode.com/svn/trunk/xmlcache

と行います。これをインストールした状態で、

cache_xml "cache name" do
 hogehoge
end

とすれば、通常のキャッシュ(フラグメントキャッシュ)同様の処理が可能になります。これでフィード生成が高速化されるようになりますね。ちなみにcaches_pageはアクションごとの設定なので、フォーマットによってキャッシュする、しないといった設定ができない模様…。これはこれで面倒だ。

ピクチャ 8.png
Amazon S3のトップページ。ここから申し込み可能。

Amazon S3はAmazonによるストレージサービスです。1バイト〜5GBまでのオブジェクトを自由に作成し、取り出し、更新、削除することができます。データベースに保存しないような、画像やファイルなどを保存するのに最適なソリューションです。

Amazon S3を使う場合、RubyにはAWS::S3という便利なライブラリがあります。これを使うとごく簡単にAmazon S3を利用することができます。Ruby on Railsでの開発の際にももちろん利用します。

ピクチャ 7.png
AWS::S3のトップページ。使い方も書かれています。

問題はローカル環境で開発している時です。ネットワーク接続が必須なのは非常に面倒ですし、何よりAmazon S3は有料のWeb APIなので、開発しているだけで課金されてしまうのは問題です。

そこで使うのがAmazon S3クローンであるParkPlaceです。このソフトウェアはクローンとは言っても置き換えを目指すのではなく、Amazon S3を利用したソフトウェア開発を便利にするために提供されているソフトウェアになります。ここではこのParkPlaceを使った開発方法を書きたいと思います。

ピクチャ 4.png
ParkPlaceのトップページ

(続きを読む…)

Rails2.0になった際に、ページネーションとAction Web Serviceがそれぞれプラグインで提供されるようになりました。Action Web Serviceは

script/plugin install http://biorails.org/svn/biorails/plugins/action_web_services

にてインストールできます。で、この二つを組み合わせた場合に、なぜかモデル内に定義した関数が使えなくなりました。

NoMethodError (undefined method `authenticate' for #<Class:0x2360a04>):
/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb:1532:in `method_missing_without_paginate'
/vendor/plugins/will_paginate/lib/will_paginate/finder.rb:101:in `method_missing'

このような感じです。なぜかClassに関数がないといってきます。実際に処理を呼び出しているのはUserモデルのUser. authenticateで、

@user=User.authenticate(h[:username], h[:password])

のように呼び出しています。が、メソッドがないと言われます。実際、コンソールでやっても失敗します。
原因は不明なのですが、
vendor/plugins/will_paginate/lib/will_paginate/finder.rb

def method_missing_with_paginate(method, *args, &block)
# did somebody tried to paginate? if not, let them be
unless method.to_s.index('paginate') == 0
return method_missing_without_paginate(method, *args, &block)
end

ここに処理が飛んで、当然paginateを使っていないのでmethod_missing_without_paginateに飛ばされ、

/opt/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/base.rb

def method_missing(method_id, *arguments)

内の

send(method_id, *arguments)
else
super
end

にてsuperが呼び出されてエラーになっているようです。回避策としては、

def authenticate(name, passwd) (処理内容) end

def self.authenticate(name, passwd) (処理内容) end

のようにself.を付けるとエラーが出なくなります。

Rails2.0からページネーションがプラグインベースになりました。普通のページネーションであれば、

@memos = @user.memos.paginate(:page => params[:page], :per_page => 10, :o rder=>”memos.id DESC”)

だけで使えるようになって便利ですが、任意の情報に対してページネーションする方法がいまいち分かっていませんでした。そして、acts_as_searchableを使って、HyperEstraierで全文検索を行う際に、ページネーションをどのように行えば良いのか調べつつ分かったところを書いてみたいと思います。

実際にページネーション処理を行っているのは、

vendor/plugins/will_paginate/lib/will_paginate/finder.rb

になります。ここの

def paginate_by_sql(sql, options)
  WillPaginate::Collection.create(*wp_parse_options!(options)) do |pager|
    query = sanitize_sql(sql)
    options.update :o ffset => pager.offset, :limit => pager.per_page

    original_query = query.dup
    add_limit! query, options
    # perfom the find
    pager.replace find_by_sql(query)

    unless pager.total_entries
      count_query = original_query.sub /bORDERs+BYs+[w`,s]+$/mi, ''
      count_query = "SELECT COUNT(*) FROM (#{count_query}) AS count_table"
      # perform the count query
      pager.total_entries = count_by_sql(count_query)
    end
  end
end

が参考になります。

pager.replaceに、リストを入れて、pager.total_entriesに行数を入れればOKのようです。この処理をまねて、

app/controllers/application.rb

に次のように定義します。

module WillPaginate
  module Finder
    module ClassMethods
      def paginate_by_fulltext_search(query, options)
        WillPaginate::Collection.create(*wp_parse_options!(options)) do |pager|
          pager.replace fulltext_search(query, options)

          count_options = Hash.new
          count_options[:count] = true
          count_options[:attributes] = options[:attributes] if options[:attributes]
          pager.total_entries = fulltext_search(query, count_options)
        end
      end
    end
  end
end

です。そして、呼び出し側では次のようにします。

@memos = Memo.paginate_by_fulltext_search(params[:q], :attributes => “user_id NUMEQ %d” % @user.id, :limit => perpage, :o ffset => offset, :page => params[:page], :per_page => perpage)

ここで、:limitはacts_as_searchable用、:per_pageはwill_paginate用になります。:pageや:offsetは共通で利用できるようです。:attributesはあれば設定します。これさえ設定しておけば、ビュー側は

<%= will_paginate @memos, :prev_label=> _(’« Prev’), :next_label=> _(’Next »’) %>

が利用できて便利です。ちなみにpaginate_by_sqlではoptionsがアップデートされるので、デフォルトの30件になってしまうようですね。これはなぜなんだろう…。

MOONGIFTネットワーク。こちらもぜひご覧ください。
MOONGIFT
Open Service
Rails 2.0
Resident on Net
iPhone最適化
リーンソフトウェア
MarketPedia
Producing Web
Cool Coding