Proper user of strong parameters, assignments, and validators in Rails 4? -
what proper way set strong parameters in rails controller , using validators them? i've seen several examples of doing several different ways.
this typical controller def looks 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 error thrown unmatched requires/permits? params.require(:user) params[:user].permit(:email) # how prevent blank params[:user][:email] 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 sending 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 understand it, params.require , params.permit allow whitelisting of data passed controller/action, doesn't keep "other" data being seen in params list (if it's passed).
so, leads few questions:
- proper way of whitelisting in similar scenario top?
- how you, instance, make sure params[:user][:email] isn't blank ("") before trying user.find_by since know blank email isn't valid anyway , not want make unnecessary database call?
- user.valid? validate entire model, though i'm interested in :email attribute valid before doing user.find_by?
- if have uniqueness validator on email, instance, how keep uniqueness hitting database, if params[:user][:email] blank , we're interested in email isn't blank, fits within length, , matches format?
thanks again.
so updating existing user?
just - assuming reason not sending user id part of 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 # has not been saved flash.now.alert = @user.errors.full_messages.to_sentence render :(whatever call display form in first place end
and add application_controller:
def not_found raise actioncontroller::routingerror.new('not found') end
to questions:
- as per above. validators run on model, have logic, keep controllers simple.
i added line - should work, you're sending , id of user, it's not i've done. don't bother testing it.
the validation happens on update,. won't hit db unless passes, it's few cycles, not i've ever worried about. put pre-validation in there, save on db roundtrip, if going - why not put on html field, , save server round trip.
- put uniqueness constraint on model , db (the model should it, race conditions, db backstop). nothing hit db unless passes validations first, should rare.
oh, , think you'll need:
params.require(:user).permit(:email, :first_name)
to other field update.
Comments
Post a Comment