JSONをHTML/CSSで表現する
突然JSONをHTML/CSSでいい感じに表現したくなったのでやってみた。
例
<div class="json"> <div class="js-value js-object"> <div class="element"> <div class="js-key">key1</div> <div class="js-value js-string">value1</div> </div> <div class="element"> <div class="js-key">key2</div> <div class="js-value js-object"> <div class="element"> <div class="js-key">key3</div> <div class="js-value js-number">12345</div> </div> <div class="element"> <div class="js-key">key4</div> <div class="js-value js-array"> <div class="element"> <div class="js-value js-string">A</div> </div> <div class="element"> <div class="js-value js-string">B</div> </div> <div class="element"> <div class="js-value js-number">3</div> </div> <div class="element"> <div class="js-value js-object"> <div class="element"> <div class="js-key">fuga</div> <div class="js-value js-number">12345</div> </div> <div class="element"> <div class="js-key">hoge</div> <div class="js-value js-number">12345</div> </div> </div> </div> <div class="element"> <div class="js-value js-string">4</div> </div> </div> </div> <div class="element"> <div class="js-key">key6</div> <div class="js-value js-string">めっちゃ長い文字列ABCDEFGめっちゃ長い文字列ABCDEFGめっちゃ長い文字列ABCDEFGめっちゃ長い文字列ABCDEFG</div> </div> </div> </div> </div> </div>
表示結果
解説
箇条書きで簡潔に
- 1つの要素は<div class="element">で表現している
- キーは<div class="js-key">, 値は<div class="js-value 型の名前">で表現。型の名前は以下の通り
- js-string ... 文字列型
- js-number ... 数値型
- js-boolean ... 真偽型
- js-array ... 配列
- js-object ... オブジェクト
- js-nullを忘れてた…(あとでやる)
ここがすごいの
CSSのafter, before要素を使ってるので「"」や「,」「{」「[」をつけなくてもいい
誰が得するの?
...
UnicornでUnix domain socketを使う場合は絶対パスで指定しなければならない
listen 8080 # TCP listen "tmp/unicorn.sock" # Unix Domain Socketのつもり
と指定するとそんなListenの方法ないよー、と怒られた
I, [2013-06-26T09:22:21.178723 #11457] INFO -- : listening on addr=0.0.0.0:8080 fd=8 F, [2013-06-26T09:22:21.179525 #11457] FATAL -- : error adding listener addr=tmp/unicorn.sock /u/apps/..../gems/unicorn-4.6.2/lib/unicorn/socket_helper.rb:149:in `bind_listen': Don't know how to bind: tmp/unicorn.sock (ArgumentError)
Unicornのソースコード
https://github.com/schneems/unicorn/blob/master/lib/unicorn/socket_helper.rb
def bind_listen(address = '0.0.0.0:8080', opt = {}) return address unless String === address sock = if address[0] == ?/ if File.exist?(address) if File.socket?(address) begin UNIXSocket.new(address).close
1文字目がスラッシュからはじまってるかどうかで判定してるんですね...そうですか...
つまり、絶対パスじゃないと無理
Githubからやってくるhookの内容メモ
Githubのhook
https://help.github.com/articles/post-receive-hooks
タグが作成され、pushされたときは
{ "ref": "refs/tags/testtag", "after": "a011d5d157f769b39b99d2c10333e936eeab6bed", "before": "0000000000000000000000000000000000000000", "created": true, "deleted": false, "forced": true, "base_ref": "refs/heads/master", "compare": "https://github.com/mashijp/gitstudy/compare/testtag", "commits": [ ], "head_commit": { "id": "a011d5d157f769b39b99d2c10333e936eeab6bed", "distinct": true, "message": "delete", "timestamp": "2013-04-25T09:10:23-07:00", "url": "https://github.com/mashijp/gitstudy/commit/a011d5d157f769b39b99d2c10333e936eeab6bed", "author": { "name": "mashijp", "email": "(ry", "username": "mashijp" }, "committer": { "name": "mashijp", "email": "(ry", "username": "mashijp" }, "added": [ ], "removed": [ "fugahoge" ], "modified": [ ] }, "repository": { "id": 9674385, "name": "gitstudy", "url": "https://github.com/mashijp/gitstudy", "description": "", "watchers": 0, "stargazers": 0, "forks": 0, "fork": false, "size": 108, "owner": { "name": "mashijp", "email": "(ry" }, "private": false, "open_issues": 0, "has_issues": true, "has_downloads": true, "has_wiki": true, "created_at": 1366902142, "pushed_at": 1366906300, "master_branch": "master" }, "pusher": { "name": "mashijp", "email": "(ry" } }
ブランチがきられ、pushされたときは
{ "ref": "refs/heads/develop", "after": "0ce9e6e68576a18c073aaf6fadd5b93aef850811", "before": "0000000000000000000000000000000000000000", "created": true, "deleted": false, "forced": true, "compare": "https://github.com/mashijp/gitstudy/commit/0ce9e6e68576", "commits": [ { "id": "0ce9e6e68576a18c073aaf6fadd5b93aef850811", "distinct": true, "message": "doyaa", "timestamp": "2013-04-25T09:13:55-07:00", "url": "https://github.com/mashijp/gitstudy/commit/0ce9e6e68576a18c073aaf6fadd5b93aef850811", "author": { "name": "mashijp", "email": "(ry", "username": "mashijp" }, "committer": { "name": "mashijp", "email": "(ry", "username": "mashijp" }, "added": [ "pyo" ], "removed": [ ], "modified": [ ] } ], "head_commit": { "id": "0ce9e6e68576a18c073aaf6fadd5b93aef850811", "distinct": true, "message": "doyaa", "timestamp": "2013-04-25T09:13:55-07:00", "url": "https://github.com/mashijp/gitstudy/commit/0ce9e6e68576a18c073aaf6fadd5b93aef850811", "author": { "name": "mashijp", "email": "(ry", "username": "mashijp" }, "committer": { "name": "mashijp", "email": "(ry", "username": "mashijp" }, "added": [ "pyo" ], "removed": [ ], "modified": [ ] }, "repository": { "id": 9674385, "name": "gitstudy", "url": "https://github.com/mashijp/gitstudy", "description": "", "watchers": 0, "stargazers": 0, "forks": 0, "fork": false, "size": 108, "owner": { "name": "mashijp", "email": "(ry" }, "private": false, "open_issues": 0, "has_issues": true, "has_downloads": true, "has_wiki": true, "created_at": 1366902142, "pushed_at": 1366906447, "master_branch": "master" }, "pusher": { "name": "mashijp", "email": "(ry" } }
こんな通知がきたよ。というメモ。
"created": true が来たら新しいタグ or ブランチ作成かな?
Railsのprotect_from_forgeryは必ずしも外部からのリクエストから守ってくれない
Railsお勉強中。ためしにログイン不要な掲示板作ってる
https://github.com/mashijp/railsboard
外部からトピック作成やレス作成をできないように対策することを「CSRF対策」っていうのかと思っていたが、ログイン前提じゃないとCSRFじゃないらしい…知らんかった…。Railsのprotect_from_forgeryはトークンのない更新系アクセスがあった場合セッションを消すだけなので、ログイン不要なサイトだと意味がない(警視庁等の通報ページも同様)。
※詳しくは» Rails3のprotect_from_forgeryはトークンの検証NGの場合にreset_sessionする TECHSCORE BLOGを参照
どうしようかなと頭を抱えていたけど、Railsのソースコード(request_forgery_protection.rb)読んでたら簡単にオーバーライドできることが判明
# This is the method that defines the application behavior when a request is found to be unverified. # By default, \Rails resets the session when it finds an unverified request. def handle_unverified_request reset_session end
ということでoverrideしました!
class ApplicationController < ActionController::Base protect_from_forgery protected def handle_unverified_request raise Exception("なんやこれ") end end
https://github.com/mashijp/railsboard/commit/31d67c7803770219b8461a0266e46f76392f72b4
↑あとでまじめにやる
(タイトルは煽り)
Amazon CloudFrontを使ってみた
Amazon CloudFrontってなに
http://aws.amazon.com/jp/cloudfront/
(語弊がありそうだけど)簡単に書くとキャッシュサーバ。
配信サーバ(Originと呼ばれる)のデータをキャッシュし、クライアントに効率的に配信する。日本やアメリカ、ヨーロッパなどにサーバがあり、クライアントの地理的条件に応じて使用するサーバを選択するので、レイテンシも小さい。
作成の仕方
アカウント登録した後は超カンタンだった!(といってもそのアカウント登録に時間がかかったんだけど…)
1. Account ConsoleのCloudFrontにアクセス
Create Distributionを押すと次の画面がでてくる
今回は静的ファイルを配信したいのでDownloadを選択。
2. Originサーバの設定をする
配信元のドメイン名をOrigin Domainに入力。
3. (必要なら)CNAMEの設定もする
標準だと"fugahogefuga.cloudfront.net"のようなドメイン名がふられるのだが、自分のドメイン名に設定することができる。
やりたいならCNAMEに"example.mashijp.net"等を追加。
これで終わり。簡単。(CNAME設定したい場合は、作成後ドメイン名がふられるのでそれに対するCNAMEレコードを追加する)
料金は?
http://aws.amazon.com/jp/cloudfront/pricing/ にも書かれている通り、リクエスト数・転送量に応じた従量課金制。つまり、青天井です。DoSられるといくらでも料金がかかるのではという不安が常に押し寄せます。
何に使うの?
静的ファイル配信に便利なんじゃないかなあ、と思ったり。急激にアクセスが来た場合(or 見込まれる場合)は使うと良さそう。
Play Framework 2.1のちょっとした新機能
実はPlay Framework 2.0.xのFormでは同じフィールド名で複数値を受け取ることができない。
<input type="checkbox" name="name" value="value1"> <input type="checkbox" name="name" value="value2"> <input type="checkbox" name="name" value="value3">
例えば、上のようなフォームがあったとして、全てにチェックを入れても一つしか値は格納されない(多分name=value3しか入らない。もしかしたらvalue1かも)。
正確に書くと、request.body.asFormUrlEncodedの時点ではMap[String, Seq[String]]としてちゃんと格納されているのでこれを直接参照すれば"(name -> Seq(value1, value2, value3))"が得られるのだが、form.bindFromRequest()した瞬間に内部的にMap[String, String]に変換され、(name -> value3)となってしまう…。
POSTパラメータ | name=value1&name=value2&name=value3 |
---|---|
request.body.asFormUrlEncoded | Map(name -> Seq(value1, value2, value3)) |
bindFromRequestした際の内部的なデータ | Map(name -> value3) |
一応、以下のようにフィールド名に"[番号]"をつけてあげれば複数の値を取得することができる。
<input type="checkbox" name="name[0]" value="value1"> <input type="checkbox" name="name[1]" value="value2"> <input type="checkbox" name="name[2]" value="value3">
コントローラ側の例
case class AddForm(val name: List[String]) val addForm = Form( mapping( "name" -> list(text) )(AddForm.apply)(AddForm.unapply) )
チェックボックスならこれで解決だが、複数選択可能なセレクトボックス(multiple要素をつけたselect)だとお手上げ。(どう転んでもnameは1つしか指定できないので)
しかし、Play Framework 2.1はこれが改善されており、末尾が"[]"で終わるフィールド名は自動的にname[0], name[1]に変換されるようになった!
POSTパラメータ | name=value1&name=value2&name=value3 |
---|---|
request.body.asFormUrlEncoded | Map(name -> Seq(value1, value2, value3)) |
bindFromRequestした際の内部的なデータ | Map(name[0] -> value1, name[1] -> value2, name[2] ->value3) |
↑こんな感じに保存されてる
これで、mappingのlistが使い物になる!やったー (2.0.xでもやってほしい…)