2012/03/27

いろいろ用語集

tmux

サーバー側でターミナルを起動して、そこに対してリモートから接続するイメージ。
もし本番環境で作業中にネットワークが切れても大丈夫。
スクリーンの縦分割がデフォルトでできるというのが使いやすいところ。

※tmux : http://goo.gl/DlKn

クロスサイトリクエストフォージェリ対策

昔mixiで話題になったぼくはまちちゃん、がそう。

1. 攻撃者が、攻撃用の Web ページを作成して WWW 上に公開する。(WWW上ででなくとも、未対策のHTMLメーラーにウェブページをHTMLメールとして送信するだけでもよい。)
2. 第三者が、攻撃用の Web ページにアクセスする。
3. 第三者は、攻撃者が用意した任意の HTTP リクエストを送信させられる。

4. 送信させられた HTTP リクエストによって、攻撃者の意図した操作が行われる。 (ここで「第三者」とは、被攻撃サイトに意図せずアクセスさせられると言う意味で用いている。)

防ぐ方法としては一連の流れを紐付けるようにセッション情報を紐付ける、という方法がある。

Railsではライブラリとして提供されているものがあるので、それを組み込む方法で対応したほうが自前で作成するよりも信頼性が高い。

クロスサイトリクエストフォージェリ - Wikipedia : http://goo.gl/bFhn

カピストラーノ

クライアントからSSHでサーバーにリモートアクセスしてシェルを実行するどいう動作をRubyをつかって自動化できるツール。
元々はRailsのデプロイの緩和のために作られたが、他にも色々と使える。

カピストラーノタスクはRubyで記述する。また、カピストラーノはcapfileから指示を読む。capfileはただのテキストファイル。

capコマンドで実行できる。また、役割を与えることでサーバーごとに処理を変えることもできる。

※カピストラーノ(Capistrano)を使ってみよう!(Basic編) : LR Labs : 株式会社ライブレボリューション アリエスユニット : http://goo.gl/SHjeF

chef-solo

chefもあるが、chefサーバーを立てないといけないので、chef-soloが比較的お手軽な感じ。
Rubyでレシピを書ける、というのがいいらしい。

※chef-soloで作業環境構築の自動化 | ひげろぐ : http://goo.gl/MfE3g

IRC【Internet Relay Chat】

基本的にはチャットシステム。Skypeなどとは違い、ID認証を必要とせずサーバー情報をIRCクライアントに指定するだけで接続することができる。また、基本は多人数でのテキストチャットがメイン機能。
IRCのサーバー側はLinuxベースでの構築が必要。
会社内や学校内のサーバーにIRCを構築してクローズドのチャットシステムを作ることができる。

※IRCとSkypeの違いってなんですか? - Yahoo!知恵袋 : http://goo.gl/IJ94V

継続的インテグレーション (Continuous Integration, CI)

継続的インテグレーションとは、ソフトウェアの品質改善・納期短縮のためのソフトウェア・エンジニアリングの習慣の集合である。その原則は、開発の連続的な全行程が終わってから品質管理を行うという古い慣行をやめ、成果物の諸小部分に対して頻繁に品質管理を行うことである。

※継続的インテグレーションとは - はてなキーワード : http://goo.gl/sY1yw

Jenkins

CIツール。
ソースコードの統合、テストの自動化、メトリクスの自動取得、ビルド完了時の画面を変えたりなどの愉快な機能もw
詳細は下記。

※「Hudson」改め「Jenkins」で始めるCI(継続的インテグレーション)入門 (1/4) - @IT : http://goo.gl/6F4d7

リファレンス

「変数を参照するもの」の意味。参照したい変数のアドレスのことで、C言語ではポインタと呼ばれたりする。
ただしC言語のポインタと同じに考えてはいけない。微妙に別のものである。
このリファレンスを通して、参照している変数を呼び出すことをデリファレンスという事も合わせて覚えておきたい。

※リファレンスとは - はてなキーワード : http://goo.gl/Dr8vb

ガングリア

下記のdstatと同様、サーバーリソースをグラフ化してくれるツール

dstat

