Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#Rails の Controller でネストした params を permit / require するのはメソッドチェーンじゃいかんともしがたいからメソッドを何度も実行するしかないのか? ( ActionController::Parameters ) #3045

Open
YumaInaura opened this issue Mar 22, 2020 · 0 comments

Comments

@YumaInaura
Copy link
Owner

  • require / permit / permit! の引数の受け取り方も、返り値も使い方もなんだか不揃いで、なんとも使いがたい
  • メソッドチェーンも使いづらくパラメータがネストされている時に permit / require しづらい
  • permit! は引数を受け取れず、破壊的に params を変えてしまう
  • require と permit を別々に実行して、頑張って組み立て直す必要があるかもしれない
  • 具体ケースとしては JSON リクエストを受け取った結果を Controller の params で扱っているのだが、Rails のもともとのフレームワークのレールからは外れる部分が多いのか、苦労がある。
# ネストした params
params = ActionController::Parameters.new(
  name: 'Alice',
  age: 22,
  contact: ActionController::Parameters.new(
    tel: 07011112222,
    email: 'user@example.com'
  )
)
# => <ActionController::Parameters {"name"=>"Alice", "age"=>22, "contact"=><ActionController::Parameters {"tel"=>941921426, "email"=>"user@example.com"} permitted: false>} permitted: false>


# require は必須パラメータチェックのためだけに利用して、返り値は使わない
params.require([:name, :age, :contact])
params[:contact].require([:tel, :email])

# permit する時はネストの構造に合わせた書き方をして、返り値を permit された params として利用する
peritted_params = params.permit(:name, :age, contact: [:tel, :email])
# => <ActionController::Parameters {"name"=>"Alice", "age"=>22, "contact"=><ActionController::Parameters {"tel"=>941921426, "email"=>"user@example.com"} permitted: true>} permitted: true>

僕はもう疲れたよ

image

公式

  • tap のブロックで頑張る方法が書かれていた
  • 結局 Action Controller Parameters は頼りに出来ない気がした
def person_params
  params.require(:person).permit(:name).tap do |person_params|
    person_params.require(:name) # SAFER
  end
end

ActionController::Parameters

example

# Execute with rails console

# Rails like Nested params with ActionController::Parameters instance
params = ActionController::Parameters.new(
  name: 'Alice',
  age: 22,
  contact: ActionController::Parameters.new(
    tel: 07011112222,
    email: 'user@example.com'
  )
)
# <ActionController::Parameters {"name"=>"Alice", "age"=>22, "contact"=><ActionController::Parameters {"tel"=>941921426, "email"=>"user@example.com"} permitted: false>} permitted: false>

# Ooops
# Args must be Array
params.require(:name, :age, :contact)
# ArgumentError: wrong number of arguments (given 3, expected 1)

# It works
params.require([:name, :age, :contact])
# => ["Alice", 22, <ActionController::Parameters {"tel"=>941921426, "email"=>"user@example.com"} permitted: false>]

# But with method chain
# How to permit multiple params Require and Permit ?

# require method returns values Array
# it is not work for generate permitted params
# because .permit .require both method does not change "params"
params.require([:name, :age, :contact])[2].permit(:tel, :email).require([:tel, :email])
# => [941921426, "user@example.com"]

# require method returns values Array
# Unable to use methods chain
params.require([:name, :age, :contact])[2].require([:tel, :email]).permit(:tel, :email)
# NoMethodError: undefined method `permit' for [941921426, "user@example.com"]:Array

# It is answer?
# User require and permit methods
# Without return values
# Without method chains
# 
# And last execute permit!

params.require([:name, :age, :contact])
params[:contact].require([:tel, :email])

peritted_params = params.permit(:name, :age, contact: [:tel, :email])
# <ActionController::Parameters {"name"=>"Alice", "age"=>22, "contact"=><ActionController::Parameters {"tel"=>941921426, "email"=>"user@example.com"} permitted: true>} permitted: true>

# OR
params.permit(:name, :age, contact: [:tel, :email])
params.permit!
params
# => <ActionController::Parameters {"name"=>"Alice", "age"=>22, "contact"=><ActionController::Parameters {"tel"=>941921426, "email"=>"user@example.com"} permitted: true>} permitted: true>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

1 participant