ビューから渡ってきた値をHoge::RegistrationsControllerで加工しようとした。 覚えてなくて再現もできないが、パラメータを再代入できなかったり、unpermitted paramterとなった。 ストロングパラメータ周りのコードを読めば何かわかるかもと思いコードを読んでみることにした。
テスト動かす
bin/test test/parameter_sanitizer_test.rb
devise/parameter_sanitizerは、ActionController::Parametersのラッパークラスってやつ?
test/parameter_sanitizer_test.rb:70~75を追いかけた。
# 70
sanitizer = begin
params = ActionController::Parameters.new('user' => { 'username' => 'jose' })
Devise::ParameterSanitizer.new(User, :user, params)
end
#71
sanitizer.permit(:sign_in) do |user|
user.permit(:username)
end
# sanitizer.instance_variable_get(:@permitted)[:sign_in] # => #<Proc:~~~devise/test/parameter_sanitizer_test.rb:71>
#75
sanitized = sanitizer.sanitize(:sign_in)
#lib/devise/parameter_sanitizer.rb:70#sanitize
# permissions = #<Proc:~~~devise/test/parameter_sanitizer_test.rb:71>
#lib/devise/parameter_sanitizer.rb:74
# cast_to_hash permissions.call(default_params)
# ->(user){user.permit(:username)}.call(#<ActionController::Parameters {"username"=>"jose"} permitted: false>)
# #<ActionController::Parameters {"username"=>"jose"} permitted: false>.permit(:user_name)
分かったことは、
Devise::ParameterSanitizerのインスタンスメソッドpermitに渡すブロックは、
Devise::ParameterSanitizerの初期化で渡した、
ActionController::Parametersインスタンスに対して実行されること。
動作確認していないが、以下のコードでコントローラ内で再代入できるんじゃないだろうか!?!?
sanitizer = begin
params = ActionController::Parameters.new('user' => { 'username' => 'jose' })
Devise::ParameterSanitizer.new(User, :user, params)
end
sanitizer.permit(:sign_in) do |params|
params['gender'] = params['username'] == 'jose' ? 'man' : 'woman'
params.permit(:username, :gender)
end
Devise::ParameterSanitizer#sanitizeは、<#ActionController::Parameters ~~ permitted: true >.to_hの結果を返すメソッド。 Devise::ParameterSanitizer#permitは、<#Devise::ParameterSanitizer @permitted={}>のpermitted[action]に値を追加するメソッド。
test/controllers/custom_registrations_controller_test.rbとtest/rails_app/app/controllers/custom/registrations_controller.rbとapp/controllers/devise/registrations_controller.rbを改造すれば動作確認できそうだ。