くりにっき

フルスタックキュアエンジニアです

PadrinoでStrongParametersみたいなことをしたかった

Strong Parametersについて

params で受け取った値をホワイトリスト形式で制御するRails4からの機能です。*1

詳しいことは StrongParameters | TECHSCORE(テックスコア) を参照

最近Padrino使ってて同じことができないか調べてました(activerecord 4系を使いたかったので3系のMass Assignmentはスルー)

忙しい人のためのまとめ

Params Whitelisting:params はHashでネストできる

いろいろ試してみた

  • padrino 0.12.3 + activerecord 4.1.4 で検証
  • サンプルコードはいろいろはしょってます
  • 簡略化のためにPOSTされた時のparamsをjsonで表示してます
  • アプリ名は架空のものです

サンプル1

何もつけないとparamsには全部入ってくるので、そのままsaveしたりすると意図しないカラムも更新してしまう

Precure::App.controllers :precures do
  post :create do
    params.to_json
  end
end

describe "PrecuresController" do
  let(:params){
    {
      series: "Precure AllStars NewStage",
      girl: {
        id:           1,
        human_name:   "Ayumi Sakagami",
        precure_name: "Cure Echo",
        created_at:   "2014-09-10",
      }
    }
  }

  it "/precures/create" do
    post "/precures/create", params
    expect(last_response.body).to eq '{"series":"Precure AllStars NewStage","girl":{"id":"1","human_name":"Ayumi Sakagami","precure_name":"Cure Echo","created_at":"2014-09-10"}}'
  end
end

サンプル2

paramsにgirlだけ追加したらseriesはparamsに渡ってこないが、girlの中身は全部渡ってくる

Precure::App.controllers :precures do
  post :create, params: [:girl] do
    params.to_json
  end
end

describe "PrecuresController" do
  let(:params){
    {
      series: "Precure AllStars NewStage",
      girl: {
        id:           1,
        human_name:   "Ayumi Sakagami",
        precure_name: "Cure Echo",
        created_at:   "2014-09-10",
      }
    }
  }

  it "/precures/create" do
    post "/precures/create", params
    expect(last_response.body).to eq '{"girl":{"id":"1","human_name":"Ayumi Sakgami","precure_name":"Cure Echo","created_at":"2014-09-10"}}'
  end
end

サンプル3

params: [girl: [:human_name, :precure_name]] で渡してみると、actionにはidやcreated_atは渡ってこない

Precure::App.controllers :precures do
  post :create, params: [girl: [:human_name, :precure_name]] do
    params.to_json
  end
end

describe "PrecuresController" do
  let(:params){
    {
      series: "Precure AllStars NewStage",
      girl: {
        id:           1,
        human_name:   "Ayumi Sakagami",
        precure_name: "Cure Echo",
        created_at:   "2014-09-10",
      }
    }
  }

  it "/precures/create" do
    post "/precures/create", params
    expect(last_response.body).to eq '{"girl":{"human_name":"Ayumi Sakgami","precure_name":"Cure Echo"}}'
  end
end

サンプル4

ちなみにparamsはArrayだけでなくHashも受け取れるらしい

Precure::App.controllers :precures do
  post :create, params: {girl: [:human_name, :precure_name]} do
    params.to_json
  end
end

describe "PrecuresController" do
  let(:params){
    {
      series: "Precure AllStars NewStage",
      girl: {
        id:           1,
        human_name:   "Ayumi Sakagami",
        precure_name: "Cure Echo",
        created_at:   "2014-09-10",
      }
    }
  }

  it "/precures/create" do
    post "/precures/create", params
    expect(last_response.body).to eq '{"girl":{"human_name":"Ayumi Sakgami","precure_name":"Cure Echo"}}'
  end
end

調べた

RailsのStrongParametersはPadrinoではParamsProtectionと言うらしい

https://github.com/padrino/padrino-framework/blob/529cc9935f72891f0bc67812ab33c96a45febf07/padrino-core/lib/padrino-core/application/params_protection.rb

補足

サンプルコードは「新しいプリキュアを作る」ということをREST風に表現しています

*1:paramsで受け取ったのをそのままsaveやupdate出来るとセキュリティ的によろしくない