サーバーリソースをグラフ化してくれるツール。
他にもいくつかツールが有るようだが、色々と統合して表示してくれる、ということで便利らしい。

※dstatの万能感がハンパない - (ひ)メモ : http://goo.gl/ETRui

iostat -dkxではIOPSやバイト単位の値など、I/Oに関する詳細は確認できますが、CPU使用率など他の統計値は同時に見ることができません。
vmstatはメモリの状況やブロック数単位のI/O状況は見られますが、バイト単位のI/O状況やネットワークの送信、受信バイト数を見ることはできません。
ターミナルを複数上げてvmstatとiostatをそれぞれ実行してもいいのですが、できれば一つのターミナルでいろいろな値を見たい。というわけで、dstatの出番です。
□MTGでの会話メモ IOスタットとVMスタットを合わせた感じ
1秒ごとにモニタリングしてくれる。
最初はガングリアでもいいが、ガングリアは15秒とか30秒ごとに見る感じ。
脳内マージしなくても良くなるのは嬉しい。
方針としてはディスクIOをなくすようにしていくことが目標。

インスタンス変数の定義はプロパティ宣言が自動生成してくれる:Objective-C

いろんなサンプルプログラムを見ているとクラスを定義する際のインスタンス変数の定義部分で色々な定義のされ方があって混乱したので、調べてみた。

そもそもは

インスタンス変数はクラス定義の.hファイル内の@interfaceから始まるコンパイラディレクティブ内の{}の中に記述する、とういうのが基本でした。が、Objective-C2.0からコンパイラがclang(詳細についてはエントリ末尾の参考サイト参照)になって賢くなった、ということらしく、プロパティで変数が宣言されていれば自動生成させるだけでOK、ということになったそうです。

なので、これまではインスタンス変数を宣言しつつ、プロパティでももう一回インスタンス変数についてのプロパティ宣言をしていたのですが、{}内の記述は消しちゃってもいい、といよりもむしろ{}ごと消しちゃいなさい、ということみたいです。具体的には下記みたいな感じです。

これまでは

@interface hogehoge : NSObject
{
    NSString *str1 ;  //インスタンス変数str1を定義
    NSString *str2;   //インスタンス変数str2を定義
}

@property (nonatomic) NSString *str1;  //str1のプロパティ宣言
@property (nonatomic) NSString *str2;  //str2のプロパティ宣言
@end

Objective-C2.0以降は

@interface hogehoge : NSObject
@property (nonatomic) NSString *str1;  //str1のプロパティ宣言
@property (nonatomic) NSString *str2;  //str2のプロパティ宣言
@end
すっきり!

また、上にも書きましたが、基本的にプロパティ宣言で済んでしまった場合は{}も消しましょう、ということみたいです。 iOS Developer Libraryの「Objective-C プログラミング言語」ファイルのP.35にも下記のように書いてあります。
歴史的には、インターフェイスにはクラスのインスタンス変数宣言が必要でした。(中略)インスタンス変数は実装詳細であり、通常、クラス自身の外からアクセスされることはありません。さらに、実装ブロック内に宣言すること、あるいは宣言済みプロパティから自動生成させることも可能です。したがって通常は、インスタンス変数宣言をパブリックインターフェイスで行うべきではないので、波括弧も省略してください。
プロパティ宣言が必要ないインスタンス変数を定義したい場合にはヘッダファイル(.hファイル)に書くのではなくて、実装ファイル(.mファイル)内の@implementation内に{}を追加してその中に記述するのが今風(?)みたいですw


参考サイト

イマドキっ子の Objective-C | cockscomb.info
Objective-C入門その7:アクセサメソッドをマスターする|サルにもできるiPhoneアプリの作り方
Clang - Wikipedia

2012/03/26

ラッパークラスについて:Objective-C

ラッパークラスってなに?

まず前提として、int型等の基本的な変数はオブジェクト化されていません。ただし、Objective-Cで用意されている基本的なクラス群の中には引数を必ずオブジェクト型で渡さないといけないメソッドがたくさん定義されています。

