2011年1月29日土曜日

CoffeeScriptをWindowsで使う

■概要

CoffeeScript面白いのですが、*nix系でしか利用できない。と思ってましたが、*.coffee -> *.jsのコンパイルだけならWindowsでも可能な方法を発見したのでご報告します!

■方法

http://jashkenas.github.com/coffee-script/ からcoffee-scriptをダウンロード。
・解凍して、extras/coffee-script.jsを取り出す。
・coffee-script.jsと同じフォルダに、下記の様な感じでcoffee-scriptコンパイラを利用するスクリプトを作成する
  ※色々処理はしょってるので要注意!

// compiler.js
var fs = WScript.CreateObject("Scripting.FileSystemObject"); 

//coffeescriptを読み込んで評価
var path = WScript.ScriptFullName.replace(WScript.ScriptName,"");
eval(fs.OpenTextFile(path + "coffee-script.js", 1).ReadAll()); 

//
// ここからメインです。
//
var args = WScript.Arguments;
if (args.length == 0) {
  WScript.Echo("error: please Drag And Drop *.coffee file!");
} else {
  for (var i = 0; i < args.length; i++) {
    var src      = fs.OpenTextFile(args.Item(i), 1).ReadAll();
    var compiled = CoffeeScript.compile(src);
    var file     = args.Item(i).replace(".coffee", ".js");
    fs.OpenTextFile(file, 2, true).Write(compiled);
  }
}

・*.coffeeなファイルをドラッグ & ドロップすると、*.coffeeと同じフォルダに*.jsが出来上がります!

■参考

・JScriptでimport スマートにできないかなぁ http://d.hatena.ne.jp/TakamiChie/20080403/1207227691

■2011/01/29 12:45

書き込み時に新規作成フラグtrueがついていませんでしたので修正しました。

2011年1月26日水曜日

rails3とbackbone.jsの組み合わせで利用する2

■概要

前回に引き続き、backbone.jsを利用してjqueryでMVCの世界を、rails3と共に作っていこうと思います。
今回はデータのやり取りをする所までが目標です。

■モデル/コントローラ等を作成する

$ rails g scaffold post title:string body:text published:boolean
$ rake db:migrate
$ rake spec (とりあえずrspecが動くか確認しとく)
$ rake spec:rcov (ついでにrcovが動くか確認しとく)
$ rails s

ここで http://localhost:3000/posts でいつもの画面が表示されてればOK!

■json入出力用にコントローラを修正する

とりあえずjsonでやり取りできるように変更します。params.exceptはbackboneとのやり取りを考慮してます。

class PostsController < ApplicationController
  respond_to :json
  def index
    @posts = Post.all
    respond_with @posts
  end
  def show
    @post = Post.find(params[:id])
    respond_with @post
  end
  def create
    @post = Post.new(params.except(:action, :controller))
    respond_to do |format|
      if @post.save
        format.json { render :json => @post, :status => :created, :location => @post }
      else
        format.json { render :json => @post.errors, :status => :unprocessable_entity }
      end
    end
  end
  def update
    @post = Post.find(params[:id])
    respond_to do |format|
      if @post.update_attributes(params.except(:id, :action, :controller, :created_at, :updated_at))
        format.json { head :ok }
      else
        format.json { render :json => @post.errors, :status => :unprocessable_entity }
      end
    end
  end
  def destroy
    @post = Post.find(params[:id])
    @post.destroy
    respond_to do |format|
      format.json { head :ok }
    end
  end
end

■jsonのフォーマットを変更する

このままだと下記の用に"post"が付いてしまうので、backbone側の期待と異なります。

