勉強のため、ゆーすけべーさんの「全裸で学ぶMVC事始め」をruby + Sinatraで書いてみました。
MVCとは何か、どのような処理をするのかについては元エントリで分かりやすく解説されているのでそちらを参照してください。(なぜ全裸なのかも)
つくるもの = zenrize
入力されたテキストを改変して表示する簡単なWebサービスを作成します。 例えば「これから歯磨きをするよ」→「これから全裸で歯磨きをするよ」のようになります。
【全裸で】を差し込む箇所については、全裸botの作者sugyanさんが色々調整を行なっていますが、 今回は単純に「文章内の動詞の前に【全裸で】を必ずつける」とします。
なお、テキスト中の品詞を特定するのにはYahoo!形態素解析APIを使用します。
実装
まずはモデル部分です。(こちらのページを大いに大いに*1参考にさせていただきました)
Zenraクラスを定義し、その中にzenrizeメソッドを定義します
class Zenra
def initialize(position='動詞', text='全裸で')
@appid = 'YOUR_APP_ID'
@position = position
@text = text
@base_url = 'http://jlp.yahooapis.jp/MAService/V1/parse'
end
def zenrize(sentence)
raise "appid is necessary!" if @appid.nil? || @appid.empty?
raise "Japanese sentence is necessary!" if sentence.nil? || sentence.empty?
req = "#{@base_url}?results=ma&appid=#{@appid}&sentence=#{URI.encode(sentence)}"
res = open(req)
xml = REXML::Document.new(res.read)
return sentence if xml.elements['ResultSet/ma_result/total_count'].text == '0'
result = ''
xml.elements.each('ResultSet/ma_result/word_list/word') do |e|
result << @text if e.elements['pos'].text == @position
result << e.elements['surface'].text
end
result
end
end
次にコントローラ部分です。
get, postメソッドに応じたルーティングを設定してリクエストを処理し、ビューを用いてHTMLをレンダリングしています。
get '/' do
erb :index
end
post '/result' do
@model = Zenra.new
erb :result, :locals => {:res => @model.zenrize(params[:text])}
end
最後にビュー部分です。 今回はerbテンプレートを使用しています。
@@ layout
<!DOCTYPE html>
<html>
<head><title>zenrize</title></head>
<body style="width:500px;margin:0 auto;"><h1>zenrize</h1><%= yield %></body>
</html>
@@ index
<form action="/result" method="post">
<textarea rows="3" cols="60" name="text"></textarea>
<br />
<input type='submit' value='zenrize' />
</form>
@@ result
<p><%= h res %></p>
<a href='/'>戻る</a>
以上の3つを繋ぎ合わせたコードは以下のようになります。
# coding: utf-8
require 'rubygems'
require 'sinatra'
require 'open-uri'
require 'rexml/document'
helpers do
include Rack::Utils; alias_method :h, :escape_html
end
class Zenra
def initialize(position='動詞', text='全裸で')
@appid = 'YOUR_APP_ID'
@position = position
@text = text
@base_url = 'http://jlp.yahooapis.jp/MAService/V1/parse'
end
def zenrize(sentence)
raise "appid is necessary!" if @appid.nil? || @appid.empty?
raise "Japanese sentence is necessary!" if sentence.nil? || sentence.empty?
req = "#{@base_url}?results=ma&appid=#{@appid}&sentence=#{URI.encode(sentence)}"
res = open(req)
xml = REXML::Document.new(res.read)
return sentence if xml.elements['ResultSet/ma_result/total_count'].text == '0'
result = ''
xml.elements.each('ResultSet/ma_result/word_list/word') do |e|
result << @text if e.elements['pos'].text == @position
result << e.elements['surface'].text
end
result
end
end
get '/' do
erb :index
end
post '/result' do
@model = Zenra.new
erb :result, :locals => {:res => @model.zenrize(params[:text])}
end
__END__
@@ layout
<!DOCTYPE html>
<html>
<head><title>zenrize</title></head>
<body style="width:500px;margin:0 auto;"><h1>zenrize</h1><%= yield %></body>
</html>
@@ index
<form action="/result" method="post">
<textarea rows="3" cols="60" name="text"></textarea>
<br />
<input type='submit' value='zenrize' />
</form>
@@ result
<p><%= h res %></p>
<a href='/'>戻る</a>
これをzenra.rbとして保存し、
ruby zenra.rb
と実行するとWebブラウザからzenrizeを試すことができます
まとめ的な
"MVCという概念を学ぶにはこうした一連の流れを網羅する小さなサンプルをつくるのが一番取っ付きやすい(元エントリより)"気がします。
Sinatraいいですね。初めて触った(rubyも初心者状態)にも関わらず、すんなり理解出来ました。 全裸寒い。
最後に
上でも述べていますが、ruby初心者+今回がSinatraデビューな未熟者ですので、ここがおかしいとか、こうした方がいい等あればコメント、もしくはTwitterで教えていただけると幸いです。
*1:丸パクリなレベルで。すいません…