そこで、int型などの数値をオブジェクトとして扱う必要があるため、その時のためにラッパークラスが用意されています。
つまり、ラッパークラスは数値などをオブジェクト化するためのクラス、ということになります。

ラッパークラスNSNumbrerでラップしてみる

まずは
NSNumber *wrappedInt = [NSNumber numberWithInt:123]; //インスタンス生成メソッドを利用してオブジェクト生成
もしくは
NSNumber *wrappedInt = [[NSNumber alloc] initWithInt]];  //イニシャライザを利用してオブジェクト生成
でInt型のラッパークラスのインスタンスを生成する。

※上記の2つにはメモリ管理の視点から見ると違いがあるらしいので、後々勉強が必要。

ラップされた値を取り出す

NSNumberオブジェクトからラップされている値を取り出すときにはいろんな型で取り出すことができる。 たとえば、 [wrappedInt intValue] とか [wrappedInt doubleValue] とか [wrappedInt stringValue] とかで取り出せる。

文字列の生成について:Objective-C

文字列の生成方法について、文字コードの指定や、複数の文字列を統合したい場合などパターン別にまとめ。

1.文字列を直接指定して生成する方法

NSString *str = @"hogehoge"; これは単純でわかりやすいですね。

2.文字列と文字コードを指定して文字列を生成する方法

オブジェクトを生成してからイニシャライザで指定する方法と、クラスメソッドを利用する方法があります。
結論から言うと、クラスメソッドを利用したほうがシンプル、かつ色々と便利です。

オブジェクトを生成してからイニシャライザで指定すると、
NSString *str = [[NSString alloc] initWithCString: "hogehoge" encoding:NSUTF8StringEncoding];
こんな感じ。

クラスメソッドstringWithCString を利用した場合、下記のようになります。

NSString *str = [NSString stringWithCString:"hogehoge" encoding:NSUTF8StringEncoding];

stringWithCString:encoding: メソッドはallocメソッドによるメモリ割り当てからインスタンスの初期化まで全部やってくれるみたいです。
また、ラッパークラスのところでも書きましたが、イニシャライズを利用する場合とクラスメソッドを利用する場合で、メモリ管理の手続きが若干変わるようです。そのあたりについてはまた別に機会にエントリしたいと思います。

3.複数の文字列オブジェクトを組み合わせて文字列を生成する場合

実際にはこの形もよく使いますね。
NSString *str = [NSString stringWithFormat: @"%@ と%@", str1, str2];
1.の方法で下記のように書くとエラーになります。サボってついついやりがち。(私だけ?)
NSString *str = @"%@ と%@", str1, str2;  //これはダメ
ちゃんとstringWithFormatメソッドを使って生成しましょう。

メソッドの定義と実行:Objective-C

Objective-Cの特徴としてメソッドの定義方法と呼び出し方法がある。 メソッドの持つ引数の数によっても形が変わってくるので慣れが必要。戻り値の有無、引数の数によっていくつか例を挙げながら確認してみる。

※下記コード内の test は各クラスのインスタンスを表す変数

1.戻り値も引数もないメソッドの場合

- (void)hogeMethod;  //メソッドを定義
{
  //処理
}

[test hogeMethod];  //メソッド呼び出し

2.戻り値があって引数がないメソッドの場合

- (NSString *)hogeMethod;  //戻り値がNSString型のメソッドを定義
{
  //処理
}

NSString *result = [test hogeMethod];

3.引数が1つあって戻り値がないメソッドの場合

- (void)hogeMethod:(NSString *)argString;  //引数がNSString型のメソッドを定義
{
  //処理
}

[test hogeMethod:@"hogehoge"];  //hogehoged文字列を引数としてメソッド呼び出し

4.引数が1つと戻り値があるメソッドの場合

- (NSString *)myMethod:(NSString *)argString;  //戻り値がNSString型、引数がNSString型のメソッドを定義
{
   //処理
}

NSString *result = [test myMethod:@"hogehoge"];

5.引数が2つと戻り値があるメソッドの場合

 - (NSString *)myMethod:(NSString *)argString   //戻り値がNSString型、引数がNSString型とint型の2つあるメソッドを定義
                           myInt:(int)argInt;
{
  //処理
}

