読者です 読者をやめる 読者になる 読者になる

新人への洗礼

新人の子が離席時にPCロックを忘れている!

チャンスですね

ls

ど定番

alias ls=sl

echo

牛さんのAAに癒されます

alias echo=cowsay
 _______ 
< hello >
 ------- 
        \   ^__^
         \  (oo)\_______
            (__)\       )\/\
                ||----w |
                ||     ||

xcowsayは、最近知りました。 より癒されます。

alias echo=xcowsay

cat

猫がマウスカーソルを追いかけてきます。 無駄な引数があると、エラーになるので引数は捨て去りますw

function cat() {
  oneko
}

EDITOR

nanoで十分です

export EDITOR=nano
alias vim=nano
alias gvim=nano
alias emacs=nano
alias xemacs=nano
alias sbul=nano
alias atom=nano

32bit Win7上でVagrant使って開発環境構築 box構築編

今日こそは

boxの構築をするぞ!ってことで
最終目標は、Ubuntu-13.04 desktop上に開発環境整える

2013/08/16 18:40 apt.shを修正

本日の流れ

  1. veeweeのtemplateから作成したいVMのtemplate選ぶ→definition作成
  2. definitionを微修正
  3. definitionを基にubuntuをインストール
  4. Vagrant用boxファイル作成
  5. vagrant up

VMのtemplate選ぶ

veewee落としてきたディレクトリへ移動する
ここは、適宜読み替えて

> cd work\veewee

template一覧表示

> bundle exec veewee vbox templates

ubuntu-13.04-desktop-i386が無いorz
しょうがないので、server版をインストールして、後でGUI対応する。

> bundle exec veewee vbox define 'ubuntu-13.04-desktop-i386' 'ubuntu-13.04-server-amd64'

これで、definitions\ubuntu-13.04-desktop-i386以下にtemplateがコピーされるわけだが
改行コードがWin仕様だと、Ubuntuが正しく解釈できないので
全てのファイルの改行コードを\nに変換しておく。

忘れると、invalid operationと言われ泣きを見るはめになる。。。

definitionを微修正

definitions\ubuntu-13.04-desktop-i386\definition.rbを編集
32bitな民は、amd64ではなくi386のイメージを指定する。

8,11c8,11
<   :os_type_id => 'Ubuntu_64',
<   :iso_file => "ubuntu-12.10-server-amd64.iso",
<   :iso_src => "http://releases.ubuntu.com/12.10/ubuntu-12.10-server-amd64.iso",
<   :iso_md5 => '4bd3270bde86d7e4e017e3847a4af485',
---
>   :os_type_id => 'Ubuntu',
>   :iso_file => "ubuntu-13.04-server-i386.iso",
>   :iso_src => "http://releases.ubuntu.com/raring/ubuntu-13.04-server-i386.iso",
>   :iso_md5 => '73d595b804149fca9547ed94db8ff44f',

apt.shに追記

1行目にsourceのURLをミラーサーバから取得するよう変更するsed追記
変えなくても取得は可能だが、転送スピードが1.5~2倍近く早くなるので、推奨。

> sed -i -e 's#us.archive.ubuntu.com#mirror.math.ucdavis.edu#g' /etc/apt/sources.list

末尾に、ubuntu-desktopをインストールする行を追記。
このままだと、CLIなのでGUI用のパッケージ入れる。

> apt-get -y install ubuntu-desktop

definitionを基にubuntuをインストール

> bundle exec veewee vbox build 'ubuntu-13.04-desktop-i386' --workdir=C:/Users/takeshi.takizawa/work/veewee
Downloading vbox guest additions iso v 4.2.16 - http://download.virtualbox.org/virtualbox/4.2.16/VBoxGuestAdditions_4.2.16.iso
Checking if isofile VBoxGuestAdditions_4.2.16.iso already exists.
Full path: C:/Users/takeshi.takizawa/work/veewee/iso/VBoxGuestAdditions_4.2.16.iso

The isofile VBoxGuestAdditions_4.2.16.iso already exists.
Building Box ubuntu-13.04-desktop-i386 with Definition ubuntu-13.04-desktop-i386:
- debug : false
- cwd : C:/Users/takeshi.takizawa/work/veewee
- force : false
- nogui : false
- auto : false
- checksum : false
- redirectconsole : false
- postinstall_include : []
- postinstall_exclude : []

