得た知識をしっかり自分のものにするために
すごくよく出来る人が作った、すごくよく要点がまとまっているノートがほしい!という人がいます。 確かに、すごくよく出来る人のノートは要点がよくまとまっており、必要な情報にアクセスしやすく、また簡単に理解することができるため、欲しがる気持ちもわかります。そして一次情報を自分で得るよりも時間もかかりません。
しかし、それを使っていても当の本人の実力は一向に向上しません。
それはなぜか。
人は散らばった知識の断片をまとめ、体系立てていく中で理解を深めていくからです。まとめるという工程を経て初めてその人はその分野を構造的に理解し自分の血肉としているのです。
したがって、その人がまとめたノートをみているだけでは本当の実力は身につきません。(そのノートは苦労してまとめた本人にとってもはや血肉になっているためほぼ必要がなくなっていることが多いです。)
実力をつけるには自分で苦労して知識を得て、そして苦労してそれを構造化する必要があります。
まとめ
- 自分で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 から脱出するコマンド
**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
とかで突っ込むと b
は a
の1要素として入ります。
つまり、[1, 2, 3, [4, 5, 6]]
ですね。
これを平坦化したいときには a.flatten!
とかやると a
が破壊的に平坦化されます。
[1, 2, 3, 4, 5, 6]
しかし、最初からこれを得たいときには +
のほうが処理が自然です。
a + b
とかすることで得られます。
でもこれは破壊的メソッドとかがないのでこの値が欲しい時には代入して得る必要があります。
c = a + b
例えば配列 a
に b
を足してランダム化したものは
(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プロセスから並列でスレッドを起動することができる
- これらはリソースを共有することができる
- 実はプロセスもスレッドの一種
- プロセスがforkし生成される実行単位
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
使い分けるべきシーン
{ ... }
を使うべき
do ... end
を使うべき
- 上記以外の場合、基本こちらを使うべき。
Ref.
- 初めてのRuby
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