I have made a resource.
resources :dashboards
I have a partial file which contains a form and I want to use this partial (as the form elements won’t change) to update and create. So here is what I have:
Controller
class DashboardsController < ApplicationController
def new
@dashboard = Dashboard.new
end
end
View
/dashboards/new.html.erb
<%= render :partial => "form", :locals => { :dashboard => @dashboard } %>
Partial Form
/dashboards/_form.html.erb
<%= form_for(@dashboard) do |form| %>
.....
<% end %>
Ruby Guide
The Ruby Guide states:
The Article model is directly available to users of the application, so — following the best practices for developing with Rails — you should declare it a resource. When dealing with RESTful resources, calls to form_for can get significantly easier if you rely on record identification. In short, you can just pass the model instance and have Rails figure out model name and the rest. For example:
## Creating a new article
# long-style:
form_for(@article, :url => articles_path)
# same thing, short-style (record identification gets used):
form_for(@article)
## Editing an existing article
# long-style:
form_for(@article, :url => article_path(@article), :html => { :method => "put" })
# short-style:
form_for(@article)
Result
I thought I have followed the Rails Guide correctly. Because I made @dashboard a resource. I could just pass it into the form and have it handle the action, method and the rest. Instead I’m getting this:
<form accept-charset="UTF-8" action="/dashboards" class="new_dashboard" id="new_dashboard_" method="post">
According to the docs. Shouldn’t the action of my form now be “/dashboards/new” because we are on the new action? And should it be passing an extra field declaring the method to be put when I use the same code in the /edit action??
My result is always the same no matter what. The form never changes.
What am I doing wrong?
EDIT
Here is my router info from rake routes
GET /dashboards(.:format) dashboards#index
POST /dashboards(.:format) dashboards#create
GET /dashboards/new(.:format) dashboards#new
GET /dashboards/:id/edit(.:format) dashboards#edit
GET /dashboards/:id(.:format) dashboards#show
PUT /dashboards/:id(.:format) dashboards#update
DELETE /dashboards/:id(.:format) dashboards#destroy
You are correct that you should be able to “pass
@dashboardinto the form and have it handle the action, method and the rest.” The issue here is whatnewis in the context of RESTful actions.When you declare a set of resources with
resources :dashboards, you are creating a set of routes which map requests to controller actions:You can check this if you run
rake routes.The issue here is that the
newaction is defined as aGETrequest to the path/dashboards/new, i.e. this is the route for the form itself. The URL in theactionattribute of the actual form is something else: this is where the form will post the data to with aPOSTrequest, which on the server (rails) side will map to thecreatecontroller action.When you use the form helper with
form_for(dashboard), a form is created with a route corresponding to whatdashboardis: if it is a new record (i.e. it does not yet exist in the database), then the form action will becreate(and point to/dashboards), whereas if it already exists it will point to the actual URL for the record (e.g./dashboards/123). This is what makes the form helpers so useful.So, to sum up,
/dashboardsis the correct URL, not for thenewaction but for thecreateaction, which the form helper uses becausedashboardis a new record.newis the route to the page where the form resides, i.e./dashboards/new.Hope that makes sense.
p.s. as a side note, you shouldn’t be accessing
@dashboardin the partial if you are passing it in as a local (:locals => { :dashboard => @dashboard }). Just usedashboard.