Reputation: 25
I've been stumped as to why my rails app is rendering the wrong partial. I have two partials, each related to a different controller (invitations and guests controllers). One partial lists the number of invitations sent out to users and the second partial lists those users who have confirmed their invitation. In addition, the second partial also allows one to see a simple profile of the confirmed guests.
What is happening is that when I visit the link related to the guests controller events/1/guests/
, I expect to see the partial related to the guest profile. Instead, the partial related to the invitations controller is rendered. Both the invitations and guests controllers are nested resources of events.
Below is the code that I have been working with. Thanks!
Routes
resources :events, only: [:new, :show, :create] do
resources :invitations, only: [:new, :create, :show]
resources :guests, only: :show
end
match '/events/:id/guests', to: 'guests#show'
Guests controller
def show
@event = Event.find_by_id(params[:id])
@guestlist = @event.invitations.where(accepted: true)
end
views/guests/show.html.erb
<% provide(:title, @event.eventname + " Guest List") %>
<h1> Guest list for <%= @event.eventname %> </h1>
<% if @event.invitations.any? %>
<%= render @guestlist %>
<% end %>
views/guests/_guestlist.html.erb
<li>
<%= guestlist.name %> | <%= guestlist.occupation %> |
<%= guestlist.interests %>
</li>
Instead, the following partial is being rendered:
views/invitations/_invitation.html.erb
<li>
<%= invitation.name %> | <%= invitation.email %> |
<% if invitation.accepted == true %> <%= "Confirmed" %> <% else %> <%= "Pending" %> <% end %>
</li>
Upvotes: 1
Views: 227
Reputation: 26203
The following snippet depicts the correct way to invoke your partial:
# app/views/guests/show.html.erb
<%= render :partial => 'guests/guestlist', :locals => {:guestlist => @guestlist} %>
Since you need access to the @guestlist
instance variable in your partial, you'll need to pass it as a local. Then, in your partial, guestlist
will be available as a local variable.
Then, within your partial, you'll need to iterate over the members of your guestlist:
# app/views/guests/_guestlist.html.erb
<% guestlist.each do |guest| %>
<li>
<%= guest.name %> | <%= guest.occupation %> | <%= guest.interests %>
</li>
<% end %>
UPDATE:
The reason the OP's original invocation of the partial rendered the invitation
partial is that @guestlist
is actually comprised of Invitation
objects, and thus, the <%= render @guestlist %>
method was actually looking for a partial named invitation
. From the canonical Rails guides:
There is also a shorthand for this. Assuming @products is a collection of product instances, you can simply write this in the index.html.erb to produce the same result:
<h1>Products</h1>
<%= render @products %>
Rails determines the name of the partial to use by looking at the model name in the collection.
Because of this, you need to explicitly declare the name of the partial you want to use, otherwise ActionView will use the invitation
partial by default.
Upvotes: 2
Reputation: 6891
If @guestlist
is an object of type Guest
, then it would by default render _guest.html.erb
.
So, you can try This
<%= render 'guestlist' %>
Variable @guestlist
would be automatically available in the partial, so no need to pass it in locals.
Hope this works.
Upvotes: 1
Reputation: 5734
In your show action, you have defined
@guestlist = @event.invitations.where(accepted: true) # it returns array of obejects or records
Now, Please have a try with the following code
views/guests/show.html.erb
<% unless @guestlist.blank? %>
<%= render "/guests/guestlist" %>
<% end %>
views/guests/_guestlist.html.erb
<% @guestlist.each do |guestlist| %>
<li>
<%= guestlist.name %> | <%= guestlist.occupation %> |
<%= guestlist.interests %>
</li>
<% end %>
Upvotes: 0