学習メモです。
#Strong_Parametersとは?
Rails4.0以降ではコントローラ層で、Strong Parametersを使うことで、必須のパラメータと許可されたパラメータを指定できる。さらに、paramsハッシュをまるごと渡すとエラーが発生するので、Railsはデフォルトでマスアサインメントの脆弱性から守られる。
###マスアサインメント(mass assignment)とは?
次のように値のハッシュを使ってRubyの変数を初期化すること。
@user = User.new(params[:user]) # 上記にあるようにRailsはこれをデフォルトでエラーにする
#####上記では、ユーザーが送信したデータを丸ごと受け取っているが、Userモデルに管理者の権限としてのadmin属性というものがあるとすると、送信したデータにadmin属性がtrueになる情報を簡単に紛れさせることができ、管理者権限を渡してしまうことになるのは危険!これがマスアサインメントの脆弱性!
###user_paramsについて
今回のparamsハッシュでは:user属性を必須とし、名前、メールアドレス、重症度、パスワード、パスワードの確認の属性をそれぞれ許可し、それ以外を許可しないようにしたい。
params.require(:user).permit(:name, :email, :seriousness, :password,
:password_confirmation)
このコードの戻り値は、許可された属性のみが含まれたparamsのハッシュ(:user属性がない場合はエラーに)。
これらのパラメータを使いやすくするために、user_paramsという外部メソッドを使うのが慣習に。このメソッドは適切に初期化したハッシュを返し、params[:user]の代わりとして使われる。
####ここまではRailstutorialで学んだことのまとめです。
#解決したい問題その1
##require(:user)
があるとエラーが発生する
private
def user_params
params.require(:user).permit(:name, :email, :seriousness, :password,
:password_confirmation)
end
param is missing or the value is empty
paramが見当たらないとのこと。
<!-- some long code --!>
<%= form_with model: @users, local: true do |f| %>
<div class="form-group">
<%= f.label :name, "ユーザー名" %>
<%= f.text_field :name, class:"form-control",
value: @name, required: true, autofocus: true %>
</div>
<!-- some long code --!>
###form_withの使い方
モデルを渡したときは、URLとスコープが自動推測される。
URL: @user
がDBに存在するときはupdateアクションに、ないときはcreateアクションに飛ぶ。
今回は存在しないため、createアクションに飛ぶ。
スコープ: params[:email]
が params[:user][:email]
に。
def new
@user = User.new
end
#####モデルは@user
だが、そうするとエラーが起きる。@users
だとエラーが起きない
undefined method `users_path' for #<# <Class:0x00007f9d8198ba18>:0x00007f9d81989178>
Did you mean? user_path
#####require(:user)
を削除すると、エラーは消えた!
#####けれども、Strong Parametersを使いたいのにそれだと意味がない!!
#解決したい問題その2
##require(:user)
を実装してのユーザー新規登録test通過
上記だと、エラーは起きなくてもtestで失敗する...
test "valid signup information" do
get signup_path
assert_difference "User.count",1 do
post signup_path, params: { user: { name: "Example",
email: "user@example.com",
password: "password",
password_confirmation: "password" } }
end
follow_redirect!
assert_template "users/show"
assert_not flash.blank?
end
FAIL["test_valid_signup_information", #<Minitest::Reporters::Suite:0x00007f958a263640 @name="UsersSignupTest">, 0.5420669997110963]
test_valid_signup_information#UsersSignupTest (0.54s)
"User.count" didn't change by 1.
Expected: 1
Actual: 0
test/integration/users_signup_test.rb:20:in `block in <class:UsersSignupTest>'
2/2: [=========================] 100% Time: 00:00:00, Time: 00:00:00
Finished in 0.58615s
####モデルが@users
だと自動推測が上手くいかず、スコープ: params[:email]
が params[:user][:email]
となっていないのかも!なので、 @users
を@user
に変更する!
###users_path
が存在しないエラーだったので、Routingの問題っぽい
<!-- some long code --!>
post "users/:id/update", to: "users#update"
get "users/:id/edit", to: "users#edit", as: :edit
post "signup", to: "users#create"
get "signup", to: "users#new"
get "index", to: "users#index"
get "users/:id", to: "users#show", as: :user
<!-- some long code --!>
rails routes
<!-- some long code --!>
users#update POST /users/:id/update(.:format)
users#edit edit GET /users/:id/edit(.:format)
users#create signup POST /signup(.:format)
users#new GET /signup(.:format)
users#index index GET /index(.:format)
users#show user GET /users/:id(.:format)
<!-- some long code --!>
いろいろ試してた時に作った名前付きルートas: :user
が怪しい。
as: :users
にしてもいいが、後々問題になりそうなので、resources: users
で対応してみる。
+ resources :users
<!-- some long code --!>
- post "users/:id/update", to: "users#update"
- get "users/:id/edit", to: "users#edit", as: :edit
- post "signup", to: "users#create"
- get "signup", to: "users#new"
- get "index", to: "users#index"
- get "users/:id", to: "users#show", as: :user
<!-- some long code --!>
rails routes
<!-- some long code --!>
users#update POST /users/:id/update(.:format)
users#edit edit GET /users/:id/edit(.:format)
users#create signup POST /signup(.:format)
users#new GET /signup(.:format)
users#index index GET /index(.:format)
users#show GET /users/:id(.:format)
<!-- some long code --!>
#####これでモデルを@user
にしても、エラーは起きなくなった!
#####また、スコープが:user
で認識されるようになり、require(:user)
を加えてのテストも通過し、StrongParametersが適応されたユーザーの新規登録ができるように!
###まとめ
Strong_Parametersよく分からなかったけど、躓いたことによって、form_withとroutingについても学べたのでよしとする!