We did not find an isofile here : C:/Users/takeshi.takizawa/work/veewee/iso/ubuntu-13.04-server-i386.iso.

The definition provided the following download information:
- Download url: http://releases.ubuntu.com/raring/ubuntu-13.04-server-i386.iso
- Md5 Checksum: 73d595b804149fca9547ed94db8ff44f


Download? (Yes/No)

忘れずに、Yesとタイプする。
時間がかかるので、まったりコーヒーでも飲みながら待つ。

The box ubuntu-13.04-desktop-i386 was built successfully!
You can now login to the box with:
ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -p 7222 -l vagrant 127.0.0.1

成功!

Win7 32bit Core i5-2520M 2.5GHz 4.00GB
で、3時間程度かかった。

Vagrant用boxファイル作成

> bundle exec veewee vbox export 'ubuntu-13.04-desktop-i386'

vagrantに登録

> vagrant box add ubuntu-13.04-desktop-i386 'C:/Users/takeshi.takizawa/work/veewee/ubuntu-13.04-desktop-i386.box'

vagrant up

ここからは、boxファイルに対して色々操作していく。
作業用ディレクトリに移動して

> cd working\directory

Vagrantfile作成

> vagrant init 'ubuntu-13.04-desktop-i386'

いざ、起動!

> vagrant up

sshで入れるかな?

> vagrant ssh
Welcome to Ubuntu 13.04 (GNU/Linux 3.8.0-19-generic i686)

 * Documentation:  https://help.ubuntu.com/
Last login: Thu Aug 15 07:15:17 2013 from 10.0.2.2
vagrant@ubuntu-13:~$

すばらっ

あとは、rails等のCookbookを
http://community.opscode.com/
から、ありがたく頂戴すれば良いはず。

32bit Win7上でVagrant使って開発環境構築 準備編

動機

備えあれば憂いなしでございます。

準備

  1. Install Ruby http://rubyinstaller.org/
  2. Install pik https://github.com/vertiginous/
  3. Install Development Kit http://rubyinstaller.org/downloads/
  4. Install veewee https://github.com/jedi4ever/veewee
  5. Install VirtualBox https://www.virtualbox.org
  6. Install Vagrant http://www.vagrantup.com
  7. Install Git http://git-scm.com/downloads

Install Ruby

Vagrantのpluginは、Rubyで書かれているので
gem installでサクッと入れられるように、Ruby入れます。

Install pik

2013/08/17 14:00
rubyのバージョンを1.9.2 -> 1.9.3に変更

Rubyのバージョン管理してくれるgem
Windows版のrmvもしくはrbenv

同じバージョンだけれど、gemだけ分けたいってのは無理なのかな?こういうの

$ rvm use 1.9.2@veewee --create

この件は、いったん保留して

サクッとgem install

> gem install pik

まだ、終わりじゃない。
PATH通っているところに、pikコマンドをインストールする必要がある。
Cドライブ直下に、binディレクトリ作ってパス通しておく。

> mkdir C:\bin

コントロールパネル -> システム -> システムの詳細設定 -> 詳細設定 -> 環境変数 -> システム環境変数
無ければPathを新規作成して、あればpathを編集
末尾に追記

;C:\bin

pikコマンドをインストールする

> pik_install C:\bin

ようやく完了。
ruby-1.9.3入れとく。

> pik install ruby 1.9.3
> pik use 1.9.3

もし、7zipが無いと怒られたら
エラーの通り、7zipを入れる。
親切なエラーですね、エラーってこうあるべき。

> pik package 7zip install

Install Development Kit

C/C++の拡張をbuildするのに必要。

最初のRubyと一緒に入れても良かったけれど
pikで取ってきたRubyにもインストールするので
ここで、一緒に入れる。

インストール手順
https://github.com/oneclick/rubyinstaller/wiki/Development-Kit

Cドライブ直下に、DevKitフォルダ作る
https://github.com/oneclick/rubyinstaller/downloads/
から、DevKit-4.5.2 self extracting archive ダウンロードする
展開先を、C:\DevKitにする

> cd C:\DevKit
> ruby dk.rb init

気をつけるのは、config.ymlにpikで入れたRubyのpathを追加することくらい
最後の行に、pikで入れたRubyのpathを追記。

