PostgreSQL 9.5 beta1 インストール

itame でインストールしてみた。
一応変数を外部に押し出してみたけど、どうだろう。汎用性はなさそうだな。

my_postgresql.rb

# PostgreSQL Install
ver = node[:postgresql][:ver]
short_ver = node[:postgresql][:short_ver]

package node[:postgresql][:pgdg] do
  not_if "rpm -q #{File.basename(node[:postgresql][:pgdg], ".rpm")}"
end

package "postgresql#{short_ver}"
package "postgresql#{short_ver}-server"
package "postgresql#{short_ver}-contrib"
package "postgresql#{short_ver}-devel"
package "postgresql#{short_ver}-libs"

execute "initdb" do
  command "PGSETUP_INITDB_OPTIONS='--no-locale' /usr/pgsql-#{ver}/bin/postgresql#{short_ver}-setup initdb"
  not_if "test -e /var/lib/pgsql/#{ver}/data/postgresql.conf"
end

service "postgresql-#{ver}" do
  action :start
end

# Firewall
execute "firewall port open" do
  command "firewall-cmd --add-port=5432/tcp --zone=public --permanent"
  not_if "grep -c 5432 /etc/firewalld/zones/public.xml"
end

service "firewalld" do
  action :restart
end

node.yaml

# postgresql
postgresql:
  pgdg: http://yum.postgresql.org/9.5/redhat/rhel-7-x86_64/pgdg-centos95-9.5-2.noarch.rpm
  ver: 9.5
  short_ver: 95

実行

itamae ssh --host localhost -p 2222 -u vagrant ./my_postgresql.rb -y node.yml

Vagrant の Box を作る

Redmine を使う環境を構築しようと思ったが、せっかくなので掲題を試してみようと思った次第。
検索すると、以下のサイト様の通りで全然OKで言うことなかった。すごいね。

Vagrant の VirtualBox 用 Base Box ファイルを手動で作ってみる | CUBE SUGAR STORAGE

CentOS7の通常DVDイメージを使ってインストールした。
f:id:yossk:20151025213722j:plain

NICの設定とかはインストール時にやってしまった。

今回、勉強も兼ねて itamae を使って設定してみた。

github.com

で、最初は上記サイト様の操作コマンドをそのまま command にして記述していたいのだが、何度も実行するのには向いていない。
そもそも何度も実行することはないのだが、気にはなる。
正しいかどうかは分からないが、結局 sshd_config や sudoers ファイルをホストに置いて、それを remote_file 使うと勝手に diff 見てくれるので便利。
下の感じでどうだろ。

# sshd config
remote_file "/etc/ssh/sshd_config" do
  owner "root"
  group "root"
  source "recipes/remote_files/sshd_config"
  mode "0600"
end

# vagrant
remote_file "/etc/sudoers" do
  owner "root"
  group "root"
  source "recipes/remote_files/sudoers"
  mode "0440"
end

directory "/home/vagrant/.ssh" do
  owner "vagrant"
  group "vagrant"
  mode "0700"
  action :create
end

execute "vagrant public key" do
  user "vagrant"
  command "curl -L -o /home/vagrant/.ssh/authorized_keys  https://raw.githubusercontent.com/mitchellh/vagrant/master/keys/vagrant.pub"
end

file "/home/vagrant/.ssh/authorized_keys" do
  owner "vagrant"
  group "vagrant"
  mode "0600"
end

service "sshd" do
  action :restart
end

7つのデータベース7つの世界

7つのデータベース 7つの世界

7つのデータベース 7つの世界

読了。 Cassandraを「使うのが目的」のことがあるんだけど、やっぱり間違ってると分かった。

第8章 Redis

  • 速度に関していえば最高
  • 超高速なキーバリューストア
  • 何であるかを正確に分類するのは難しい
  • 応用的なデータ構造をサポート
  • ブロッキングキュー
  • スタック
  • Pub/Sub
  • 有効期限/永続レベル/レプリケーションのオプションが設定可能
  • 便利なデータ構造のアルゴリズムやプロセスのツールキット