NSString *result = [test myMethod:@"hogehoge" myInt:123]; //メソッド呼び出し
myMethod、myIntはメッセージキーワードと呼ばれ、メソッド名はメッセージキーワードをつないだものになる。 つまり、このメソッドのメソッド名は「myMethod:myInt:」となる。

もっとわかりやすくすると、、

たとえば、
- (void)setWidth:(int)argWidth
              height:(int)argHeight
               depth:(int)argDepth;
{
  //処理
}
というメソッドの場合、メソッド呼び出しは下記のようになる。
[test setWidth:5 height:6 depth:7]
この記述方法だと各引数の意味がメッセージキーワードを見ればわかるので便利。

※一般的には下記のように書くがちょっとわかりにくい。
public void setSize(int w, int h, int d)  //メソッド定義
{
  //処理
}

test.setSize(5, 6, 7);  //メソッド呼び出し

というわけで

Objective-Cでメソッドを定義するときにはメソッドを呼び出した時の記述のされ方をイメージしておくとコードが非常にわかりやすくなる、というメリットがある。

おまけ

メソッド定義の最初の「-」はインスタンスメソッドの定義の場合に付加する。 先頭の記号が「+」の場合はクラスメソッドの定義となる。 例えば、クラスの初期化手続きで利用するallocメソッドやinitメソッドなどが代表的なクラスメソッド。

2012/03/08

sort_byメソッドの定義をひとつひとつ理解してみる

sortよりもsort_byの方が処理が軽いらしい。なんで?と思ったので、yield、ブロックの勉強も兼ねて調べてみた。

sort_byメソッドの定義を確認

class Array
  def sort_by
    self.collect { |i| [yield(i), i] }.
      sort {|a,b| a[0] <=> b[0] }.
      collect! {|i| i[1]}
  end
end
ほっほう。何やら複雑そうだ。yieldも入っていてなんだかわかりにくいので、処理の流れに沿って1つ1つ見ていく。

まずはsort_byメソッドが呼ばれるところから

sort_byメソッドは下記のような感じで呼ばれる。
ary = [1,2,3]
ary.sort_by do |num|
  num
end
もちろん下記でも同じ。
ary = [1,2,3]
ary.sort_by { |num| num }
この時にプログラムの気持ちになると、、
「実行しようとしたらsort_byメソッドが呼ばれたから呼び出してみよう!」
と思ってsort_byメソッドの定義を参照。
class Array
  def sort_by
    self.collect { |i| [yield(i), i] }.
      sort {|a,b| a[0] <=> b[0] }.
      collect! {|i| i[1]}
  end
end
「あれ?sort_byメソッドの中にyieldって書いてある!何したらいいかわからんからもう一回呼び出し元のブロックの中身を見に行かなきゃ!」

で、もう一回sort_byの呼び出し元を見てブロック要素を発見
do |num|
  num
end
yieldを実行すると、呼び出し時に与えられたこのブロックが実行されることになる。
イメージとしては下記のような感じに呼び出されたブロック内が実行される。
def yield(num)
  num
end
この場合は単純に引数をそのまま返すだけの処理。
これでようやくsort_byメソッド内でやるべきことがわかった。

ここからはメソッド内部の話。

最初から順番に見ていく。
self.collect { |i| [yield(i), i] }
まず、self.collectとあるので、メソッドのレシーバであるary配列に対してcollectすることがわかる。
ary配列の各要素を取り出し、[yield(i), i]の左側の部分で先程定義されたyield関数が実行され、右側のiにはそのまま配列から取り出した要素が渡される。
それをary配列分繰り返すと下記のような配列が生成される。
[[3, 3],[2, 2][1, 1]]
そしてこの配列に対して次の処理がそのまま実行される。つまり、
[[3, 3],[2, 2][1, 1]].sort{ |a, b| a[0] <=> b[0] }
となる。
sortメソッドがする処理を日本語で書くと、
「配列の中の各要素の内、左側の数字を2つ(たとえば、[3, 3]の左側の3と[2, 2]の左側の2)を持ってきて <=>で比較して並び替える。この処理をすべての要素の並び順が整うまで実行する」となる。

