There's an echo in my head

日々のメモ。

素のオブジェクトをfields_forに使う

例えばモデル的にGraph has_many Entityだけど、GraphはActiveRecordを使う一方でEntityには素のオブジェクトを使いたい場合。データストアが異なるとか。

class Graph < ActiveRecord::Base
  after_save :save_entities

  def entities
    @entities ||= [] # TODO: entitiesを読み込む
  end

  def entities_attributes=(attributes)
    # attributes = { "0" => { "name" => "foo", "body" => "bar" }, ... }
    @entities = attributes.map do |i, (attrs)|
      Entity.new(attrs)
    end
  end

  private

    def save_entities
      # TODO: entitiesを保存する処理
    end
end

class Entity
  include ActiveModel::Model

  attr_accessor :name, :body
end

class GraphsController < ActionController::Base
  def new
    @graph = Graph.new
    # 初回表示用にEntityをいくつか初期化
    @graph.entities << Entity.new
    @graph.entities << Entity.new
  end

  def create
    @graph = Graph.new(graph_params)
    @graph.save!
  end

  private

    def graph_params
      params.require(:graph).permit(
        :title,
        entities_attributes: [:name, :body]
      )
    end
end
# new.html.slim
= form_for @graph do |f|
  = f.text_field :title

  = f.fields_for :entities do |g|
    = g.text_field :name
    = g.text_area :body

  = f.submit

キモはentities_attributes=が定義してあること。これがあるかどうかでfields_forの挙動が変わる。

こんな雰囲気。端書きなので間違ってるかも。

reactのチュートリアルを触ってみた

ここ最近ほとんどフロントエンドを触ってなかったのでFacebookのreactのチュートリアルを試しに触ってみた。

a2ikm/react-tutorial

  • コンポーネントってそういうことかー
  • JSX、最初は違和感あったけど、記述量が減るし慣れれば気にならなくなる
  • 規模が大きくなるとわからないけど、この程度なら見通しよさそう
    • propsで深く値を引き回すようだと大変になりそう

sorceryを使ったログインのテストをするときはupdate_attributesを使うこと

sorcery v0.9.0からソルトの生成とパスワードの暗号化の処理がbefore_saveからbefore_validationに移された。この影響で、テストのためにログインパスワードを上書きするときにupdate_attributeを使っているとログインできずにテストが落ちるようになった。

これはupdate_attributeがバリデーションをスキップするためにbefore_validationのフックが発火されないためだ。

対策としてはupdate_attributesもしくはupdate_attributes!を使えばいい。

module AuthenticationForFeatureRequest
  def login user, password = 'login'
    user.update_attributes password: password

    page.driver.post sessions_url, {email: user.email, password: password}
    visit root_url
  end
end

wikiのほうも更新しておいた

Ruby 2.2.0でsafe_yamlを使うときはv1.0.4以上が必要

Ruby 2.2.0を使っていて次のようなエラーが起きたらsafe_yaml(webmockなどが依存)がv1.0.4未満になっていないか確認、なっていたらv1.0.4以上に上げる。

NoMethodError: undefined method `tagged_classes' for Psych:Module

結城浩「新版暗号技術入門 秘密の国のアリス」を読んでる

新版暗号技術入門 秘密の国のアリス

新版暗号技術入門 秘密の国のアリス

すごくわかりやすいし面白い。

  • 共通鍵暗号
    • 事前に共有しておいた秘密鍵を使って暗号化・復号化する方式
    • 今のところAES-256-CBCが安全
      • AES(やDES)は固定長のブロックを暗号化するための技術
        • ブロック暗号という
        • ストリーム暗号
      • CBCやCTRは自由長のバイト列をブロックに分割してブロック暗号に渡す方法。モード
        • CBCは前ブロックの結果(最初は初期化ベクトル)を対象のブロックにXORしてから暗号化する
          • 並列処理はできない
          • 最後のブロックはそれ以前の全てのブロックの影響を受けるので、最後のブロックだけ切り取ってMACに使うことができる
        • CTRはnonceをもとに作ったカウンタをブロックごとにインクリメントして暗号化し、ブロックとXORをとる
          • ブロックごとの並列処理ができる
          • ブロックごとの暗号化は独立しているのでCBCのようにMACには使えない
  • 公開鍵暗号の仕組み
    • 公開鍵暗号は公開鍵で暗号化したものはそれと対になるプライベート鍵でのみ復号化できるという方式
    • RSA公開鍵暗号アルゴリズムのひとつ
      • デジタル署名にRSAが使えるのは、それが上記と逆にプライベート鍵で暗号化したものを公開鍵で復号化できるから
      • 公開鍵暗号アルゴリズムであってもデジタル署名に使えるとは限らない
  • 共通鍵暗号公開鍵暗号の使い分け
    • 共通鍵暗号は速いけど事前に相手に秘密鍵を安全に共有しておく必要がある
    • 公開鍵暗号は遅いけど公開鍵だけを相手に渡しておけばよく、これは他者に漏れても構わない
      • プライベート鍵さえ漏れなければ良い
    • 長い秘密のメッセージを送りたい場合には、そのセッション用の秘密鍵を生成し、それでメッセージを暗号化する。そしてセッション秘密鍵を相手の公開鍵で暗号化してセットで送れば、相手はそれと対になるプライベート鍵でセッション秘密鍵を復号化し、さらにメッセージを復号化できる
  • 暗号化で守れないもの
    • 暗号化はあくまでデータを他人に見られないようにするための技術
    • 通信経路での改ざんは行われなかったのかという正真性の検証にはハッシュを使う(MD5SHA-1、SHA-2(SHA-256など)、最近はSHA-3をコンペするとか)
    • そもそも本当に本人が送ってきたものなのか、また第三者がみてどうやってそれを判断するかという認証にはメッセージ認証コード(MAC)やデジタル署名を使う

などなど。デジタル署名あたりまで読み終えたけど、SSL/TLSはまだまだこれから。

素数をもとにしたRSAが解けるかどうかは素因数分解を高速に解けるかどうかにかかっていて、P≠NP問題が暗号につながるのはこれかーとか。楕円曲線暗号ってなんだろうなーとか。AESはオープンなコンペ方式で専門家が穴をつつきまくった結果負けなかったアルゴリズムであるとか。

やあ、楽しいですね。

OSXでmysqlが"Too many open files in system”を起こした時の対処

10.7あたりからパーティションを切っていると頻発するようになっていて、最近ようやく対処方法が分かった。

3つのファイルに次のような設定をしたのちMacを再起動する。

/etc/sysctl.conf:

kern.maxfiles=20480 
kern.maxfilesperproc=18000

/etc/launchd.conf:

limit maxfiles 8192 20480
limit maxproc 1000 2000

/etc/profile:

ulimit -n 4096

参考

GuardでEnterを打ったときに全プラグインが実行されないようにする

$HOME/.guardrcもしくはGuardfileと同じディレクトリの.guardrcに次のように追記する。

Pry.commands.delete(/^$/)

プラグインを実行するにはaallを入力すればよい。

このブログに出てくるコードスニペッツは、引用あるいは断りがない限りMITライセンスです。