得た知識をしっかり自分のものにするために

すごくよく出来る人が作った、すごくよく要点がまとまっているノートがほしい!という人がいます。 確かに、すごくよく出来る人のノートは要点がよくまとまっており、必要な情報にアクセスしやすく、また簡単に理解することができるため、欲しがる気持ちもわかります。そして一次情報を自分で得るよりも時間もかかりません。

しかし、それを使っていても当の本人の実力は一向に向上しません。

それはなぜか。

人は散らばった知識の断片をまとめ、体系立てていく中で理解を深めていくからです。まとめるという工程を経て初めてその人はその分野を構造的に理解し自分の血肉としているのです。

したがって、その人がまとめたノートをみているだけでは本当の実力は身につきません。(そのノートは苦労してまとめた本人にとってもはや血肉になっているためほぼ必要がなくなっていることが多いです。)

実力をつけるには自分で苦労して知識を得て、そして苦労してそれを構造化する必要があります。

まとめ

  • 自分で1次情報に当たりましょう。
  • そこで得た知識は頑張って自分でまとめましょう。
  • そしてまとめ終わったらそのノートは基本的に不要なので窓から投げ捨てましょう。

各種偽装データを作成できる Faker が便利

Ruby gem の Faker が便利だったのでメモしておきます。

この gem はTESTをする時などに用意したくなる fixture などを作成するときなどに活躍します。 文字数指定で validation しているコードを TEST したいときや email アドレスのフォーマットに従っているか validation しているコードの TEST をするときに、それらのデータを複数作成するのは手間です。

この gem はそのような場合に特に活躍します。

例えば任意の長さの人名を作成するには下記の様にします。

Faker::Name.name
# => "Adelia Kovacek II"

10 桁の数字をランダムに作成します。

Faker::Number.number(10)
# => "7128905535"

email アドレスを作成します。

Faker::Internet.email
# => "sharon@bahringer.org"

Faker::Internet.email('libitte')
# => "libitte@crist.info"

変わったところではアバター画像を作成してくれるものもあります。

Faker::Avatar.image
# => "http://robohash.org/[\"animi\", \"eveniet\", \"et\"]"

他にもたくさんオプションがありますので、用法を調べたいときには本家のREADMEを読むと良さそうです。

 

参考

演算子 && と and の使い分け

Ruby における演算子 &&and は同じ意味を持ちますが優先度が異なります。(Perlについても同様) これによって使うべきシーンがそれぞれ異なりますので、ここにはその辺りの使い分けについて書いておきます。

 

定義

定義は && も and も「左辺を評価し、真である場合右辺も評価する」というものです。

文法:
  • 式 `&&' 式
  • 式 `and' 式

 

しかし、優先度は && が and よりも高いです。

よって、下記のようなシーンで and を使用することはあまりおすすめできません。

return if a and b

なぜならば、and は優先度が低い演算子であるため例えば if の条件式が長くなってきた時に説明変数をおく場合、

target_condition = a and b

などとしてしまうと、おそらく作者が予期したとおりの値が変数に代入されないためです。 target_condition には b の値には一切依らず、

  • a が true の場合 true
  • a が false の場合 false

が代入されます。

これは and よりも = 演算子の優先度が高いことが理由です。 詳しい挙動は下記を参考にしてください。

[18] pry(main)> a = true and false
=> false
[19] pry(main)> a
=> true
[20] pry(main)> b = (true and false)
=> false
[21] pry(main)> b
=> false
[22] pry(main)> c = true && false
=> false
[23] pry(main)> c
=> false

 

参考

RSpec expect の () と {} の違い

RSpec の expect において

  • expect()
  • expect {}

はそれぞれ値を引数として取得するか、ブロックつきメソッドを引数とするかが異なります。

 

expect()

これにより、expect() ではすでに取得済みのレコードがあり、それが予期する値と等しいかどうかなどをTESTする際に便利です。

expect(response).to be_success
expect(response.status).to eq(200)

 

expect {}

一方 expect {} はexpect実行時に評価される関数を渡すことができるため、例えば Request spec を書くときなどに request 実行をブロックつきメソッドにして呼び出し時に実行したいというときに便利です。

let(:request) { post foobar_path, request_params, request_headers(user) }

...

expect { request }.to raise_error(APIErrors::Forbidden)

 