結果は
[[1, 1],[2, 2],[3, 3]]
となる。
これをさらに
[[1, 1],[2, 2],[3, 3]].collect! { |i| i[1] }
今度は各要素の右側の要素を抜き出して並べる処理。結果は
[1, 2, 3]
こうなる。完成!

で、結局なんでsortよりもsort_byのほうが処理が軽いのか

並び替えの操作自体はそれほど重い処理ではないので、大きな差は生まれない。ただ、並び替えをする前に処理の重い文字列操作などが入ると大きな差になる、ということ。

たとえば、暗号化をしてから並び替えを実施する場合などには、sortの場合には比較する度に暗号化の操作が必要になるため、最大でn^2(nは比較の要素数)の処理が発生することになる。
これに比べて、sort_byの場合は最大で要素数n回の処理で済む。

サンプルで示したような単純な並び替えであればそれほど処理速度に差は生まれないが、後から操作を追加したりすることも想定されるので、できるだけsort_byを使うようにしておくほうがよい、ということになる。

sort_by、よく考えられていますね!

参考URL

collect と map の違いってなんだ?

結論:調べてみたけどちょっとわからない、、

派閥抗争??

Enumerable#collect を主に使う派閥と Enumerable#map を主に使う派閥があり (これらのメソッドは効能および用法用量が同じ)、互いに血で血を洗う派閥抗争に明け暮れている
ん?結局同じもんだって理解でいいのかな。

Perlにはmapしかないらしい。ちなみにDan Kogaiさんはmap派。
404 Blog Not Found:mapとはおれのことかとcollectいい

だったらcollectはなんかタイプミスしそうだからmapつかおっと。

おまけ

ついでに見つけたmapの動きについて解説してるページ
map/collect - もち

キューとスタックについて

配列に対する処理について

配列の先頭・末尾要素を操作するメソッドまとめ

先頭要素に対する操作末尾要素に対する操作
要素を追加するunshiftpush
要素を取り出すshiftpop
要素を参照するfirstlast

キュー処理

キューはFIFO(First-in First-out:列の最後に要素を追加し、列の先頭(最初に列に追加したもの)を取り出す処理)なので、下記で実現できる。
ary = %w(a b c d e f)
p ary.push("g")
p ary.shift
p ary
実行すると
>> $ ruby que.rb
["a", "b", "c", "d", "e", "f", "g"]
"a"
["b", "c", "d", "e", "f", "g"]

スタック処理

スタックはFILO(First-in Last-out:列の最後に要素を追加し、列の最後を取り出す処理)なので、下記で実現できる。
ary = %w(a b c d e f)
p ary.push("g")
p ary.pop
p ary
実行すると
>> $ ruby stack.rb
["a", "b", "c", "d", "e", "f", "g"]
"g"
["a", "b", "c", "d", "e", "f"]

2012/03/06

print / puts / p の出力と返り値について

こんがらがるのでメモ。

それぞれで出力結果と返り値が異なる

それぞれ単体で動かしてみる。

print
>> print "test"
test=> nil    # testが出力され、返り値はnil
puts
>> puts "test"
test    # testが出力されて改行される
=> nil    # 返り値はnul
p
>> p "test"
"test"    # テキストオブジェクトが出力される
=> "test"    # 返り値にもテキストオブジェクトが入る
ここからわかるのは
・printとputsは改行がある程度で大きく変わらない。(putsは文字列の最後で改行)
・pは返り値を持ちつつ、オブジェクトが属するクラス情報も保持している。


出力と返り値の関係を理解するためにいろんなパターンで動きを見てみる。

print puts "test"

puts が test を出力して改行。putsの返り値 nil が print に引き渡され、print の出力は何もなし、返り値はnil

実行結果
>> print puts "test"
test
=> nil

print p "test"

pが"test"を出力して改行。pの返り値"test"がprintに引き渡され、printがtestを出力し、返り値はnil

実行結果
>> print p "test"
"test"
test=> nil

puts p "test"

