Amazon EC2でmod_rails環境を構築するサンプル
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/
ホスティングサービスでもRailsが利用できるようになるかも、な「Passenger」
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に組み込むためのコマンドを実行します。詳細は以下にて。
Atom.builderもキャッシュする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はアクションごとの設定なので、フォーマットによってキャッシュする、しないといった設定ができない模様…。これはこれで面倒だ。
ローカルでAmazon S3を使った開発をParkPlaceを利用して行う
Amazon S3はAmazonによるストレージサービスです。1バイト〜5GBまでのオブジェクトを自由に作成し、取り出し、更新、削除することができます。データベースに保存しないような、画像やファイルなどを保存するのに最適なソリューションです。
Amazon S3を使う場合、RubyにはAWS::S3という便利なライブラリがあります。これを使うとごく簡単にAmazon S3を利用することができます。Ruby on Railsでの開発の際にももちろん利用します。
問題はローカル環境で開発している時です。ネットワーク接続が必須なのは非常に面倒ですし、何よりAmazon S3は有料のWeb APIなので、開発しているだけで課金されてしまうのは問題です。
そこで使うのがAmazon S3クローンであるParkPlaceです。このソフトウェアはクローンとは言っても置き換えを目指すのではなく、Amazon S3を利用したソフトウェア開発を便利にするために提供されているソフトウェアになります。ここではこのParkPlaceを使った開発方法を書きたいと思います。
will_paginateとaction_web_servicesを組み合わせた際のmethod_missingエラーについて
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.を付けるとエラーが出なくなります。
will_paginate + acts_as_searchableで全文検索+ページネーション
Rails2.0からページネーションがプラグインベースになりました。普通のページネーションであれば、
@memos = @user.memos.paginate(:page => params[:page], :per_page => 10,
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
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,
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件になってしまうようですね。これはなぜなんだろう…。