% brew install redis
% redis-server -v
Redis server v=3.0.5 sha=00000000:0 malloc=libc bits=64 build=78b12a45f78ec0e
% redis-server
% redis-cli
127.0.0.1:6379> PING
PONG
127.0.0.1:6379> SET 7wks http://www.sevenweeks.org/
OK
127.0.0.1:6379> GET 7wks
"http://www.sevenweeks.org/"
127.0.0.1:6379> MSET gog https://www.google.co.jp/ yah http://www.yahoo.co.jp/
OK
127.0.0.1:6379> MGET gog yah
1) "https://www.google.co.jp/"
2) "http://www.yahoo.co.jp/"
127.0.0.1:6379> SET count 2
OK
127.0.0.1:6379> INCR count
(integer) 3
127.0.0.1:6379> GET count
"3"
127.0.0.1:6379> SET bad_count "a"
OK
127.0.0.1:6379> INCR bad_count
(error) ERR value is not an integer or out of range
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> SET prag https://pragprog.com/
QUEUED
127.0.0.1:6379> INCR count
QUEUED
127.0.0.1:6379> EXEC
1) OK
2) (integer) 4
127.0.0.1:6379> MULTI
OK
127.0.0.1:6379> INCR count
QUEUED
127.0.0.1:6379> DISCARD
OK
127.0.0.1:6379> GET count
"4"
  • 複雑なデータ型
    • リスト・ハッシュ・セット・ソート済みが保存できる
    • ハッシュ
      • ネストできない
      • HDEL 削除
      • HINCRBY インクリメント
      • HLEN フィールド数
127.0.0.1:6379> MSET user:eric:name "Eric Redmond" user:eric:password s3cret
OK
127.0.0.1:6379> MGET user:eric:name user:eric:password
1) "Eric Redmond"
2) "s3cret"
127.0.0.1:6379> HMSET user:eric name "Eric Redmond" password s3cret
OK
127.0.0.1:6379> HVALS user:eric
1) "Eric Redmond"
2) "s3cret"
127.0.0.1:6379> HKEYS user:eric
1) "name"
2) "password"
127.0.0.1:6379> HGET user:eric password
"s3cret"
  • リスト
127.0.0.1:6379> RPUSH eric:wishlist 7wks gog yah
(integer) 3
127.0.0.1:6379> LRANGE eric:wishlist 0 -1
1) "7wks"
2) "gog"
3) "yah"
127.0.0.1:6379> LREM eric:wishlist 0 gog
(integer) 1
127.0.0.1:6379> LRANGE eric:wishlist 0 -1
1) "7wks"
2) "yah"
127.0.0.1:6379> LPOP eric:wishlist
"7wks"
127.0.0.1:6379> LRANGE eric:wishlist 0 -1
1) "yah"
127.0.0.1:6379> RPOPLPUSH eric:wishlist eric:visited
"yah"
% gem i redis
Successfully installed redis-3.2.1
1 gem installed
  • リストのブロック
127.0.0.1:6379> BRPOP comments 300
127.0.0.1:6379> LPUSH comments "Prag is great! I buy all my books there."
(integer) 1
127.0.0.1:6379> BRPOP comments 300
1) "comments"
2) "Prag is great! I buy all my books there."
(30.38s)
  • セット
127.0.0.1:6379> SADD news nytimes.com pragprog.com
(integer) 2
127.0.0.1:6379> SMEMBeRS news
1) "pragprog.com"
2) "nytimes.com"
127.0.0.1:6379> SADD tech pragprog.com apple.com
(integer) 2
127.0.0.1:6379> SINTER news tech
1) "pragprog.com"
127.0.0.1:6379> SDIFF news tech
1) "nytimes.com"
127.0.0.1:6379> SUNION news tech
1) "pragprog.com"
2) "apple.com"
3) "nytimes.com"
127.0.0.1:6379> SUNIONSTORE websites news tech
(integer) 3
127.0.0.1:6379> SMEMBErS websites
1) "pragprog.com"
2) "apple.com"
3) "nytimes.com"
  • ソート済みセット, 範囲
