I have a problem with the way I'm currently propagating the object id
from the current view to child objects. Right now, I'm doing this:
# properties_controller.rb
def show
@property = Property.find(params[:id])
session[:property] = params[:id]
# snipped for brevity
end
# notes_controller.rb
def create
@note = Note.new(params[:note])
@note.property_id = session[:property]
# snipped for brevity
end
This populates the foreign key in the note with the parent object's id.
This works so far as it goes, but there's a problem here. Basically, if
more than one browser window is open at a time, then the
@note.property_id is set to whatever window was opened last, rather than
the using the id from the property view that linked to the create
action. This can result in notes being assigned to the wrong
property--ugh!
How can I *safely* propagate the property.id to note.property_id if I'm
not using a nested form? I don't want to pass it as a hidden form field
(vulnerable to tampering by the client), and I can't necessarily trust
request.referer either, except possibly to validate whether the session
value matches the referer.
I can't be the first person to encounter this sort of issue. What is a
good rails-centric way of doing this securely?
Assuming your associations are kosher and notes are never created
without a parent property, I'd rely on Rails Magic(tm) do the note
create via the Property model and leave the session alone altogether:
notes_controller:
def create
@note = Property.find(params[:id]).notes.create(params[:note])
...
end
Once you're back in the view, you can still get the property via the
reflexive association in @note via @note.property
I'm not sure I'm following this. If I follow a link from a property
view:
<%= link_to 'New note', new_note_path %>
how is Property.find(params[:id]).notes.create(params[:note]) going to
find @Property? I don't really understand how that's getting passed
along via params here.
how is Property.find(params[:id]).notes.create(params[:note]) going to
find @Property? I don't really understand how that's getting passed
along via params here.
You need to, by one method or another, carry around the id of the
property that the note should be added to. One way of this is by using
nested routes/resources where your urls would be
/properties/123/notes/new
or
/properties/123/notes (for the create action)
(and obviously the corresponding route helpers take a property as an
argument) The id of the property ends up in your parameters as params
[:property_id].
If you don't use nested routes then it's up to you to tack the
property_id on by a method of your choice (add it to the path, use a
hidden field etc.)
respond_to do |format|
if @note.save
flash[:notice] = 'Note was successfully created.'
format.html { redirect_to property_path @note.property_id }
else
format.html { render :action => "new" }
end
end
end
So, something is still not quite right. How is @note supposed to get the
property id from params here?