I have models called project and test. A project has many tests.
In the index.html.erb of tests, I have:
<%= render #tests %>
So I therefore have a file called _test.html.erb, and in it I have:
<%= render "form" %>
I then have a filed called _form.html.erb with:
<%= form_for([#project, #project.tests.build]) do |f| %>
<p>
<%= f.label :name %>
<%= f.text_field :name %>
</p>
<% end %>
But I get an exception:
undefined method `tests' for nil:NilClass
So #project is apparently nil. I understand my set up is a bit strange, so I'm not sure how I would refactor this to work?
Instance variables are accessible from any level of rendering.
You can render 100 partials inside each other and you would still have access to those same ivars.
The problem looks like you aren't actually setting #project anywhere.
You probably are looking for "test.project" in your form.
<%= render #tests, project: #project %>
Then
<%= render 'form', project: project %>
The idea is to pass in the #project instance variable as a local variable.
Are both partials in the same view?
You will also have to pass the #project object to the partial and every partial that uses #project.
Example:
<%= render #tests, project: #project %>
Related
I have a Project that has_many tasks. The Task has a _form.html.erb file that I wanted to show on my show.html.erb file from Project.
But everytime I try this, I am getting the following error:
undefined local variable or method `task'
I am using <%= render 'tasks/form' %> to render the partial.
Also, would
<% #tasks.each do |task| %>
<%= listing.task.name %>
<% end %>
do the trick to show all listings that's associated with the current page?
It looks like you are just missing to pass the task local to the partial.
This should work:
<%= render partial: 'tasks/form', locals: { task: #task } %>
I have an edit view. In this view I got a dropdown and a render partial to a form. Like this:
<ul class="dropdown-menu dropdown-user installations">
<% #installations.each do |i| %>
<li>Installation<%= i.installation_id%></li>
<% end %>
</ul>
<div class="ibox-content form-installations">
<%= render :partial => 'installations/test'%>
<%= render 'form_data' %>
</div>
The view to edit the form:
<%= simple_form_for #installation, class: 'form-horizontal' do |f| %>
<%= f.error_notification %>
...
<%end%>
Controller:
def edit
#installations = current_user.installations
#installation = current_user.installations[0]
end
So in this point I can see in dropdown all installations but only can edit the first "current_user.installations[0]". So my objective is to select the installation in dropdown-menu and edit the selected installation. How I can do this?
The simplest way to do this will be to pass the relevant installation to the dropdown:
#app/controllers/installations_controller.rb
class InstallationsController < ApplicationController
def index
#installations = current_user.installations
end
end
#app/views/installations/index.html.erb
<%= render #installations %>
#app/views/installations/_installation.html.erb
<%= simple_form_for installation do |f| %>
...
<% end %>
I think there are some major issues with the structure of your code - which is why you're seeing these problems.
1. Edit
By definition edit is a member route...
This means that Rails expects a single resource to be loaded through that route (hence why you get url.com/:id/edit as the path).
The reason for this is quite simple -- Rails/Ruby are object orientated. This means that each time you create/read/update/destroy (CRUD), you're doing it to an object.
Objects are invoked by using #installation = Installation.new etc... meaning if you want to edit "all" of your installations, you'll basically need to use one of the collection routes for your Installations resource, sending any fields to the update path:
#app/views/installations/_installation.html.erb
<%= simple_form_for installation, method: :patch do |f| %>
...
<% end %>
This should send the updates to the installations#update path of your app, making it work properly.
--
2. Partials
Partials are just views which can have multiple uses; you should only use "local" variables in them.
There are two ways to invoke local scope variables into partials:
passing them in the locals: {} hash
passing them as in the as: :__ switch
In both instances, you're setting the "local" variables inside the partial to have data that was only available outside of it.
For example, you're calling:
<%= simple_form_for #installation
... inside a partial. This is bad because you're relying on #installation -- you're better using installation and populating it as you invoke the partial (as I have done in the code above).
I am sorry in advance as I know this should be an easy one but I am stuck. I have a show view for "Category" in which I am trying to display related has_many "Subcategories". I am calling the partial by using the following:
<%= render partial: 'subcategories/subcategory', locals: {category: #category }%>
I have an html file in the Subcategories view folder properly named and the partial view loads. I know this because the partial has the code
<%= #category.name %></p>
which shows the correct Category name within the partial. However, when I try to load any of the subcategory data by calling
<% #subcategories.each do |subcategory| %>
<%= subcategory.name%>
<% end %>
I get the error: NoMethodError in Categories#show, undefined method `each' for nil:NilClass
I'm sorry to ask such a basic question but I will be using partials from related modules extensively in this project.
Replace this:
<%= render partial: 'subcategories/subcategory', locals: {category: #category }%>
with this:
<%= render #category.subcategories %>
Then in the partial app/views/subcategories/_subcategory.html.erb do this:
<%= subcategory.name %>
I'm new to ruby on rails.
In views/events I have "_form.html.erb" which is rendered in "new.html.erb" by this code:
<%= render "form" %>
Now I want to render "_form.html.erb" in "index.html.erb" which is in the same folder(views/events).
But I get the error "missing template".
I guess I have to add some thing to controller, please help me to render form in other pages of views...
You "usually" don't render a form in an index action. Most form partials are setup semantically to expect a #my_resource, but if you're doing everything the rails way you're not going to have a instance variable during your index action. There's a number of ways you can do this but this is probably the quickest.
You probably have some collection (let's pretend you're using books) in your index action:
#views/books/index.html.erb
<% #books.each do |book| %>
...
<%= render "form" %>
...
<% end %>
You can just set an instance variable somewhere prior to rendering the form:
#views/books/index.html.erb
<% #books.each do |book| %>
<% #book = book %>
...
<%= render "form" %>
...
<% end %>
Another way to do it would be through passing in some locals to a partial. You'd have to change all of your references in _form to use a local variable instead. Then you can call render like this:
<%= render :partial => "form", :locals => {:book => book } %>
You can try
<%= render "events/form" %>
I had this problem before and this solved
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?
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 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.
If the partial needs to know about a variable in the calling erb file, you can pass it like this:
<%= render partial: "tasks/new", locals: { task: #task } %>
And in file app/views/tasks/_new.html.erb, refer to the variable like this:
<% form_for task do |f| %>
<%= f.text_field :body %>
<%= submit_tag "Submit" %>
<% end %>
That is, without the #. (The code a: b is just a more convenient form of :a => b.)
I wonder, though, why do you want to use partials in file application.html.erb? I'm assuming that you mean the Ruby-generated file app/views/layouts/application.html.erb, which is supposed to be used as a layout file containing elements common to all your application's pages, not for business logic. Perhaps the file you need to call the partial from is app/views/tasks/index.html.erb?