127.0.0.1:6379> ZADD visits 500 7wks 9 gog 9999 prag
(integer) 3
127.0.0.1:6379> ZINCRBY visits 1 prag
"10000"
127.0.0.1:6379> ZRANGE visits 0 1
1) "gog"
2) "7wks"
127.0.0.1:6379> ZRANGE visits 0 -1 WITHSCORES
1) "gog"
2) "9"
3) "7wks"
4) "500"
5) "prag"
6) "10000"
127.0.0.1:6379> ZREVRANGE visits 0 -1 WITHSCORES
1) "prag"
2) "10000"
3) "7wks"
4) "500"
5) "gog"
6) "9"
127.0.0.1:6379> ZRANGEBYSCORE visits 9 10000
1) "gog"
2) "7wks"
3) "prag"
127.0.0.1:6379> ZRANGEBYSCORE visits (9 (10000
1) "7wks"
127.0.0.1:6379> ZRANGEBYSCORE visits -inf inf
1) "gog"
2) "7wks"
3) "prag"
127.0.0.1:6379> ZADD votes 2 7wks 0 gog 9001 prag
(integer) 3
127.0.0.1:6379> ZUNIONSTORE importance 2 visits votes WEIGHTS 1 2 AGGREGATE SUM
(integer) 3
127.0.0.1:6379> ZRANGEBYSCORE importance -inf inf WITHSCORES
1) "gog"
2) "9"
3) "7wks"
4) "504"
5) "prag"
6) "28002"
  • 有効期限
    • カウントダウンは EXPIREAT (絶対時間)
    • EXPIRE は相対時間
127.0.0.1:6379> SET ice "I'm melting..."
OK
127.0.0.1:6379> EXPIRE ice 10
(integer) 1
127.0.0.1:6379> EXISTS ice
(integer) 1
127.0.0.1:6379> EXISTS ice
(integer) 1
127.0.0.1:6379> EXISTS ice
(integer) 1
127.0.0.1:6379> EXISTS ice
(integer) 0
127.0.0.1:6379> SETEX ice 10 "I'm melting..."
OK
127.0.0.1:6379> TTL ice
(integer) 4
127.0.0.1:6379> SETEX ice 10 "I'm melting..."
OK
127.0.0.1:6379> PERSIST ice
(integer) 1
127.0.0.1:6379> EXISTS ice
(integer) 1
127.0.0.1:6379> SET greeting hello
OK
127.0.0.1:6379> GET greeting
"hello"
127.0.0.1:6379> SELECT 1
OK
127.0.0.1:6379[1]> GET greeting
(nil)
127.0.0.1:6379[1]> SET greeting "guten tag"
OK
127.0.0.1:6379[1]> SELECT 0
OK
127.0.0.1:6379> GET greeting
"hello"
127.0.0.1:6379> MOVE greeting 2
(integer) 1
127.0.0.1:6379> SELECT 2
OK
127.0.0.1:6379[2]> GET greeting
"hello"
127.0.0.1:6379[2]> SELECT 0
OK
127.0.0.1:6379> GET greeting
(nil)
% telnet
telnet> open localhost 6379
Trying ::1...
Connected to localhost.
Escape character is '^]'.
SET test hello
+OK
GET test
$5
hello
SADD stest 1 99
:2
SMEMBERS stest
*2
$1
1
$2
99
% (echo -en "ECHO hello\r\n"; sleep 1) | nc localhost 6379
$5
hello
% (echo -en "PING\r\nPING\r\nPING\r\n"; sleep 1) | nc localhost 6379
+PONG
+PONG
+PONG
  • 出版/購読
