views:

190

answers:

2

Here's the call in the application.html.erb file:

<%= render :partial => 'tasks/_new' %>

Here's the partial being rendered (_new.html.erb):

<% form_for @task do |f| -%>
  <%= f.text_field :body %>
  <%= submit_tag "Submit" %>
<% end -%>

Here's the method in the 'tasks' controller:

def new
  @task = Task.new

  respond_to do |format|
    format.html # new.html.erb
    format.xml  { render :xml => @task }
  end
end

Here's the error message I keep getting:

Missing template tasks/__new.erb in view path app/views

And it says the error is in this line:

<%= link_to "tasks", tasks_path %> <%= render :partial => 'tasks/_new' %>

The file is in the right directory. The weird thing is that there's an extra _ in the file name, in the error. When I give in and rename the partial to __new.erb, here's the error I get:

Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use object_id

And it says the error is in this line:

<% form_for @task do |f| -%>

I had also tried without the _ in the code, as Petros suggested, but it returns the same error as above, Called id for nil….

What's going on?

+3  A: 

You don't need the _ in your code. It should be:

<%= render :partial => 'tasks/new' %>

The first error is because you don't need to put the _ inside the :partial parameter. Rails takes care of that. That's why you get double __ because Rails will put one for you.

The second error is your real problem. The error suggests that @task is nil. This is true because the partial only knows what the container view knows, and your view in that particular moment hasn't called the action from the proper controller. As you (Baby Diego) already found out and indicated in one of your comments below, you needed to create an instance of a Task in your partial. I don't know if there is a more elegant solution, but maybe someone can suggest something better in the future.

Thanks to MattMcKnight for informing us that the partial itself does only know what the container view knows.

Petros
Sorry, I should have specified. I tried that, too. It returned the "called id for nil" error. I'm gonna fix the OP.
Baby Diego
Can you try <%= render :partial => 'tasks/new', locals => { :task => @task } %> ... You might need to change @task to task in your partial or add code at the top of the partial doing <% @task = task if @task == nil %>
Petros
I tried to make that work but I couldn't. You helped me realize the problem was that there was no instance of '@task' actually reaching the application layout, as it's bound to the tasks controller, so I tried "<% form_for Task.new do |f| -%>" and it worked. But it feels kind of like a hack. Is it the right approach?
Baby Diego
Yes it feels hackish, but I don't know how we could improve it. I edited my answer suggesting maybe a more elegant way and correcting it based on MattMcKnight's answer.
Petros
Thanks, I just read your update, but unfortunately "<%= render :partial => 'tasks/new', :object => Task.new %>" doesn't work. I've read on partials documentation but the only thing I managed to get working was to use 'Task.new' in the form of the partial itself.
Baby Diego
Thanks for the feedback Baby Diego. I'll edit my answer removing my last suggestion. I'll highlight what you found that works and maybe someone else may suggest a better approach in the future.
Petros
When you do <%= render :partial => 'tasks/new', :object => Task.new %> the object you end up with in the partial will be called "new" (not @task or @new). To call it @task, you would need a variable called that to be in scope somewhere, perhaps by doing something like <% @task = Task.new %>. It's really not worth it so long as it is always an empty form.
MattMcKnight
+2  A: 

Petros correctly identified the first issue- you don't need the underscore in the partial call. The second thing to know about partials is that they don't call the controller method, they just reference the view. Thus, you need to setup the @task object in every action that uses that partial, or just call Task.new in the partial. When I have a partial in a layout in similar situations, I usually load it with JavaScript so that I can call the action.

MattMcKnight
I am calling it from the application layout, the action using the partial would be something in the application controller, right? Other than that, me using "<% form_for Task.new do |f| -%>" instead is not a hack?
Baby Diego
Thanks MattMcKnight for informing us that a partial only knows what the container view knows. I edited my answer to be more accurate.
Petros
Not a hack to call a class method on a Model. Calling <% tasks = Task.find(:all, :conditions => "complete = false") %> in the partial would be close to a hack.I think a key concept that some people don't understand in Rails is that only one action (aka controller method) gets called.
MattMcKnight