pが"test"を出力して改行。pの返り値"test"がputsに引き渡され、putsがtestを出力して改行。返り値はnil

実行結果
>> puts p "test"
"test"
test
=> nil

puts print "test"

printがtestを出力。printの返り値nilがputsに引き渡され、putsの出力は何もなしで改行。返り値はnil

実行結果
>> puts print "test"
test
=> nil

p print "test"

printがtestを出力。printの返り値nilがpに引き渡され、pはnilを出力して改行。返り値はnil

実行結果
>> p print "test"
testnil
=> nil

p puts "test"

putsがtestを出力して改行。putsの返り値nilがpに引き渡され、pはnilを出力して改行。返り値はnil

実行結果
>> p puts "test"
test
nil
=> nil

2012/03/05

timesメソッドをeachメソッドで書き換えてみる

timesメソッドにもブロックローカル変数がある、ということを知って へー と思ったのでメモ。 自分の頭の整理のためにtimesメソッドをeachメソッドで書き換えてみる。

timesメソッドは簡潔

簡単なコードにしておく。
flower = "Rose"

5.times do
  puts flower
end
実行すると
$ ruby times_test.rb
0Rose
1Rose
2Rose
3Rose
4Rose
こうなる。問題なし。

timesメソッドでもブロックローカル変数を定義できる

flower = "Rose"

5.times do |i|
  print flower,i,"\n"
end
実行すると
$ ruby times_test.rb
Rose0
Rose1
Rose2
Rose3
Rose4
ブロックローカル変数iに数字が順番に代入されていることがわかる。

あえてeachメソッドで書き換えてみる

flower = "Rose"
ary = [0, 1, 2, 3, 4]

ary.each do |i|
  print flower,i,"\n"
end
こんな感じになる。

こうやって見てみるとeachメソッドもtimeメソッドも結局根本は同じで、timesメソッドはeachメソッドの実行を数字配列に限定したもの、と理解できる。
また、数字配列に限定することによって、終了の数字をtimesの前に書くだけで実行してくれるようになっている、ということ。

case文を勘違いしていたのでメモ

case文ってifとかwhileとかと同じようなもんでしょ!と思ってたけど、ちゃんと調べたらなんか色々勘違いしていたのでメモ。

case文をif文で書き換えてみる

下記は普通のcase文。
ary配列の各要素の所属クラスによって条件分岐させている。

case version
ary = [1, "hoge", nil]

ary.each do |item|
  case item
  when String
    print item," is string\n"
  when Numeric
    print item," is numeric\n"
  else
    print item," is something\n"
  end
end

実行結果
$ ruby case_test.rb
1 is numeric
hoge is string
 is something
※3つ目の変数はnilなので、何も表示されない。

まずは素直にif文にしてみる

if version1
ary = [1, "hoge", nil]

ary.each do |item|
  if item == String
    print item," is string\n"
  elsif item == Numeric
    print item," is numeric\n"
  else
    print item," is something\n"
  end
end
ん?これでクラスの情報にアクセスしてくれるのかな?とりあえず実行してみる。
$ ruby case_test.rb
1 is something
hoge is something
 is something
あぁ。やっぱりだめ。「==」は値の等号の演算子だしね、、(「==」は類似のメソッドも判断できるらしい)全部somethingになってしまった。

こういう時は「===」という演算子を使うらしい。

調べてみると、、
「===」は左辺が数値や文字列の場合は「==」と同じ意味を持つが、左辺が正規表現の場合は「=~」と同じようにマッチ判定をする。また、左辺がクラスの場合は右辺がそのクラスのインスタンスかどうかを判定する。
なるほど。ということは下記もダメ。一応試してみる。

if version2
ary = [1, "hoge", nil]

ary.each do |item|
  if item === String                  # クラス名が右辺になっている
    print item," is string\n"
  elsif item === Numeric          # クラス名が右辺になっている
    print item," is numeric\n"
  else
    print item," is something\n"
  end
end
実行してみる。
$ ruby case_test.rb
1 is something
hoge is something
 is something
やっぱりだめだった。

左辺にクラス名を移動

ary = [1, "hoge", nil]

