Rails4でトークン認証のアクションに対してCSRFを無効にする
Railsはprotect_from_forgeryって書くだけでCSRF対策が有効になってマジ便利なわけだけど、セッションで認証するんじゃなくてiOSから呼ぶAPIとかでトークン使って認証する場合はCSRFの対策いらないので無効にしたい。
その場合は
protect_from_forgery with: :null_session
ってすればいいらしい。これはCSRF Tokenが一致しなかった場合に例外を投げるんじゃなくてセッションを空にするという動作になる。
ちなみにprotect_from_forgeryのデフォルトは:null_sessionなので
protect_from_forgery
でもよさそう(Rails 4.0.0現在)
ただし最初は以下のようになってるので明示的に変更する必要はある。
class ApplicationController < ActionController::Base # Prevent CSRF attacks by raising an exception. # For APIs, you may want to use :null_session instead. protect_from_forgery with: :exception end
RubyMotionでブロック中のblock_given?の値が変わる
これではまった。
https://gist.github.com/ainame/5651453
yieldも同じようにダメっぽい。
def callback_caller callback_caller2 do yield end end def callback_caller2(&block) block.call end callback_caller do p 'origin' end
# CRuby 1.9.3 $ ruby sample.rb "origin" # ruby motion 2.5 $ /Library/RubyMotion/bin/ruby sample.rb 2013-07-25 22:59:58.924 ruby[89777:707] /Users/hokamura/Works/tmp/sample.rb:3:in `block': no block given (LocalJumpError) from /Users/hokamura/Works/tmp/sample.rb:8:in `callback_caller2' from /Users/hokamura/Works/tmp/sample.rb:2:in `callback_caller' from /Users/hokamura/Works/tmp/sample.rb:11:in `<main>' /Users/hokamura/Works/tmp/sample.rb:3:in `block': no block given (LocalJumpError) from /Users/hokamura/Works/tmp/sample.rb:8:in `callback_caller2' from /Users/hokamura/Works/tmp/sample.rb:2:in `callback_caller' from /Users/hokamura/Works/tmp/sample.rb:11:in `<main>'
ちなみにcallback_caller2の処理をyieldにするとRubyMotionでもいける。
def callback_caller callback_caller2 do yield end end def callback_caller2 yield end callback_caller do p 'origin' end
# ruby motion 2.5 $ /Library/RubyMotion/bin/ruby sample.rb "origin"
うーむ・・。
delegateでclickイベントを拾う場合のtap-highlight-color
iOSとかでリンクをクリックするときにグレイにハイライトされるけど、clickイベントでも特定の条件を満たせばハイライトされる(対象の要素がリフローしない場合とかだった気がするけど詳しくは覚えてない)。
ハイライトされるのはいいとして、delegate次のようにイベント貼ったとして
<div class="box"> <span class="btn">click</span> </div>
$('.box').delegate('.btn', 'click', function() { console.log('clicked!'); });
.btnをクリックすると.boxの領域がハイライトされて嬉しくない。
ハイライト出さなくてよければCSSで
.box { -webkit-tap-highlight-color: rgba(0, 0, 0, 0); }
とか指定すればいいんだけど、ハイライトは出したいけどクリックされた要素にちゃんとハイライト出したいという場合はこれじゃダメなので、delegateせずに.btnにclickイベント貼ることでしか解決しないかな。
$('.box .btn').click(function() { console.log('clicked!'); });
Backbone.Viewのeventsとかだと全部delegateになるし、けっこう困る。
PostgreSQLでwhereの値にダブルクォートでエラる
Railsで以下のようなコード書いてて
entries.where('url != ""')
MySQLとSQLiteでは動いてたんだけどPostgreSQLに移行したらエラって動かなくなった。
MySQL uses ' or " to quote values (i.e. WHERE name = "John"). This is not the ANSI standard for databases. PostgreSQL uses only single quotes for this (i.e. WHERE name = 'John'). Double quotes are used to quote system identifiers; field names, table names, etc. (i.e. WHERE "last name" = 'Smith').
http://wiki.postgresql.org/wiki/Things_to_find_out_about_when_moving_from_MySQL_to_PostgreSQL
ということらしい。
とりあえずこれで直った。
entries.where("url != ''")
apt-get install node
apt-get install node
でインストールしたんですけどNode.jsが動きません!と言われてなんでかよくわからなかったんだけど、「node」だとこれが入るらしい
http://packages.ubuntu.com/lucid/hamradio/node
ただしくは
$ apt-get install nodejs
node のほうでもインストールは成功し、インストールされた node コマンド実行しても何も起きない(エラーすらでない)のでこれは知らないとはまる。
Node.jsでロードパスをプログラム内から追加する
その昔はrequire.pathsというのがあってプログラム内からロードパスを設定できたんだけど、いつしかrequire.pathsは廃止され、NODE_PATHで設定するしかなくなった。
でもNODE_PATHだとプログラムの中からロードパスを変更することができない。
// libにパスを通して./lib/foo.jsをrequire('foo')で読み込みたい process.env['NODE_PATH'] = __dirname + '/lib'; require('foo'); // Error
とやっても ./lib/foo.js は読み込めない。でも環境変数いちいち指定するのめんどいよ!ってこともある。
そこでソース読んでたらModule._initPathsってのを呼べばNODE_PATHを見てパスを再設定してくれそうだなーと思ってやってみたらできた。
process.env['NODE_PATH'] = __dirname + '/lib'; require('module')._initPaths(); require('foo'); // Success
現状の最新の安定バージョン(v0.10.7)で動くのを確認した。
ただしアンドキュメントだし全くもって正攻法ではないので使う場合はその辺をわかった上で使いましょう。むしろ使わないにこしたことはない。
RailsでModelからselectボックスをつくる
collection_selectを使うといい感じにできる。例えば、あるグループに所属しているユーザーをプルダウンで選択させたい場合はこんな感じ。
<%= f.collection_select :user_id, @group.users.all, :id, :name %>
ってやるとuser.idがoptionのvalue、user.nameがoptionの中身になる。結果はこんな感じ。
<select id="user_id" name="task[user_id]"> <option value="1">user1</option> <option value="2">user2</option> </select>
デフォルトのテキストも表示したい場合はinclude_blankオプションを設定する。
<%= f.collection_select :assigned_user_id, @group.users.all, :id, :name, include_blank: '選択してね!' %>