2009年4月30日木曜日

文字の切り詰めメソッド 追記

先日投稿した文字の切り詰めメソッド、先輩社員さんに間違いを指摘されて編集。
すいませんでしたm(_ _)m

新しいソース上げました。

以下にためになったことを書きます。

日本語を分割するときは文字のエンコードを指定してsplit

文字の切り詰めを行うときに、改行コードを変換しながら切り詰めを行うので改行コードが入っていないかを確認しながら処理。
その際、文字コードを指定していないと日本語(2バイト文字)が1バイトずつ分割されるみたい。

なので、

# $KCODE = "NONE"
str = "あああ"
str.split(//)

=> ["\202", "\240", "\202", "\240", "\202", "\240"]

$KCODE = "SJIS"
str = "あああ"
str.split(//)

=> ["あ", "あ", "あ"]

文字コードをSJISに指定してあげると日本語をうまく識別して切り取ってくれます。

破壊的メソッドと破壊的でないメソッド

オブジェクトの内容を変えてしまうメソッドを破壊的メソッドという。
一般的に波形的メソッドはメソッド名の最後に!マークをつける。

str = "あああ\nあああ"
str.gsub(/\n/, "")
str

=> "あああ\nあああ"

str = "あああ\nあああ"
str.gsub!(/\n/, "")
str

=> "ああああああ"

ちなみに

str = "あああ\nあああ"
str.gsub(/\n/, "")

=> "ああああああ"

てっきりstrが置換されたかのように思えるけど戻り値が表示されてるだけなのね。

str = "あああ\nあああ"

のままなので注意。

正規表現は前から順番に

改行コードを\lt;br\gt;タグに変換する処理があります。その時の注意。

str = "一行目\r二行目\n三行目\r\nラスト"
str.gsub(/\r|\n/|\r\n,"<br>")

=> "一行目<br>二行目<br>三行目<br><br>ラスト"

str = "一行目\r二行目\n三行目\r\nラスト"

str.gsub(/\r\n|\r|\n/,"<br>")

=> "一行目<br>二行目<br>三行目<br>ラスト"

gsubの正規表現の条件で, "\r"と"\n"、"\r\n"がかぶっている部分があるので注意。
先に変換してほしい"\r\n"の条件を先に書かないと2重変換される。

問題解決の際には原因特定からやりましょう。

これが一番大事なことだとですね。
ある問題があった時に、原因と思われる個所を"予想して"解決するのは効率が悪い。
明確に原因と思われる個所を"特定して"そこを中心に原因を探る。

急いでいるときには特に"予想して"解決しようとする癖が強い。

急がば回れ。
あせらず急ぐ。

大事な考え方ですね。

2009年4月27日月曜日

文字の切り詰めメソッド

多くの情報が書かれている情報を文字を制限して表示するメソッドの実装。
たとえば1000バイト以上の文字列が格納されてる変数から上1000バイトだけを取り出して、最後に...をつけて返すメソッド。

意外と時間がかかったので記録。


# 文字の切り詰めメソッド
def truncate(str, limit, add='...')

  return "" if str.nil? || str.blank?
  # 制限バイト数から追加する文字列のバイト数マイナスする
  limit -= add.size

  # 制限バイト数まで一文字ずつ文字列を生成
  #(その際、改行コードを(<br />に変換)
  code = $KCODE
  $KCODE = "SJIS"
  result = ""
  str.tosjis.split(/(\r\n)|(\r)|(\n)|/).each do |e|
    e = e.gsub(/\r\n|\r|\n/,",< br />;")
    if (result + e).size <= limit
      result << e
    else
      # 途中で切る場合、追加する文字列を追加して戻り値とする
      result << add
      break
    end
  end
  $KCODE = code
  return result
end

正規表現は初めてやったんだけど、結構面白いね。


追記--
2009.4.30 先輩社員さんに間違いを指摘されて編集。
if分の使い方とか間違ってたし、正規表現も勉強になった。

あと、文字コードの指定によってsplitの切り方が変わってくるところも参考になった。
まだまだ勉強不足ですね。。

2009年4月24日金曜日

ページキャッシュのお話

他社様の勉強会に行ってきた。
先々週の続きでメモリ、ディスクの読み書きの処理速度に対するボトルネックの探し方について。

その中でも主にページキャッシュの話について。

一般に
ディスクへの読み書きは遅い。
メモリへの読み書きは早い。

なので、Linuxは

・何かディスクからデータを読み込んで
・ページキャッシュ上になく、メモリが空いていれば
・いつでも新しいキャッシュを構築する

らしい。

なので、時間がたてばたつほどディスクから読みだされたデータはメモリ上にキャッシュされ、
次回読み込み時に早くロードすることができる。

さらに、ここで注意しなければならないこととして、
メンテナンスでサーバーを再起動させた場合にメモリにキャッシュされていた情報はすべてフラッシュされる。
そうすると、次回はすべての読み出しがメモリからではなくディスクからとなり、ディスクI/Oを発生させる。

よって、一度必要なデータ全体に読み込みをかけてメモリ上にキャッシュを作ってからプロダクション環境に移すのがいいみたい。

2009年4月23日木曜日

食べログAPIの使い方

先日、イケてるRails勉強会で学んだこと。
すでにわかってること、聞いてもよくわからなかったこと、あったけれども、今の自分の知識量でかろうじて理解できて、へぇ!と思ったことの記録。

食べログAPIの情報を検索する部分。

class Restaurant < ActiveResource::Base
 self.site = "http://api.tabelog.com/"

 def self.find_restaurants(restautant_params = {})
  restautant_params[:Key] = "**********" # APIのキーは取得する
  Hash.from_xml(
   self.find(
    :one,
    :from => "/Ver2.1/RestaurantSearch/",
    :params => restautant_params
   ).to_xml
  )
 end
end

以下、ひとつひとつの項目について。

class Restaurant < ActiveResource::Base

ActiveResource とは、簡単にRESTfulなAPIを使えるようにする機能らしい。
簡単に言うと、ActiveRecord を使うのと同じような感覚でWebAPIが使用出来る。


self.site = "http://api.tabelog.com/"

APIのホスト名までを指定。
"http://api.tabelog.com/"という場所とRestaurantモデルをリンクさせてるという認識。


restautant_params[:Key] = "**********" # APIのキーは取得する

APIの登録キーを設定。
APIのサーバーにリクエストを投げるときにリクエストのパラメータとして投げられる。


  self.find(
   :one,
   :from => "/Ver2.1/RestaurantSearch/",
   :params => restautant_params
  ).to_xml

:from のパラメータは、APIのディレクトリを指す。
:params のパラメータは、restrant_paramsのパラメータをリクエストとして投げる。


要は、このようなクラス、メソッドを設定してやった時に、

  Restaurant.find_restaurants()["restaurant"]

を指定すると、APIサーバーに、

  http://http://api.tabelog.com/Ver2.1/RestaurantSearch/?Key=**********

というリクエストを投げて食べログからレストラン情報が返ってくる。
さらに、パラメータを指定して、

  Restaurant.find_restaurants({ :Prefecture => 'tokyo' })["restaurant"]

を指定すると、APIサーバーに、

    http://http://api.tabelog.com/Ver2.1/RestaurantSearch/?Key=**********&restaurant=tokyo

というリクエストを投げて、食べログから”東京の”レストラン情報が返ってくる。

2009年4月22日水曜日

クラスメソッドとインスタンスメソッド

バッチでモデルのコントローラをたたくという処理を行うにあたってクラスメソッドとインスタンスメソッドの違いについて聞いたのでメモ。

インスタンスメソッドとは、特定のインスタンスに対するメソッドで、インスタンスを指定してやらないと実行できない。
一方、クラスメソッドとは、特定のインスタンスを必要とせず、クラスそのものに直結しているメソッド。

クラスとはある概念、たとえば人間というものを表すものなので、人という概念に対する機能がクラスメソッド。
インスタンスとはある実体、たとえばAさんという人を表すものなので特定の人が実行する機能がインスタンスメソッド。

ということか?

Rubyにおいてはクラスメソッドは「self.」をつけるか「self」で囲むかで指定。

たとえばHumanクラスというものがあった時に以下のような使い分け。

class Human

 # クラスメソッド 書き方1
 def self.get_popularity
  # 略
 end

 # クラスメソッド 書き方2
 class << self
  def get_japanese
   # 略
  end
 end

 # インスタンスメソッド
 def go_school
  # 略
 end
end

# クラスメソッドを使ってみる
Human.get_popurarity # クラス.クラスメソッド
Human.get_japanese

# インスタンスメソッド使ってみる
masa = Human.new # まずはインスタンス生成
masa.go_school # 続いてインスタンス.インスタンスメソッド

こんなイメージですかね?
ちなみにnew関数はHumanクラスで実行させてるのにクラスメソッドではないらしい。。

2009年4月14日火曜日

スレッドとプロセス

他社勉強会に行ってきた。
勉強会のスタイルとしては、エンジニアたちが本を読んでいき、読んだ内容について要約してみたり、わからないところをその場でググったり、詳しい人に聞いたり。


学んだこととしてはスレッドとプロセス。

プロセスもスレッドもCPUから見るとおんなじ。
でもそれぞれに違いがあるらしい。

マルチプロセスってのは
・メモリをくう。
・ひとつのプロセスが壊れると他のプロセスに影響がない。

マルチスレッドってのは
・メモリ空間を共有できる。
・一つのスレッドが壊れると他のプロセスも巻き込んで壊れる。

たとえて言うならば、プロセスが島で、スレッドが人。
プロセスは規模が大きい。スレッドは規模が小さい。
島でひとが一人ウイルスに感染すると、島の人たちはウイルスに感染する。
が、島が離れていると、影響はない。



それから、ブラウザ。

google クロムはマルチプロセス。
だから、ひとつのタブがエラーになったところで、他のタブが影響をうけることはない。

一方、firefoxはマルチスレッド。
ひとつのタブが壊れると、firefox自体がシャットダウン。

なるほどねーって思った。

2009年4月13日月曜日

Ajax:リモートプロシージャコール

>> HTTP GETリクエストに対するメソッド
単なるレンダリングなら
link_to_remote

>> HTTP POSTリクエストに対するメソッド
idを渡したりするレンダリングならこちら
form_remote_tag

へぇ。

と、いいつつもGETとPOSTの違いについてそんなによくわかってるわけではない。
HTTPについてちょっと勉強してみる必要あり。

DRYとか。

~DRYの原則~
繰り返しのコードを書いていることに気がついたら、
いったん手をとめて「1つのテンプレートにロジックが入りすぎていないか」と自問してみる。
~~

はいはい。今日も勉強してて新しく知ったこと。

部分テンプレートをレンダリングするメソッドにはコレクションを渡すことができ、
そのメソッドはコレクション内の各項目に対して1回ずつ自動的にテンプレート
を呼び出すことができるらしい。

今まで部分テンプレートを使い、さらにイタレータで繰り返しを作っていたけど、そんな必要ない。

>> add_to_cart.rhtml
<%= render :partial => "cart_item", :collection => @cart.items %>

とすると、_cart_item.rhtml の部分テンプレートが@cart.itemの要素数回レンダリングされる。
さらに、_cart_item.rhtml内では、@cart_itemsのインスタンスがインスタンス名 cart_itemとして使うことができる。
これはCoCの原則ですね。

例:

>> _cart_item.rhtml
<%= cart_item.quantity %>

とすると、@cart_itemsの各インスタンスcart_itemのquantity属性が表示される。

動的scaffoldと静的scaffold

scaffoldには動的scaffoldと静的scaffoldがある。

動的scaffoldはrailsが勝手にviewとか作ってくれる。
しかし、カスタマイズ性は少ない。

一方、静的scaffoldはview構造を作ってくれ、それを自由にカスタマイズできる。

active_scaffoldは動的scaffoldに近い気がする。
カスタマイズ性が高くなると使ってみてもいいのかなと思う。

ただ、rails2系からは動的scaffoldはプラグインを入れないと使えないみたい。

また、静的scaffoldを行う場合も、rails2系からデーブルのカラムを指定しない
といけなくなったっぽいので注意が必要。

備忘録、はじめます。

新卒エンジニアMasaの備忘録、はじめます。
現在以下の内容勉強中&勉強する予定。

とりあえず、半年後には応用情報処理技術者の資格をとりたい。

朝1時間の時間を使って勉強&まとめ
RailsによるアジャイルWebアプリケーション開発

他社さんとの勉強会
サーバ/インフラを支える技術

データベース系連載を暇な時に読む。
techscore

勉強したことをアウトプットしていきます!