ary.each do |item|
  if String === item                    # クラス名を左辺にした
    print item," is string\n"
  elsif Numeric === item            # クラス名を左辺にした
    print item," is numeric\n"
  else
    print item," is something\n"
  end
end
実行してみる。
$ ruby case_test.rb
1 is numeric
hoge is string
 is something
やっといけた。
case文の挙動をちゃんと理解できていなかった。。一つ一つ根本を理解していく癖をつけたい。


2012/03/04

Ruby1.9におけるローカル変数とブロック変数の関係

Ruby1.9からブロック内の変数のスコープが変わったようなのでメモ。


1.9ではブロック変数はブロックローカル変数として扱われる

つまり、ブロック内のパラメータとして定義された変数のスコープはブロック内に限定される、ということ。これをブロックローカル変数という。
試しに下記のコードを1.8.7、1.9.3それぞれのバージョンで実行してみる。

block_test.rb
x = 1
ary = [1,2,3]

ary.each do |x|
  puts x
end

p x

1.8.7での実行結果
$ ruby block_test.rb
1
2
3
3
1.9.3での実行結果
$ ruby block_test.rb
1
2
3
1
上記のように、1.8.7では最初に定義したx=1がイテレータ実行による影響を受けて x=3 になっているが、1.9.3では x=1 が保持されている。


ブロックパラメータで指定していない変数はブロックローカルにはならない

ブロック内でパラメータとして定義されずに利用された変数はブロックローカルな変数ではないため、ローカル変数として扱われる。

例えば、
x = 1
ary = [1,2,3]

ary.each do |y|
  x = y
end

p x
とすると結果は x=3 になる。念のため。
また、上記のようなケースで x もブロックローカルにするためには下記のように記述する。
x = 1
ary = [1,2,3]

ary.each do |y; x|
  x = y
end

p x
上記の実行結果は x=1 になる。


<以下、2012/03/05追記>

もうちょっと複雑にしてみると、
x = y = z =0         # 変数初期化
ary = [1, 2, 3]

ary.each do |x; y|   # 配列の要素はxに順番に代入される。yはブロック内のみをスコープとしたブロックローカル変数
  y = x              # ブロック変数xに配列の要素が順番に追加され、ブロックローカル変数yに代入される
  z = x              # ブロック変数xに配列の要素が順番に追加され、ローカル変数zに代入される
  p [x, y, z]
end

p [x, y, z]

実行結果は下記のようになる。
[1, 1, 1]
[2, 2, 2]
[3, 3, 3]
[0, 0, 3]

ブロックローカル変数として定義をしなかったzのみ影響を受けていることがわかる。



参考サイト

Ruby 1.9に移行する際に注意すべき10のポイント - なんとなく日記


2012/03/01

githubを使い始めるために最低限わかっておくべきこと

チームでgithubを使う事になったので、勉強中。
githubを理解する上で、なぜGitが生まれたのか、なぜSVNじゃだめなのか、を簡単に調べつつ、基本的な操作手順メモを書いておく。

なぜGitが生まれたのか

SVNとGitの比較から考えてみる。
調べてみたらこんな説明があった。

SVN は中央のサーバー上で実行され、変更を SVN のデータ・リポジトリーに追加し、また変更ごとにスナップショットを提供することができます。このスナップショットにはリビジョン番号が付けられています。リビジョン番号は SVN にとって、そして SVN を使用する人にとって、非常に重要です。私が変更した後で他の人が変更した場合には、その人のリビジョン番号の方が必ず大きいことが保証されています。
Git の目標も SVN に似ており、変更を追跡することですが、Git には中央のサーバーはありません。この違いは重要です。SVN は集中型ですが、Git は分散型です。そのため、Git では変更ごとに増加するリビジョン番号というものはありません。「最新のリビジョン」というものはないからです。Git にも一意のリビジョン ID がありますが、これらのリビジョン ID 自体は SVN のリビジョン番号ほど有用なものではありません。
Git の場合、重要なアクションはもはやコミットではありません。マージです。誰でもリポジトリーを複製することができ、そのクローンにコミットすることができます。リポジトリーの所有者は、変更をマージして元の 1 つのリポジトリーに戻すことができます。あるいは、開発者が変更をプッシュしてリポジトリーに戻すこともできます。
※Subversion ユーザーのための Git: 第 1 回 Git 入門 : http://goo.gl/U5I0Dより