ちなみに expect の用法は公式のREADMEが詳しいです。  

参考

binding.pry から脱出するコマンド

binding.pry は debug の際に step 実行を行うことができ非常に便利なものです。 ただ脱出方法がいまいちわからず RSpec などで複数のテストケースを実行してしまう時など Ctrl + D の連打はつらいものがありました。 それでちょっと調べてみたらすぐにでてきました・・・。

exit!

とかで脱出できるみたいです。 他にも exit-programdisable-pry などを使う人もいるみたいです。

Ref.

**args は引数として期待していないハッシュが送られてきた時にとりあえず受け取ってくれるものらしい

def log(msg, level: "ERROR", time: Time.now)
  puts "#{ time.ctime } [#{ level }] #{ msg }"
end

みたいなメソッドがあった時に、正しくハッシュを渡してやると

log('Hi!', level: 'ERROR', time: Time.now) #=> Thu Nov 13 01:42:07 2014 [ERROR] Hi!

みたいに返ってくるわけなのですが、これに対して余分なハッシュを送った場合、下記のように例外を吐きます。

log('Hi!', level: 'ERROR', time: Time.now, date: Time.now) #=> ArgumentError: unknown keyword: date

もしこれが嫌なとき、つまり期待するハッシュ以外のハッシュがきても別にスルーしてほしい時などには ** で受け取ってやるといいみたいです。

こんなかんじで。

def log(msg, level: "ERROR", time: Time.now, **kwrest)
  puts "#{ time.ctime } [#{ level }] #{ msg }"
end

 

そうすれば期待しないハッシュを送っても例外を吐きません。

log('Hi!', level: 'ERROR', time: Time.now, date: Time.now) #=> Thu Nov 13 01:45:11 2014 [ERROR] Hi!
log('Hi!', date: Time.now) #=> Thu Nov 13 01:45:19 2014 [ERROR] Hi!

Ref.

配列における `<<` と `+` の違い

a = [1, 2, 3]b = [4, 5, 6]a << b  とかで突っ込むと ba の1要素として入ります。

つまり、[1, 2, 3, [4, 5, 6]] ですね。

これを平坦化したいときには a.flatten! とかやると a が破壊的に平坦化されます。

[1, 2, 3, 4, 5, 6]

 

しかし、最初からこれを得たいときには + のほうが処理が自然です。

a + b とかすることで得られます。

でもこれは破壊的メソッドとかがないのでこの値が欲しい時には代入して得る必要があります。

c = a + b

 

例えば配列 ab を足してランダム化したものは

(a + b).shuffle

とか

(a << b).flatten!.sort_by{rand}

とかとすれば得ることができます。

MySQL の分離レベルとか自動コミットとか

今回は分離レベルの話と自動コミットについて雑多なメモを。

 

分離レベル

MySQL InnoDB のデフォルト分離レベルは REPEATABLE-READ になっています。

このモードはダーティーリードは禁止するものの、ファントムリードなどは発生するというやつで、 4つの分離レベルの中で2番目に厳しいトランザクション独立性を持ちます。

  • READ UNCOMMITTED
  • READ COMMITTED
  • REPEATABLE READ
  • SERIALIZABLE

でも僕は READ COMMITED を使うことが多いです。 理由はパフォーマンスです。

また、READ COMMITED の場合、コミットされたデータは別のトランザクションから参照可能です。 これにより、別トランザクション内でも無駄にクエリを発行することを防いだりすることができたりするメリットもあります。

 

自動コミット

MySQL には自動コミットというのがあります。 これが有効の場合、更新系クエリは即座にコミットされてしまいます。 一方トランザクションを使うと、明示的に commit, rollback をしない限り更新が確定されません。

これは複数処理を一つのトランザクションとして all or nothing を実現したいときに便利です。 (Webアプリケーションを作成するときによく見かける方針だと思います。)

それで、これを命令するのが

start transaction, begin, set autocommit = 0

だったりします。

一つの起動プロセスの中で何度かトランザクション処理をするときには AUTO COMMIT モードをOFFにしてしまったほうがらくだと思います。

そういう時には

select @@autocommit;
set autocommit = 0
select @@autocommit;

とかで確認、設定してしまって、トランザクション処理を行うのがオススメです。