# This configuration file contains the absolute path locations of all
# installed Rubies to be enhanced to work with the DevKit. This config
# file is generated by the 'ruby dk.rb init' step and may be modified
# before running the 'ruby dk.rb install' step. To include any installed
# Rubies that were not automagically discovered, simply add a line below
# the triple hyphens with the absolute path to the Ruby root directory.
#
# Example:
#
# ---
# - C:/ruby19trunk
# - C:/ruby192dev
#
--- 
- C:/Ruby192
- C:/Users/takeshi.takizawa/.pik/rubies/Ruby-193-p429

インストール
pikで新しくruby追加したら、そのバージョンにも忘れずにDevKit入れる。

> ruby dk.rb install

defaultのrubyを変更したい場合は、環境変数のPathのrubyの向き先を変える必要がある。
今回の場合、Pathには
C:/Ruby192
が書かれているので
C:/Users/takeshi.takizawa/.pik/rubies/Ruby-193-p429
に変更する。

いちいち面倒だな。。。

Install veewee

Vagrantのbox作成をサポートしてくれるgem

既存のboxで十分な場合は、不要。
既存のVagrant box一覧は、こちら
http://www.vagrantbox.es/

veeweeを使う場合、githubから頂戴してくる

> cd <path_to_workspace>
> git clone https://github.com/jedi4ever/veewee.git
> cd veewee

bundlerでinstall

> gem install bundler
> bundle install

veeweeコマンド叩いて、コマンド一覧が見れれば
インストール成功

> bundle exec veewee

Install VirtualBox

仮想マシンを実行する仮想化ソフトウェア・パッケージ

Install Vagrant

仮想マシンの雛形(box)から、お手軽に仮想マシンのセットアップができるツール。
仮想マシンごと作成、破棄できるので、気に入らなければ気軽に1から作り直せる。

Install Git

バージョン管理さまさま

RubyでDSL作ってみる

肝となる処理

instance_eval が便利。

ブロック渡し以外にも、文字列を渡してインスタンス内のコンテキストで実行可能。

てことで

  1. DSL用のメソッドAを用意
  2. DSLで書かれたファイルを読み込む
  3. メソッドAと同じインスタンスで、ファイルの内容をinstance_eval
  4. -_-b

Example

DSL用のメソッドを持ったクラス

class DSL
  attr_reader :names

  def self.execute
    contents = File.open('DSLFile', 'rb'){ |f| f.read }
    dsl = new
    dsl.instance_eval(contents)

    p dsl.names
  end

  def initialize
    @names = []
  end

  def hello(name)
    @names << name
  end
end

DSLファイル

hello 'world'
hello 'again'
hello 'kitty'

実行してみる

DSL.execute

["world", "again", "kitty"]

imagemagickをインストール

公式のFAQや、似たような記事は多数あるのですが、それでも嵌ったのでメモ残しときます。

事前準備

Install XQuartz

結果を出力するときに、ウィンドウ(X11)に出す場合は、先にXQuartzをインストールしておく必要があります。

display: delegate library support not built-in `' (X11) @ error/display.c/DisplayImageCommand/1909.
Unsatisfied dependency: XQuartz·
Homebrew does not package XQuartz. Installers may be found at:
  https://xquartz.macosforge.org

こんなエラーが出る場合は、XQuartzが入ってないです。
エラーが教えてくれている通りに、 https://xquartz.macosforge.org からインストールします。

Install libtool

なかったら入れておきます。

sudo brew install libtool

動かしたときに、以下のエラーが出る場合はリンク張りましょう

Library not loaded: /usr/local/lib/libltdl.7.dylib (LoadError)
sudo brew link --force libtool

set display

表示先を指定しておきます

export DISPLAY=:0.0

Install imagemagick

デフォルトだと、X11(XQuartz)利用しないので、オプションに指定してインストールします。

sudo brew install imagemagick --with-x11

お疲れ様です。インストール完了です。

動かしたときに、以下のエラーが出る場合は、X11が起動してません。

`display': unable to open X server `' @ error/display.c/DisplayImages/1666 (Magick::ImageMagickError)

/Applications/Utilities/XQuartz をダブルクリックして起動してやりましょう。


やれやれ、インストールで力つきちゃったよ。。。

