Question

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

Était-ce utile?

La solution

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
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top