一方で一つのトランザクション処理しかしないよー、という場合には、 start transaction とか begin を使うのもいいと思います。

このへんはおこのみですね。

 

Ref.

スレッドとプロセスの違い (箇条書きメモ)

スレッドのプロセスがいまいちよくわからなくなったのでさくっと調べたものを箇条書きでメモしておきます。  

プロセス

  • プロセスはプログラムの実行単位のこと
    • リソースを共有するには別プロセスのリソースをコピーしてこなければならない。
    • プロセスが実行するプログラム内の変数は各プロセスごとに固有の領域が物理メモリ上に確保され、仮想メモリに割り当てられる  

スレッド

  • スレッドはプロセスがforkした並列動作可能な処理の単位
    • プロセスがforkし生成される実行単位
      • 1プロセスから並列でスレッドを起動することができる
      • これらはリソースを共有することができる
    • 実はプロセスもスレッドの一種

 

Ref.

Perl 及び Ruby におけるMixin

Perl

Perl は言語として多重継承が可能です。 例えば Cafe クラスが Shop クラスを継承しつつ、 Spotメソッドも使いたい、 という場合には下記のように書くことができます。

package Cafe
use strinct;
use warnings;
use parent qw(Spot Shop);

...

1;

NEXTを使えば同名メソッドの呼び出し順の問題を ある程度回避できるものの、やはり多重継承の持つ問題をすべて解消するものではありません。

というわけで Mixin を利用して多重継承の便利さを享受しようと考えるわけですが、 これを Perl で行うためには Exporter を使うのかなと思います。

package Shop;
use strict;
use warnings;
our @EXPORT = qw(menu);

sub menu {
    my $self = shift;
    return {
        coffee => 300,
        bread => 300,
    };
}

1;
package Spot;
use strinct;
use warnings;
our @EXPORT = qw(location);

sub location {
    my $self = shift;
    return 'shibuya';
}

1;
package Cafe;
use strinct;
use warnings;
use Shop;
use Spot;

sub new {
    my ($class, $name) = @_;
    bless { name => $name }, $class;
}

1;

Cafe クラスはどのクラスも継承せず、代わりに use することで Shop 及び Spot の持つメソッドを import することで Cafeインスタンスメソッドとして利用することが可能になっています。

Ruby

Ruby における Mixin はクラスがモジュールを include というものを使って継承することで実現しています。

Comparable は大小比較機能を付与するモジュールです。 これを include する例を下記に載せます。

class Foo
  include Comparable
  def <=>(rhs)
    #something good codes
  end
end

Foo から Comparableメソッドを利用できます。

foo1 = Foo.new
foo2 = Foo.new
food1 <= foo2  # Comparable が提供するメソッド

Ref.

初めての Ruby を読んだ

初めての Ruby を読みました。 良書でした。 この本は他の言語を使ったことがある人が Ruby の言語仕様をざっとキャッチアップするのに最適な本な気がします。

自分は本を読んだ後に書かないと知識が残留しない方なので、 自分忘備録として個人的に便利だったことを箇条書きでメモしておきます。

2章 配列とハッシュ

添字代入について

配列 a に対して添字代入は下記のような挙動となります。

irb(main):001:0> a = [1, 2]
=> [1, 2]
irb(main):002:0> a[0] = 3
=> 3
irb(main):003:0> a
=> [3, 2]
irb(main):004:0> a[4]= "4"
=> "4"
irb(main):005:0> a
=> [3, 2, nil, nil, "4"]
irb(main):006:0> a[0, 3] = 'a', 'b', 'c'
=> ["a", "b", "c"]
irb(main):007:0> a
=> ["a", "b", "c", nil, "4"]
irb(main):008:0> a[0..2] = "A"
=> "A"
irb(main):009:0> a
=> ["A", nil, "4"]
a[0, 3] = 'a', 'b', 'c'

^^ index: 0 から 3 要素以外はデータが消えてしまいます。

添字代入の裏側

添字参照式が返す値は、配列が保持しているオブジェクトの参照 実は添字代入式と添字参照式はまったく別物。

  • 添字代入式 ... Array#=メソッドの呼び出し
  • 添字参照式 ... Array#メソッドの呼び出し

よって下記のような現象が発生する。

