What is the proper way to set strong parameters in a Rails controller and using validators with them? I've seen several examples of doing this several different ways.
This is what a typical controller def looks like for me:
# User model
class User < ActiveRecord::Base
validates :first_name, length: { in: 2..50 }, format: { with: /[a-zA-Z0-9\s\-\']*/ }
validates :last_name, length: { in: 2..50 }, format: { with: /[a-zA-Z0-9\s\-\']*/ }
validates :email, presence: true, length: { 5..100 }, format: { with: /**email regex**/ }, uniqueness: { case_sensitive: false }
end
# Controller def
def valid_email
# Strong parameters defined here? When is an error thrown for unmatched requires/permits?
params.require(:user)
params[:user].permit(:email)
# How to prevent blank params[:user][:email] from making unnecessary database call if it's blank?
@user = User.find_by(email: params[:user][:email])
unless @user.nil?
# Should work because in permit whitelist?
@user.assign_attributes(email: params[:user][:email])
# Should not work because not in permit whitelist?
@user.assign_attributes(first_name: params[:user][:first_name])
# Should work just sending to private def
@user.assign_attributes(savable_params)
# Validate entire model
if @user.valid?
@user.save
end
end
rescue => e
log_error(e)
render text: "Something bad happened. Contact support.", status: :unprocessed_entity
end
private def savable_params
params.require(:user).permit(:email)
end
How I understand it, is the params.require and params.permit allow for whitelisting of data passed to the controller/action, but doesn't keep "other" data from being seen in the params list (if it's passed).
So, leads into a few questions:
Thanks again.
So this is updating an existing user?
Just do - assuming for some reason you are not sending a user id as part of your submission:
not_found if params[:user].blank? or params[:user][:email].blank?
@user = User.find_by email: params[:user][:email] or not_found
@user.update savable_params
if @user.valid?
flash.notice = "All good"
redirect_to @user
else
# this has not been saved
flash.now.alert = @user.errors.full_messages.to_sentence
render :(whatever you call to display the form in the first place
end
and add to your application_controller:
def not_found
raise ActionController::RoutingError.new('Not Found')
end
to your questions:
I added a line for that - should work, but normally you're sending up and id of the user, so it's not something I've done. I don't bother testing it.
The validation happens on the update,. it won't hit the db unless it passes, it's a few cycles, not something I've ever worried about. You could put another pre-validation in there, to save on the db roundtrip, but if your going to do that - why not put it on the html field, and save a server round trip.
oh, and I think you'll need:
params.require(:user).permit(:email, :first_name)
to get the other field to update.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.