I have an app with the following relationships between models:
class ContentPartner < User
has_many :events, dependent: :destroy
has_many :videos, through: :events, dependent: :destroy
class Video
belongs_to :event
class Event
has_many :videos, dependent: :destroy
How can I create a new video so that it has the correct :event_id and :content_partner_id passed to it, without using nested resources (which I don't want) or creating a mass-assignement security issue by adding :event_id and :content_partner_id to the Video attr_accessible whitelist?
With my controller like this:
def create
@event = Event.find(params[:video][:event_id])
@video = @event.videos.create(params[:video])
if @video.save
flash[:success] = "Video uploaded!"
redirect_to session[:return_to]
else
flash[:error] = "#{@video.errors.messages}"
render new_video_path
end
end
and no hidden_field in my @videos form, I end up with the error "Couldn't find Event without an ID"
but with:
<%= f.hidden_field :event_id, value: @event.id %>
in my form, I get the error "Can't mass-assign protected attributes: event_id"
Is there a 3rd way to create a new video that belongs_to an event without using nested resources or compromising on mass assignments risks?
Well, you can change your hidden_field to:
<%= hidden_field_tag :event_id, @event.id %>
And now in your controller, you can access that variable with:
Event.find(params[:event_id])
This should circumvent the mass-assign error. However, now any malicious user can edit that hidden field and add a video to any event he wishes. To fix this, you should find the event through an association. So if you have a current_user
or current_content_partner
, you should find the event like this:
current_content_partner.events.find(params[:event_id])
Now, a user is only able to access events he owns.