irb(main):010:0> a = %w[a b]
=> ["a", "b"]
irb(main):011:0> a
=> ["a", "b"]
irb(main):012:0> a[-3]
=> nil
irb(main):013:0> a[-3] = 1
IndexError: index -3 too small for array; minimum: -2
    from (irb):13:in `[]='
  from (irb):13
  from /usr/bin/irb:12:in `<main>'

3章 数値

ビット演算

ビットシフトは下記のように行うことができます。

右にシフト

irb(main):021:0> 1 << 0
=> 1
irb(main):022:0> 1 << 1
=> 2
irb(main):023:0> 1 << 2
=> 4
irb(main):024:0> 1 << 3
=> 8
irb(main):025:0> 1 << 4
=> 16

左にシフト

irb(main):026:0> a = 1 << 4
=> 16
irb(main):028:0> a
=> 16
irb(main):029:0> a >> 1
=> 8

4章 文字列

ヒアドキュメント

EOS が区切り文字で % のあとに送りたい変数をがかけます。

count = database_connector.get_int(<<"EOS" % author.id)
  SELECT COUNT(*)
  FROM book
  WHERE book.author_id = %d
EOS

シンボル

シンボルは唯一性と軽量性が利点。

文字列の場合

irb(main):039:0* str1 = "ruby"
=> "ruby"
irb(main):040:0> str2 = "ruby"
=> "ruby"
irb(main):041:0> str1 == str2
=> true
irb(main):042:0> str1.equal? str2
=> false

シンボルの場合

シンボルは内容が同値であれば必ず同一のオブジェクトとなる。 特定の内容を表すシンボルオブジェクトはプロセス内で唯一となる。

irb(main):043:0> symbol1 = :ruby
=> :ruby
irb(main):044:0> symbol2 = :ruby
=> :ruby
irb(main):045:0> symbol1 == symbol2
=> true
irb(main):046:0> symbol1.equal? symbol2
=> true

オブジェクトとして同一かどうかだけを調べれば良いので、 シンボル同士は文字列同士に比べて高速に同値性を判定できる。

また、内容に対する唯一性を維持しなければならないため、 シンボルオブジェクトは文字列をは異なり変更不能(immutable)。

5章 入出力

特にまとめることはなかったかもです。

6章 変数と式

参照

入力のオブジェクトを破壊せずにオブジェクトを加工したいときには dup を使って複製してから行う。

def describe(name)
  name[2] = ?p
end

^^ これだと破壊的に処理してしまうため、

def describe(name)
  name = name.dup
  name[2] = ?p
end

という感じでオブジェクトを複製します。

多重代入

複数の式を平行して代入することができる。

a, b, c = 1, 2, 3

内部的には

a = 1; b = 2; c = 3

をしているとおもいきやそうではないらしい。

上記とは評価順序が異なり、 代入されようとしている値は、代入が実際に行われるよりも先に完全に計算される。 よって、

a, b = b, a

なども、元々も a 及び b の値がそれぞれ b 及び a に代入され、値の交換が実現できる。

irb(main):062:0> a, b, c = 1, 2, 3
=> [1, 2, 3]
irb(main):065:0> a, b = b, a
=> [2, 1]
irb(main):066:0> a
=> 2
irb(main):067:0> b
=> 1

多値と配列展開

多重代入は多値をいっぺんに代入する記法です。 * とい修飾を使うことで多値を受け取ることができる。

irb(main):068:0> a, *b = 1, 2, 3, 4, 5
=> [1, 2, 3, 4, 5]
irb(main):069:0> b
=> [2, 3, 4, 5]
irb(main):070:0> a
=> 1

また、* が代入の右辺に出現すると、逆に配列を多値に展開してくれる。

irb(main):071:0> array = [1, 2, 3]
=> [1, 2, 3]
irb(main):072:0> a, b, c = *array
=> [1, 2, 3]

irb(main):078:0> a, b, *c, d = *array, 3, 4, 5
=> [1, 2, 3, 3, 4, 5]
irb(main):079:0> a
=> 1
irb(main):080:0> b
=> 2
irb(main):081:0> c
=> [3, 3, 4]
irb(main):082:0> d
=> 5

7章 メソッド

レシーバの省略

擬似変数selfは常に「現在のレシーバ」を指している。 private メソッドは常にレシーバ省略形式で呼び出さなければならない。