バイナリ形式にするだけでメモリ節約プログラミング

比較条件に関係しない値なら、バイナリにする価値あり

小さい数値を多く扱う場合は、バイナリ(可変長表現)にすると結構小さくできます。

データ量が小さくなれば、DBからの取得速度が向上し、アプリのメモリ上にもより多くのデータを保持できるようになります。

ただ、バイナリ形式のままだと大小比較などの計算ができないので、必要に応じて数値型に戻してあげる必要があります。

コード

今回比較に利用したコードは、githubに上げてあります。

https://github.com/TakiTake/seiseki

数値とバイナリの速度比較

学校の生徒100人毎日テストを5科目受けたときの成績管理用DBを想定

バイナリ形式のDBは、科目カラムに5科目分のデータを保持させます。

テストデータなんで、土日祝日お構いなしにテスト受けてますw

ノーマルなDB

カラム名
日付 text
学籍番号 text
科目1 integer
科目2 integer
科目3 integer
科目4 integer
科目5 integer

バイナリ形式のDB

カラム名
日付 text
学籍番号 text
科目 blob

結果

1年分のデータ

size

normal  1.9MB
binary  1.7MB

insert

user     system      total        real
normal  4.740000  11.920000  16.660000 ( 94.378284)
binary  4.660000  11.920000  16.580000 ( 93.093927)

select

user     system      total        real
normal  0.210000   0.010000   0.220000 (  0.221661)
binary  0.190000   0.010000   0.200000 (  0.201906)
5年分のデータ

size

normal  9.6MB
binary  8.8MB

insert

user     system      total        real
normal 23.860000  58.860000  82.720000 (476.608330)
binary 23.530000  58.400000  81.930000 (507.330652)

select

user     system      total        real
normal  1.190000   0.070000   1.260000 (  1.300539)
binary  0.980000   0.070000   1.050000 (  1.078891)
10年分のデータ

size

normal  19MB
binary  18MB

insert

user     system      total        real
normal 47.350000 118.030000 165.380000 (920.600014)
binary 46.610000 118.380000 164.990000 (935.340207)

select

user     system      total        real
normal  2.140000   0.100000   2.240000 (  2.236974)
binary  1.790000   0.100000   1.890000 (  1.891564)

なぜ、サイズが小さくなるのか?

小さい数値を表すのに、8 byte もいらないよね

環境差分はありますが、自分の環境ではRubyのFixnumは、8 byte でした。

0~255までの数値なら 1byte で表すことができるので、固定長ではなく可変長で数値を扱えば、 7byte 削減できというわけです。

どうやって変換すればいいの?

数列 -> バイナリ文字列

Array#pack のテンプレートに w(BER-compressed integer) を指定するだけです。

http://www.ruby-doc.org/core-1.9.3/Array.html#method-i-pack

バイナリ文字列 -> 数列

String#unpack テンプレートに w(BER-compressed integer) を指定するだけです。

http://www.ruby-doc.org/core-1.9.3/String.html#method-i-unpack

応用編

ただの文字列なので、文字列結合もできます

  [33, 49, 300, 99, 1000].pack('w5') // "!1\x82,c\x87h"
  'abc' + [33, 49, 300, 99, 1000].pack('w5') // "abc!1\x82,c\x87h"

また、こういった文字列処理には、StringScannerが便利です。

http://www.ruby-doc.org/stdlib-1.9.3/libdoc/strscan/rdoc/StringScanner.html

先頭から、3 byte 取得

  str = 'abc' + [33, 49, 300, 99, 1000].pack('w5')
  ss = StringScanner.new(str)
  ss.peek(3) // "abc"

3 byte 分ポインタを進める

  ss.pos += 3

ここから後ろは、可変長なので何byte分取得すればいいかわかりません。

そんなときは、文字列中にbyte数を持たせてあげれば、そこから判断できます。