http://localhost:3000/posts.json
=> [{"post":{"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}}]

http://localhost:3000/posts/1.json
=> {"post":{"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}}


config/initializers/include_root_in_json.rbの様なファイルを作成し

ActiveRecord::Base.include_root_in_json = false

とすると下記の様な感じでgoodです!

http://localhost:3000/posts.json
=> [{"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}]

http://localhost:3000/posts/1.json
=> {"body":"a","created_at":"2011-01-19T16:13:47Z","id":1,"published":false,"title":"aa","updated_at":"2011-01-19T16:13:47Z"}

■backbone用のcontorollerを作成

コントローラ/ビューを追加して必要な設定を追加します。

$ vim controllers/home_controller.rb

class HomeController < ApplicationController
  def index
  end
end

$ vim config/routes.rb
  root => "home#index"
$ rm public/index.html
$ mkdir views/home

■backbone.jsを使ってみる

$ vim views/home/index.html.erb



http://localhost:3000/ を開いて、画面に味気ないalertが表示されればOkay!!
railsのログとDB見てると少しは楽しいかも

次は画面を作っていきましょう!

2011年1月24日月曜日

railsにおけるデータファイルの出力三段階

画面で選択した検索条件に基づき、データをファイル出力したいという要件は、非常に多いですが、基本に忠実な実装しないとメモリー不足等で大変な事になります。メモリーの利用方法と、応答速度を意識して、改善していきます。

  • メモリー展開+ファイル作成

@posts = Post.all

open(file_name, "wb") do |f|
  @posts.each do |post|
    f.write(post.to_csv + "\r\n")
  end
end

send_file(file_name)

長所
  簡単

短所
  @postsが大量データだった場合に、メモリー不足に陥ります。
  ファイルが出来上がるまで応答を返せない。

  • フェッチループ+ファイル作成

open(file_name, "wb") do |f|
  Post.connection.raw_connection.query("select * from posts", :cache_rows => false).each do |row|
    f.write("#{row[0]},#{row[1]}\r\n")
  end
end

send_file(file_name)

長所
  同時に必要なメモリーが削減する事ができる。

短所
  生SQLを書く必要があり、少しとはいえDB依存のコード(raw connection)を書く必要あり。
  ファイルが出来上がるまで応答を返せない。

  なおrailsにはbatch方式でのquery発行もありますが、複数回SQLを実行してしまうのでスピード面で問題が出る事が多いです。
  • フェッチループ+ネットワーク転送

headers.merge!(
  "Content-Type"              => "application/octet-stream",
  'Content-Disposition'       => "attachment; filename=\"test.csv\"",
  'Content-Transfer-Encoding' => 'binary'
)

self.response_body = proc { |r, o|
  Post.connection.raw_connection.query("select * from posts", :cache_rows => false).each do |row|
    o.write("#{row[0]},#{row[1]}\r\n")
  end
}

長所
  同時に必要なメモリーが削減する事ができる。
  途中で応答が返せる(ネットワーク例外を途中で捕捉できるので尚良しです)。

短所
  生SQLを書く必要があり、少しとはいえDB依存のコード(raw connection)を書く必要あり。

※webrickでは応答は最後になってしまうので注意
※rails3になってまた変わったみたい。 http://stackoverflow.com/questions/3507594/ruby-on-rails-3-streaming-data-through-rails-to-client

  • 結論

要件に応じてメモリー展開+ネットワーク転送(簡単)、もしくは、フェッチループ+ネットワーク転送(無敵)が良いと思う。

2011/01/25 追記


よく考えたらrails3になってArelが導入されたおかげで、sqlは構築するのが楽になりましたね。。

Post.where("created_at < ?", Time.now).to_sql

2011年1月23日日曜日

BloggerでSyntaxHighlighterを利用する

ブログ上でプログラムの断片を表示する場合、シンタックス・ハイライト機能があれば見やすいですよね。ネットで調べると様々な方法が出てきますが、色々と現状(?)にあってない気もしたので、メモとっておきます。

・テンプレートに必要なjavascript・cssを読み込む

デザイン -> HTMLの編集 -> テンプレートの編集のheadタグの中に下記を記載。
ここではjavascriptとshのみ読み込んでいます。なうなヤングは、onloadはjqueryとかなんでしょうか?!

<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shCore.js' type='text/javascript'/>
<script src='http://alexgorbatchev.com/pub/sh/current/scripts/shAutoloader.js' type='text/javascript'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shCore.css' rel='stylesheet' type='text/css'/>
<link href='http://alexgorbatchev.com/pub/sh/current/styles/shThemeDefault.css' rel='stylesheet' type='text/css'/>
<script type='text/javascript'>
  window.onload = function() {
  SyntaxHighlighter.autoloader(
    'js jscript javascript http://alexgorbatchev.com/pub/sh/current/scripts/shBrushJScript.js',
    'bash shell http://alexgorbatchev.com/pub/sh/current/scripts/shBrushBash.js'
  );
  SyntaxHighlighter.all();
};
</script>

・投稿側でpreタグで囲む

<pre class="brush: js">
var x = 0;
</pre>

・参考
本家 http://alexgorbatchev.com/SyntaxHighlighter/ 対応している言語はこちらで調べて下さい。



2011年1月19日水曜日

mod_proxy_html をあきらめて mod_substitute を試した

リバースプロキシ越しに、内部のサーバへ転送したいのですが、良くあるのが、パスがずれる問題。

何とかならんかなと調べてると、mod_proxy_html を利用すると、hrefを変換かけたり出来るようですが、centos5 でかなり悩んだのですが、、、、上手くいきません(全く効いていない?)。どうしようか悩んだ所


の様な話があり、mod_substitute を試そうと思いました。

ところが mod_substitue は apache2.2.7 から標準添付らしく、centos5 の apache2.2.3 には付いてないのです! さらに悩んだ所

http://corpocrat.com/2008/09/19/install-apache-mod_substitute/

を発見!ソースだけ取ってきて apxs でコンパイルかけちゃうみたいです。
という訳で

# wget http://www.meisei-u.ac.jp/mirror/apache/dist//httpd/httpd-2.2.17.tar.gz
# tar zxvf httpd-2.2.17.tar.gz
# cd httpd-2.2.17/modules/filters/
# cp mod_substitute.c /tmp
# cd /tmp
# apxs -aic mod_substitute.c

これでインストールが完了するので、少し設定

AddOutputFilterByType SUBSTITUTE text/html
Substitute s/inner.domain.com/mydomain.com/n


再起動後見てみると!!上手く動きました。感謝、感謝です。ちょっと怖いけど動いてるからいっか。。







2011年1月11日火曜日

rails3とbackbone.jsの組み合わせで利用する1

■概要
backendをrails3にして、backbone.jsを利用する為の手順を残しておきます。

■railsプロジェクトの作成
$ rails new demo -T -J -d mysql
demo プロジェクト名
-T testunitはいらない
-J prototype.jsはいらない
-d mysql データベースはmysql

■gemを追加
$ cd demo
$ vim Gemfile
下記を一番下に追加(本当はバージョンをつけた方が良い)
gem 'jquery-rails'
group :development, :test do
  gem 'rspec'
  gem 'rspec-rails'
  gem 'rcov'
end
$ bundle install

■コードジェネレート
$ rails g rspec:install
$ rails g jquery:install --ui

■まず使えるように編集
$ vim config/database.yml

$ vim app/views/layouts/application.html.erb
文字列エンコーディングを明確に指定する為に下記追加
<meta charset="utf-8"/>

$ vim config/application.rb
jquery-railsに、javascriptのdefaults設定はまかせる(コメントアウトする)
# config.action_view.javascript_expansions[:defaults] = %w()
これを有効にしたい

$ vim spec/spec_helper.rb

ruby1.9.2でrcovを正しく動作させる為に、下記を一番下に追加
# quick monkey patch for rcov
# http://codefluency.com/post/1023734493/a-bandaid-for-rcov-on-ruby-1-9
if defined?(Rcov)
  class Rcov::CodeCoverageAnalyzer
    def update_script_lines__
      if '1.9'.respond_to?(:force_encoding)
        SCRIPT_LINES__.each do |k,v|
          v.each { |src| src.force_encoding('utf-8') }
        end
      end
      @script_lines__ = @script_lines__.merge(SCRIPT_LINES__)
    end
  end
end

$ vim .rspec
spork等で動いてもいい様に下記を追加しておく
--drb

■backbone.jsの準備
$ cd public/javascripts
↓jsファイル取得。ここも本当はバージョンを明示すべきかな
$ wget http://documentcloud.github.com/underscore/underscore.js
$ wget http://documentcloud.github.com/underscore/underscore-min.js
$ wget http://documentcloud.github.com/backbone/backbone.js
$ wget http://documentcloud.github.com/backbone/backbone-min.js
$ cd ../..
$ vim app/views/layouts/application.html.erb
backbone.jsを読み込むようにする。下記をhead内に追加
<%= javascript_include_tag "underscore-min.js", "backbone-min.js" %>

■履歴管理開始
$ vim .gitignore (履歴管理しない最低限のものを追加)

.bundle
db/*.db
db/*.sqlite3
db/schema.rb
log/*.log
tmp/
coverage/
*.swp

$ git init
$ git add .
$ git commit -m "最初のコミット"

■DB作成
$ rake db:create:all
$ rake db:migrate

■起動
$ rails s

ここまでで準備完了!次は実際にデータの操作をしてみます

20110113 追記
http://d.hatena.ne.jp/nedate/20101004/1286183882を参考にrcovの設定も追加させてもらいました!

2011年1月4日火曜日

CoffeeScript面白そう2

前回インストールしてみたCoffeeScriptだが、jasmineと組み合わせるとこんな感じで、javascriptのspecが書けた。


describe "String クラスは", ->
  str = ""
  beforeEach ->
    str = "jasmine"
  it "split メソッドを持っている", ->
    expect(str.split).toBeDefined()
  describe "ネストは", ->
    it "当然いけます", ->
      expect(str).toEqual("jasmine")


オリジナルのjasmine specと比較して良いのは

  • {} とか () とか が激減している
  • functionって書かなくて良い
  • varも書かなくて良い

辺りでしょうか。本気で使うなら課題は

  • coffeeの実行(*.coffee -> *.jsにコンパイル)を自動化
  • expect ~ toEqualとかをもっと"rspec"らしくしたい
  • 上の"str"をrspecっぽく何とかしたい(無理かな?)

といった所かな。少し考えるか。。

2011/01/04 0:52 追記


変数にrubyっぽく@をつけて(thisとバインド)、上記は

describe "String クラスは", ->
  beforeEach ->
    @str = "jasmine"
  it "split メソッドを持っている", ->
    expect(@str.split).toBeDefined()

で動くんだ。

2011年1月3日月曜日

CoffeeScript面白そう

CoffeeScriptとは「javascript悪くないけどね...文法がちょっと...」という人の為の言語で、
コンパイルするとjavascriptのソースが出力されます。

  • ruby(やpython)が大好き
  • "var"って書くのを忘れる
  • "function"って綴り長げー
  • "return"書きたくない
  • "if"を一行で書きたい

という私にぴったり。ちなみに37 signalsも使っているらしいですね

下記は「centos 5.5」に動く環境を作成するまでの記録です(2011/1/3現在)

■node.jsのインストール(v8もインストールされるようです)

# wget http://nodejs.org/dist/node-v0.2.6.tar.gz
# tar zxvf node-v0.2.6.tar.gz
# cd node-v0.2.6
# ./configure
# make
(# make test)
# make install

centos5.xにはshasumコマンドが存在しないようので、make testでエラーが発生します。
http://groups.google.com/group/nodejs/browse_thread/thread/4f8290fc06baab3b?pli=1
の様な話があるので

# ln -s /usr/bin/sha1sum /usr/bin/shasum

としておけば、落ちたテストは通ります。
(上記を実行しても私の環境的に multicast はテストが通りません...)

■npm(the Node Package Manager)のインストール

# curl http://npmjs.org/install.sh | sh

# npm -v (確認)
0.2.13-3

危ないからrootで実行するなとか言われましたが「It worked」だそうなのでほっときました。

■coffee scriptのインストール

# npm install coffee-script
# coffee -v (確認)
CoffeeScript version 1.0.0

■とりあえず実行してみる

# vim test.coffee で下記のように記載

debug = (x) -> console.log(x)
debug num for num in [1, 2, 3]

# coffee test.coffee
1
2
3
って表示されればOkay!

あとは、CoffeeScriptのサンプルを見てみましょう!