127.0.0.1:6379> SUBSCRIBE comments
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "comments"
3) (integer) 1
127.0.0.1:6379> PUBLISH comments "Check out this shortcoded site! 7wks"
(integer) 1
127.0.0.1:6379> SUBSCRIBE comments
Reading messages... (press Ctrl-C to quit)
1) "subscribe"
2) "comments"
3) (integer) 1
1) "message"
2) "comments"
3) "Check out this shortcoded site! 7wks"
  • サーバ情報
127.0.0.1:6379> info
# Server
redis_version:3.0.5
redis_git_sha1:00000000
redis_git_dirty:0
redis_build_id:78b12a45f78ec0e
redis_mode:standalone
...
  • 永続性
    • SAVE
    • BGSAVE
  • スナップショット
  • 追記型フィールド
    • めちゃくちゃ遅い
  • セキュリティ
    • プレインテキストのパスワードを設定するだけの機能はある
    • ファイアウォールSSHのセキュリティを使うべき
    • コマンド自体を隠したり無効にしたりできる
  • パラメータの調整
% redis-benchmark -n 100000                                                                                                         [252/576]
====== PING_INLINE ======
  100000 requests completed in 3.33 seconds
  50 parallel clients
  3 bytes payload
  keep alive: 1

0.86% <= 1 milliseconds
83.00% <= 2 milliseconds
99.95% <= 7 milliseconds
99.96% <= 8 milliseconds
100.00% <= 9 milliseconds
100.00% <= 9 milliseconds
30012.00 requests per second
...
% redis-server redis-sl.conf
37908:S 24 Oct 21:38:41.265 * Increased maximum number of open files to 10032 (it was originally set to 256).
                _._
           _.-``__ ''-._
      _.-``    `.  `_.  ''-._           Redis 3.0.5 (00000000/0) 64 bit
  .-`` .-```.  ```\/    _.,_ ''-._
 (    '      ,       .-`  | `,    )     Running in standalone mode
 |`-._`-...-` __...-.``-._|'` _.-'|     Port: 6380
 |    `-._   `._    /     _.-'    |     PID: 37908
  `-._    `-._  `-./  _.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |           http://redis.io
  `-._    `-._`-.__.-'_.-'    _.-'
 |`-._`-._    `-.__.-'    _.-'_.-'|
 |    `-._`-._        _.-'_.-'    |
  `-._    `-._`-.__.-'_.-'    _.-'
      `-._    `-.__.-'    _.-'
          `-._        _.-'
              `-.__.-'

37908:S 24 Oct 21:38:41.268 # Server started, Redis version 3.0.5
37908:S 24 Oct 21:38:41.268 * The server is now ready to accept connections on port 6380
37908:S 24 Oct 21:38:41.268 * Connecting to MASTER 127.0.0.1:6379
37908:S 24 Oct 21:38:41.269 * MASTER <-> SLAVE sync started
37908:S 24 Oct 21:38:41.269 * Non blocking connect for SYNC fired the event.
37908:S 24 Oct 21:38:41.270 * Master replied to PING, replication can continue...
37908:S 24 Oct 21:38:41.270 * Partial resynchronization not possible (no cached master)
37908:S 24 Oct 21:38:41.271 * Full resync from master: d5f7d1c8d4640c774e1c747b7cec1bd169e092c9:1
37908:S 24 Oct 21:38:41.397 * MASTER <-> SLAVE sync: receiving 400726 bytes from master
37908:S 24 Oct 21:38:41.400 * MASTER <-> SLAVE sync: Flushing old data
37908:S 24 Oct 21:38:41.400 * MASTER <-> SLAVE sync: Loading DB in memory
37908:S 24 Oct 21:38:41.451 * MASTER <-> SLAVE sync: Finished with success
  • ブルームフィルタ
    • セットに存在しない項目をチェックする確率的データ構造
    • Ruby の神童 Ilya Grigorik
  • SETBIT と GETBIT
127.0.0.1:6379> SETBIT my_burger 1 1
(integer) 0
127.0.0.1:6379> SETBIT my_burger 2 1
(integer) 0
127.0.0.1:6379> GETBIT my_burger 3
(integer) 0
127.0.0.1:6379> GETBIT my_burger 1
(integer) 1
  • ポリグロット永続亜kサービス
  • ノンブロッキングコード
    • 時間のかかるプロセスの終了を待たずにメインコードを実行し続けること
    • Ruby: EventMachine
    • Python: Twisted
    • Java: NIOライブラリ
    • C#: Interlace
    • JavaScript: Node.js
  • Redis の強み
    • 速度
    • 他のキーバリューストアと違うのはリスト・ハッシュ・セットのような複合データ型の保存や検索ができる
    • 永続化のオプションがある
      • 速度とデータの保全性を秤にかけて落としどころを探る
    • レプリケーションは読み取り回数の非常に多いシステムに最適
  • Redis の弱み
    • スナップショットをとる前にシャットダウンするとデータが失われる
    • 追記型ファイルを設定しても期限切れの値を扱うリスクがある
    • 使用可能な RAM より大きなデータセットは扱えない

第9章 まとめ

  • データの保存方法は大きく5つに分類
    1. リレーショナル
    2. キーバリュー
    3. カラムナー
    4. ドキュメント
    5. グラフ
  • リレーショナル
    • データが変わりやすかったり、データ階層が深いものには適していない
  • キーバリュー
    • 複雑なモデリングが必要なデータには弱い
    • データがさほど結びついていない問題に適している
    • CRUD 操作以上のクエリが必要なときにはうまくいかない
  • カラムナ-
    • 水平スケーラビリティが高いので、ビッグデータの問題に最適
    • データ使用パターンが事前に決定できていないければ適していない
  • ドキュメント
    • 変化の大きなドキュメントの問題に適している
    • 事前にデータがどのようになるか正確に分からない場合
    • インピーダンスミスマッチが少ない
    • 結合に該当するものがないので正規化できない
  • グラフ
    • レコメンテーションエンジン
    • アクセスコントロールリスト
    • ジオグラフィックデータ
    • ネットワーキングアプリケーション
    • オブジェクト指向にも完璧に対応
    • ネットワーク分割には適さない
  • データベースの選択はドメインのデータに適したデータベースの分野を考えるより複雑

7つのデータベース7つの世界

7つのデータベース 7つの世界

7つのデータベース 7つの世界

第7章まで。

第7章 Neo4j

7つのデータベース7つの世界

7つのデータベース7つの世界

7つのデータベース 7つの世界

7つのデータベース 7つの世界

NoSQLを使う場面とは?ということに悩んだので、読んでみた。 正直、PostgreSQLさえあればなんでも出来そうって気になってきた。 第6章まで。

第1章 イントロダクション

  • リレーショナルデータベース
  • キーバリューストア
    • Raik
    • Redis
  • 列指向データベース
    • HBase
  • ドキュメント指向データベース
  • グラフデータベース
    • Neo4j
  • ポリグロット(混合型)
    • 複数のデータベースの長所を組み合わせてエコシステムを構築

第2章 PostgreSQL

  • 普及の要因
    • データの安全性(ACID準拠)
    • マインドシェア
    • クエリの柔軟性
    • 正規化による柔軟な問い合わせ
  • PostgreSQL
    • 自然言語のパース
    • 多次元インデックス
    • 地理空間クエリ
    • 高度なトランザクション
    • ストアドプロシージャ
    • ユニコード
    • シーケンス
    • テーブル継承
    • 副問い合わせ
    • ANSI SQL に最も準拠したRDB
    • 高速
    • 信頼性が高い
    • テラバイト単位のデータも扱える
    • Skype、CNAF、FAAでも実運用されている
  • 数学的リレーション
    • リレーション(テーブル)
    • 属性(列)
    • タプル(行)
  • CRUD
    • Create
    • Read
    • Update
    • Delete
  • インデックスで高速検索
    • Bツリーインデックス
    • ハッシュインデックス
  • 集約関数
  • グループ化
  • ウィンドウ関数
    • 複数の行に対して集約関数を実行
    • 行をグループ化することなく集約関数を使える
  • トランザクション
    • ACID 準拠
      • Atomic(原子性: 操作はすべて実行されるか、すべて実行されない)
      • Consistent(整合性: データは常に正しい状態にあり、不整合な状態はない)
      • Isolated(隔離性: トランザクションは他から邪魔されない)
      • Durable(永続性: コミットされたトランザクションはサーバがクラッシュ後も安全である)
    • ACID の整合性は CAP定理 の整合性とは違う
  • ストアドプロシージャ
  • 恐怖のベンダーロックイン
  • コードはアプリケーションに依存するのか?データベースに依存するのか?
  • トリガー
  • ビュー
  • ルール
  • クロス集計
  • あいまい検索
    • LIKE、ILIKE
  • 正規表現
  • レーベンシュタイン
  • トリグラム
  • TSVevtor, TSQuery
  • 汎用転置インデックス GIN
  • メタフォン
  • 多次元ハイパーキューブ
  • PostgreSQL の強み
    • リレーショナルモデルと同じく膨大
    • 長年の研究
    • あらゆる計算分野における利用実績
    • 柔軟なクエリ
    • 高い整合性と永続性
    • 実践で使い込まれた各言語用のPostgres用のドライバ
  • PostgreSQL の弱み
    • 分割がうまくできない
      • スケールアップ、スケールアウト
    • データが柔軟過ぎる場合

第3章 Raik

HBase

  • RDBMS の双子の悪魔
  • 他のDBにない機能
    • バージョニング
    • 圧縮
    • GC
    • インメモリテーブル
  • Apache Hadoop の contrib パッケージとして生まれたが、今はトップレベルプロジェクト
  • Facebook、Tiwtter でも利用
  • 本番の品質で運用するには最低5台以上のノードが必要
  • 3つのモード
  • HBaseシェル
  • 列ファミリーを変更する操作はコストが高い
    • 新しい設定の列ファミリーを作って、すべてそこにコピーするから
  • 列ファミリーを使うことにより細かなパフォーマンスチューニングが可能となる
  • 圧縮
    • Gzip(GZ)
    • Lempel-Ziv-Oberhumer(LZO)
      • Community 推奨だがライセンスに問題がありバンドルされていない
      • 高性能圧縮が必要なら
  • ブルームフィルタ
    • 消費領域を抑えることができるが、飽和率に応じて一定の誤検出が発生する
    • コストの高いディスク読み取りをする前にデータが存在するかどうかを決定する高速な方法
  • スパースデータストア
  • Thrift
  • HBase のスキーマ設計は、テーブルや列のパフォーマンスを決定する
  • HBase の強み
    • 堅牢なスケールアウトアーキテクチャ
    • バージョニング
    • 圧縮機能
      • ギガ、テラで役に立つ
    • ラックウェア
    • Community が素晴らしい
  • HBase の弱み
    • スケールダウンできない
    • 最低5台が必要
    • 管理が難しい
    • 小さな問題の解決には向いていない
    • 初心者用のドキュメントも手に入らないので学習曲線は急勾配
    • 行キー以外にソートやインデックスの機能を提供していない
    • データ型も存在しない
  • HBase と CAP定理
    • CP
  • 使うときは怪我をしないように

第5章 MongoDB

  • パワードリル
  • 様々な用途に使える
  • 仕事の大小を問わない
  • JSON フォーマットのドキュメントデータベース
  • スキーマレス
  • サーバサイドでの結合をサポートしていない
  • 自動採番
  • あらゆるところに JavaScript を使っている
  • スペルミスに注意
    • 柔軟性にはコストがつきもの
  • ドキュメントの集まりはコレクション
  • インデックス
    • Bツリー
    • 2次元インデックス
    • GeoSpatial
  • 大きなコレクションにインデックスを作ろうとすると時間とリソースを浪費
  • 集約クエリ
  • group() 関数の弱点
    • 結果ドキュメント数の上限が10,000
    • コレクションをシャードするとうまく動かない
  • 特別な要素
  • レプリカセット
    • スケールアウトを目的に作られている
      • 単独で実行するものではない
    • ノードが奇数であることを期待する
    • マルチマスターを許可しないことがコンフリクト対策
    • 奇数にできない場合は調停者を設ける
      • arbiterOnly プロパティ設定
  • シャーディング
    • mongos サーバは mongoconfig コンフィグサーバに接続して保存されたシャーディング情報を追跡する
  • 地理空間情報クエリ
  • GridFS
  • MongoDB の強み
    • レプリケーションと水平スケーリングによって大量データ/リクエストを扱える
    • スキーマを揃える必要がないので柔軟なデータモデルを扱える
    • 簡単に扱えるように作られている
  • MongoDB の弱み
    • 非正規系
    • スキーマレス故のスペル間違え問題
    • 設計や管理が手間

第6章 CouchDB

  • スケールアップもダウンもできる
  • 様々な規模や難しさの問題空間に適している
  • JSON と REST ベースの典型的なドキュメント指向データベース
  • ウェブとそれに関する膨大な不備・欠陥・障害・問題を念頭に置いて設計されたもの
  • 他DBとは比べものにならないほどの堅牢性
  • ほとんど接続がなくても平気
  • 様々な開発シナリオをサポートしている
  • シャットダウンするにはプロセスを殺すしかない
  • データが破損することがほとんどない
  • ストレージと通信用に JSON を使っている
  • 呼出は REST インターフェイス経由
  • レプリケーションは一方向または双方向
  • データの構造・保護・分散における柔軟性が高い
  • 寝心地のいい Futon
  • 一時的なビューは開発用途のみ使用すべき
  • プロダクション環境ではデザインドキュメントに mapreduce 関数を保存してビューを永続化
  • マルチマスター
  • コンフリクトの解消
    • ドキュメントをマージするのはアプリケーション固有の問題
  • CouchDB の強み
    • 堅牢で安定した NoSQL DB
    • データストレージに分散化の手法が採用されている
    • データベースでありAPIである
    • of the Web, for the Web
  • CouchDB の弱み
    • RDB のようなデータのスライシングはできない
    • レプリケーションのやり方が常に正しい選択というわけではない
      • オールオアナッシング
    • データセンターに分散するシャーディングはない

Effective Ruby

www.shoeisha.co.jp

第5章、メタプログラミング
正直、理解もそうだが、使いどころも難しい。あとでわからなくなりそう。

こっちを読んで学んだ方が良いかも。

メタプログラミングRuby 第2版

メタプログラミングRuby 第2版

第一版しか読んでないけど。

Refinements については、前田さんの言うとおりになっていればこのようには言われていなかったであろう。
以下はその前田さんによる記事。

Rubyist Magazine - Refinementsとは何だったのか

carrierwave で新規ファイル保存

github.com

github.com

ファイルをアップロードするのではなく、例えばサーバ側で rubyXL を用いて新規ファイルを作ってそれを carrierwave の仕組み上で管理したい。

carrierwave 用に mount_uploader した変数に ActionDispatch::Http::UploadedFile を渡せば良いのだろうけど、やり方がわからない。

ActionDispatch::Http::UploadedFile

rubyXL で新規にデータを作った場合はまだファイルになっていない。
StringIOの状態。

そこで、ささたつさんのサイトに答えが。よくこんなのわかるなぁ。すごい。

blog.livedoor.jp

tempfile を作って、ActionDispatch::Http::UploadedFile インスタンスを渡せばよい。
tempfile を作るときに、carrierwave 側で拡張子で制限を行っている場合は new の際の第一引数配列の二つ目が suffix なので、拡張子を指定すること。

singleton method Tempfile.new (Ruby 2.2.0)