Mashの罠にハマる

以下のような感じのhamlを書いてサーバでjsonデータを受け取ろうとしたけど

    %tr#new_task
      = fields_for @task do
        %td= text_field :title
        %td= text_field :priority
        %td= text_field :status
        %td= text_field :due_at
      %td
      %td

= link_to 'New', url(:new_task), :id => 'new_task_link'

- throw_content :js do
  :javascript
    $(function(){
      $('#new_task_link').click(function(){
        $.ajax({
          type: 'POST',
          url: '#{url :tasks}',
          data: $(':input', '#new_task').serializeArray(),
          dataType: 'json'
        });
        return false;
      });
    });

JSON.parseがエラーになるので以下のようにしてデバッガで調べてみた。

  def create
    debugger
    # エラーになる。
    JSON.parse(request.raw_post)
    # 略
  end

ちなみにデバッガ使うときはmerb -Dで立ち上げる。で、見てみたんだけど…

merb : worker (port 4000) ~ Started request handling: Sat Jan 24 23:22:27 +0900 2009
merb : worker (port 4000) ~ Routed to: {"format"=>nil, "action"=>"create", "task"=>{"title"=>"test", "priority"=>"4", "status"=>"new", "due_at"=>"2009-01-27"}, "controller"=>"tasks"}
merb : worker (port 4000) ~ Params: {"format"=>nil, "action"=>"create", "task"=>{"title"=>"test", "priority"=>"4", "status"=>"new", "due_at"=>"2009-01-27"}, "controller"=>"tasks"}
merb : worker (port 4000) ~ In repository block default
/home/maedana/local/repos/private/git/gom/app/controllers/tasks.rb:32
JSON.parse(request.raw_post)
    (rdb:14) p request.raw_post
    "task%5Btitle%5D=test&task%5Bpriority%5D=4&task%5Bstatus%5D=new&task%5Bdue_at%5D=2009-01-27"
    (rdb:14) p params
{"format"=>nil, "action"=>"create", "task"=>{"title"=>"test", "priority"=>"4", "status"=>"new", "due_at"=>"2009-01-27"}, "controller"=>"tasks"}
(rdb:14) p params['task']
{"title"=>"test", "priority"=>"4", "status"=>"new", "due_at"=>"2009-01-27"}

ああ、params['task']が勝手にHashになってるんだー、便利ーとか思って何気なく.classしたら

(rdb:14) p params['task'].class
Mash

ま、マッシュ?? Hashじゃないの!??と思ってググったら http://wota.jp/ac/?date=20081202#p03 を発見。へー、そんなのあるのねー。

そんなわけでjsonで送ると勝手にMashになってるのでわざわざJSON.parseとかしなくても

(rdb:14) Task.new(params[:task])
#<Task id=nil title="test" priority=4 status="new" due_at=#<DateTime: 4909717/2,0,2299161> complete_at=nil created_user_id=nil created_at=nil updated_at=nil user_id=nil>

するだけでいいということがわかった。