Passing ID Value to a Controller, Getting Mass Assignment Security Error
-
02-06-2021 - |
题
I have a message model and a user model. my message belongs_to
my user and user has_many
messages.
I'm trying to allow a user to private message another user while on their public profile page (their show template). I have tried a number of attempts, but I ultimately run back into the issue of requiring an ID to be attr_accessible
(which I heard is bad to do). Am I doing something wrong?
My message model, I have :user_id
(which is the current user, aka a sending_from
ID), :to_id
, :content
.
When I'm looking at a users profile page, on the show template I have
<%= form_for([current_user, @message]) do |f| %>
<%= f.hidden_field :to_id, :value => @user.id %>
<div class="field">
<%= f.text_area :content, placeholder: "Send a private message..." %>
</div>
<%= f.submit "Post", class: "btn btn-large btn-primary" %>
<% end %>
In my user show action, I have
def show
@user = User.find(params[:id])
@microposts = @user.microposts.paginate(page: params[:page])
if user_signed_in?
@message = current_user.messages.build(params[:messages], to_id: @user.id)
end
end
when the form submits, it goes to my message create action
def create
@message = current_user.messages.build(params[:message])
redirect_to user_path(params[:message][:to_id])
end
However, I always get the error
`Can't mass-assign protected attributes: to_id`
It seems like I can fix it by making :to_id attr_accessible
, however I have heard it is not very safe to do so. Am I doing something wrong? This issue has been killing me.
Any help would be appreciated. Thanks
解决方案
Making to_id
accessible is fine. But if you don't want that error just fix it like this:
def create
@message = current_user.messages.build
@message.to_id = params[:message][:to_id]
# manually assign whatever other params you need to
redirect_to user_path(params[:message][:to_id])
end
Mass assignment just means you can't use update_attributes
, you can still use model.attribute=
. The reason for doing it that way might be to add additional whitelisting parameters, such as:
def create
safe_params = params[:model].slice(:safe_attr1,:safe_attr2)
@model = Model.new(safe_params)
whitelist = ['some_safe_string','another_safe_string']
if whitelist.include?(params[:model][:dangerous])
@model.dangerous_attribute = params[:model][:dangerous]
end
@model.save
redirect_to @model
end