Propogating the current view's id to a child object

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?

In this case nested-routes may be a good choice.

Darian Shimy

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

-eric

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.

> notes_controller: > def create @note = > Property.find(params[:id]).notes.create(params[:note]) ... end

I'm not sure I'm following this. If I follow a link from a property view:

&lt;%= link\_to &#39;New note&#39;, new\_note\_path %&gt;

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.)

Fred

routes.rb:

map.resources :properties, :has_many => :notes

view:

<%= link_to 'New note', new_property_note_path(@property) %>

or however you're holding the property in the view, if not @property...

'rake routes' for more

-eric

I did that, and it works for views (e.g. "/properties/4/notes/2"). However, I get this error when I try to actually create a note:

    ActiveRecord::RecordNotFound in NotesController#create     Couldn't find Property without an ID

In my notes_controller.rb, I have:

  def new     @note = Note.new     respond_to do |format|       format.html     end   end

  def create     @note = Property.find(params[:id]).notes.create(params[:note])     @note.user_id = current_user.id

    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?

Check your params for the correct property id parameter.

-eric