つまり、SVNはリビジョン管理をメインとした集中管理型で、Gitはリポジトリーをみんなで複製(クローン)して変更をマージして一つのリポジトリに戻すための分散型システム。Gitのすごいところは分散して開発しても変更がちゃんとマージされるようになっている、という点。

いくつか理解すべきキーワードがあるが、全体像を確認しながら見ていったほうが理解しやすいので、全体像から。今回は簡単な説明、ということで、remote側ではbranchは切らずに常にmasterにpushする。(最後まで読めば意味わかるので、いまはわからなくてOK)

用語説明

local:ここでは自分のPC内のgithubのこと
remote:ここではチームメンバーで共有しているオンライン上のgithubのこと
repository:プロジェクトとほぼ同義。リポジトリを作成してその中にソースコードを配置する。実際にはローカルのgithub内とリモートのgithub内で同じリポジトリを作成して同期する。
branch:masterから分岐した枝で、新機能を開発する際には必ずbranchを切ってmasterに影響しない状態で実装する。
master:各branchの大元となる幹のようなもの。最終的にはmasterに全てのソースコードを取り込んで本番環境にリリースする。
merge:branchをmasterを取り込むこと。また、branchを切る前には必ず手元のソースコードを最新にすべきで、他人が開発したソースコードを取り込むこともmergeという。
commit:実装したソースコードファイルをbranchに取り込むこと。
    * masterに直接commitも可能だが、開発ログが残らないので、必ずbranchを切ってからcommitする。
push:ローカルのgitからリモートのgitに反映すること
pull:リモートのgitからローカルのgitに取り込むこと

たとえば、functionAという機能を実装してremoteのリポジトリに公開するまでの手順

実装したソースコードを共有するまでの手順を時系列で書くと、下記のようになる。
1.ローカルでfunctionAを実装
2.「$ git checkout -b functionA」 → branch を作成し、checkoutする(そのbranchに移動)
3.「$ git add ファイル名」→ 実装したファイルをgit管理下に置く
    * 「$ git add . 」だと全てのファイルが対象になる。事前に除外するファイルを設定しておく必要がある。基本的には「. 」はつけずにファイル名を指定する。
4.「$ git commit -m "functionA"」→ functionAbranchにコミットする
5.「$ git checkout master」→ masterに移動する。
    * masterにコミットするためにはmaster側からcommit コマンドを打つ必要があるため。
6.「$ git merge functionA」→ functionAをmaster にコミット
7.「$ git push origin master」→ remote のmaster に差分をpush

図解するとこんな感じ。番号は上の説明に対応(ちょっとずれてるので修正中)



参考URL

[導入メモ] GitHubを使うために、SVNユーザーがGitを調べた ::ハブろぐ : http://goo.gl/giYg6
Git ユーザマニュアル (バージョン 1.5.3 以降用) : http://goo.gl/5BJbd
transitive.info - Git 使い方 見出し一覧 : http://goo.gl/TRei4




Railsで簡易掲示板を作ってみる。studylog

http://www.evernote.com/shard/s13/sh/7dbb790f-c7a0-4660-a1db-38d26338730f/06d65c6896653294fc6886afe3ca371c

2012/03/01 20:29
・現時点ではCSSは未対応

「RilasによるアジャイルWebアプリケーション開発 第4版」studylog


http://goo.gl/RJCwi

・赤文字が疑問点、青文字は解決策や理解した部分。
・コードが画像になっているので、今後は埋め込み型に切り替える必要がある。
・現時点ではログイン機能などの部分は未着手。
・全体的につぶやきベースなのであしからずw

今勉強している内容メモ


□今勉強している内容
Rails
Ruby
オブジェクト指向
HTML/CSS
githubの使い方
vimの使い方

□これから勉強する内容
HTML5
JS
Fireworks
Hadoop
Objective-C
Java