サイズを含む文字列

  packed = [33, 49, 300, 99, 1000].pack('w5')
  
  # packした文字列のサイズをさらに、packする
  # C(8-bit unsigned)にすることで、この1byteを読めば続く文字列のサイズが分かる
  # 文字列のサイズが、8bitで表しきれない場合は、テンプレートにS, L, Qを適宜使う
  packed_size = [packed.size].pack('C')
  
  str = 'abc' + packed_size + packed
  ss = StringScanner.new(str)
  
  # "abc"の3byte分進める
  ss.pos += 3
  
  # 1byte取得して、unpackすることで保存しておいたサイズを取得
  # unpackは、配列で返ってくるので、最初の要素を取得している
  ss.peek(1).unpack('C').first // 7
  
  # サイズを格納している、1byte分進める
  ss.pos += 1
  
  # 最後に、先ほど判明した7byte分取得して、unpackすると
  # めでたく最初の数列が取得できる
  ss.peek(7).unpack('w5') // [33, 49, 300, 99, 1000]

heroku上にsinatraで作ったアプリ上げるときのハマりどころ

herokuもsinatraも初心者な自分がハマった所と、対処法書いときます。

基本は、ユーザ登録をして
https://devcenter.heroku.com/articles/ruby
の通りに進めていけば良いのですが

HTMLのテンプレート使いたい

風の噂で、hamlがサクサク書けて良いと聞いたので、hamlを選択

Gemfileにhamlを追加
gem 'haml'
bundle installでhamlをインストール
bundle install
APPファイル(web.rb)でhaml読み込み
require 'haml'


これで、準備OK。

hamlテンプレートを指定する
get '/' do
  haml :index
end

と書いてやれば、index.hamlファイルをテンプレートとして利用可能。

# -*- coding: utf-8 -*-

require 'rubygems'
require 'sinatra'
require 'haml'

# ここだと、渡せないよ
@hoge = "この位置で宣言しても渡せません"

get '/' do
  # ここで、宣言すれば
  # 変数の受け渡しも可能
  @foo = "bar"
  haml :index
end
テンプレートはどこに置けば良いの?

sinatraのデフォルトだと、viewsディレクトリを見に行くらしいので

mkdir views

ディレクトリ作成。
viewsの"s"をお忘れなく。

cssとかは?

静的ファイルは、publicディレクトリ

mkdir public

同じようなコードで毎回テンプレート名指定するのがめんどくさい

パスと同じテンプレートファイル名ならば、これでいけた。

get '/:path' do
  path = params[:path]
  haml path.intern
end

hamlでちょっと凝ったことしたい

HTML5のフォーマットで書きたい

hamlのrequire文の下辺りに

set:haml, :format => :html5

で、フォーマットを指定する。

HTMLエスケープも自動でしたい

エスケープ設定も追加で

set:haml, :format => :html5, :escape_html => true
共通部分はレイアウトとしてまとめたい

layout.hamlという名前でレイアウトファイルを作成すれば
自動的にレイアウトとして認識してくれます。
ビューファイルは、= yieldで呼べる。
以下、body宣言までのレイアウトが、ビューを呼ぶ例。

!!!
%html{:lang => "ja"}
  %head
    %meta{:charset => "UTF-8"}
  %body
    / ここでビューを呼ぶ
    / =ではなく、!=にしないとエスケープされるので注意
    != yield

呼ばれるビューファイル側のインデントは、インデント無しの状態から始める。
bodyの子要素だからと、インデント2つ分から始めたら怒られた。

要素の属性値がたくさんあって、1行が長くなるのがいや

rubyのハッシュに詰めてから渡すと多少改善される

:ruby
  opts = {
    :src => "https://www.google.com/calendar/embed?src=XXX
    :style => "border: 0",
    :width => "800",
    :height => "600",
    :frameborder => "0",
    :scrolling => "no"
  }
%iframe{opts}

herokuでアプリの名前変えたらコミットできなくなっちゃった

# 現在の設定確認
% git remote -v 
heroku     git@heroku.com:strong-day-3354.git (fetch)
heroku     git@heroku.com:strong-day-3354.git (push)
# 変更
# アプリ名をAAAに変えた場合
% git remote set-url heroku git@heroku.com:AAA.git
# 反映確認
% git remote -v                                    
heroku     git@heroku.com:AAA.git (fetch)
heroku     git@heroku.com:AAA.git (push)

感想

使ってみての感想は、sinatraは記述量が少なくて便利。
命名規則は知らないとさっぱり。


hamlは、噂通りサクサクかける。
<、>と閉じタグ書かなくて良いのが楽。
rubyコードと記法が似ているから、覚えやすい。


裏側は、サクサクだな。
後は、表のデザインセンスがあれば、、、