Rubyプログラムにおいては、メソッド内外にかぎらずいかなる箇所においてもselfとなるべきオブジェクトが存在する。

irb(main):083:0> self
=> main

ブロック付きメソッドの定義

yield 式は、メソッド内から呼び出し側のブロックをコールバックする構文。

irb(main):092:0> def foo_bar_baz
irb(main):093:1> yield "foo"
irb(main):094:1> yield "bar"
irb(main):095:1> yield "baz"
irb(main):096:1> end
=> nil
irb(main):097:0> foo_bar_baz do |item|
irb(main):098:1* puts item
irb(main):099:1> end
foo
bar
baz
=> nil

8章 オブジェクトとクラス

特異メソッドと特異クラス

Rubyには特定のオブジェクトのためだけのメソッドやクラス、という概念があり、 これらのことを特異メソッド、特異クラスと呼ぶ。

特異クラス

ある特定のインスタンスのためだけにあるクラス。

CENTRAL_REPOSITORY = Object.new

class << CENTRAL_REPOSITORY
  def register(target)
    ...
  end

  def unregister(target)
    ...
  end
end

特異メソッド

概念上はクラスではなく、インスタンスに直接所属しているメソッド。 実装上は、特異メソッドもクラスに属していて、特異クラスのインスタンスメソッドという位置づけ。

irb(main):100:0> message = "Hello"
=> "Hello"
irb(main):101:0> def message.build_greeting(target)
irb(main):102:1> "#{self}, #{target}"
irb(main):103:1> end
=> nil
irb(main):104:0> message.build_greeting("world")
=> "Hello, world"
irb(main):105:0> message2 = "Hello"
=> "Hello"
irb(main):106:0> message2.build_greeting("world")
NoMethodError: undefined method `build_greeting' for "Hello":String
    from (irb):106
    from /usr/bin/irb:12:in `<main>'

認証と認可

認証はサイトのユーザーを識別することであり、認可はそのユーザーが実行可能な操作を管理することです。

  • 認証 ... サイトのユーザーを識別すること
  • 認可 ... そのユーザーが実行可能な操作を管理すること

権限付与とかを例に取ってみると、 付与のためにそのユーザーを識別するのが認証、 そして権限付与するのが認可 ということになるのだと思います。

認証されてから認可が行われる、ということなのだと思います。

expect change を複数データ同時にTESTしたいときに

expect change を複数データ同時にTESTしたいときなどがあります。 そんな時には以下のようにするとできます。(例はあまり適切ではありません...)

expect{ execute }.to change{ [User.find_by(id: 1).coin, User.find_by(id: 1).skill] }.from([100, 0]).to([0, 1])

Ref.

`{ ... }` と `do ... end` の違いと使い分けるべきシーン

ブロック付きメソッド呼び出しを記述する際には { ... } あるいは do ... end を使うと思います。 しかしこれらは厳密にいうと異なります。 その違いは 結合強度 です。

{ ... } の場合

some_method other_method { ... }

この式は次のように解釈されます。

some_method(other_method{ ... })

do ... end の場合

some_method other_method do ... end

この式は次のように解釈されます。

some_method(other_method) do ... end

使い分けるべきシーン

{ ... } を使うべき

  • メソッドの戻り値を利用する場合
  • メソッドチェーン(a.foo{}.bar{}.baz{})をする場合
  • 1行で記述できる場合

do ... end を使うべき

  • 上記以外の場合、基本こちらを使うべき。

Ref.

OS X への Redis インストール

homebrew 経由でインストールしました。

Install

$ brew search redis
hiredis    redis      redis1310  redis24
homebrew/nginx/redis2-nginx-module         homebrew/php/php54-redis               homebrew/php/php56-redis
homebrew/php/php53-redis               homebrew/php/php55-redis

$ brew install redis
$ brew install hiredis

起動

$ redis-server
[80855] 31 Oct 00:18:38.270 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
[80855] 31 Oct 00:18:38.272 * Increased maximum number of open files to 10032 (it was originally set to 2560).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 2.8.17 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in stand alone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6379
 |    `-._   `._    /     _.-'    |     PID: 80855
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

[80855] 31 Oct 00:18:38.278 # Server started, Redis version 2.8.17
[80855] 31 Oct 00:18:38.279 * The server is now ready to accept connections on port 6379