Tek Mobile
Tek Mobile

Reputation: 41

Ruby on rails: Is it possible to nest partial calls/rendering like so:

Assuming that the "books/book" partial below is being called from multiple locations (like: author#show view, categogories#show view, categories#index view) and i only want the votes partial called from the author#show view. That is, i want the books collection returned from the books partial (@upvoted_books) to each render the "votes/vote" partail so that authors are able to vote on a book from their author#show view. Is the following code or a variation of it sensible?

    <%= render partial: "books/book", collection: @upvoted_books  do |upvoted| %>
  <%= render partial: "votes/vote", locals: {category: book.category, book: upvoted } %>

<% end %>

p.s: I have tried this particular code here and it doesnt work in my project but i was just wondering if something similar to it could work but it doesnt throw any apparent error either. Maybe i was just getting the syntax a bit mixed up. I alos know a few other ways to solve the same problem but i was looking for something more elegant. Thanks in anticipationm of your creative responses.


update:

Thanks @Deep, for your very insightful solution. What I have done to solve the problem before is calling the line below from "books/book" partial:

<% if defined?(@upvoted_books) && @upvoted_books.include?(book) %>
  <%= render partial: "votes/vote", locals: {category: book.category, book: upvoted } %>
<% end %>

That works but i'm not sure it has some significant code-smell or if its syntatically awkward. What do you think?

Final update:


@Deep these are the views you asked for: This is my category#show view :

`<h1>Topics#show</h1>

<p><%= @category.title %></p>

<%= render partial: "books/form", locals: {topic: @category, book: Book.new} %>

<%= link_to "edit category", edit_author_category_path(@category.author, @category) %>

<p> Books you have Authored </p>

<%= render partial: "books/book", collection: @category.books %>`

 And this is my books/_book.html.erb partial now    

    `<% if defined?(upvoted_book) && current_author.books.include?(upvoted_book) %>

  <h5>Created by <%= upvoted_book.category.author.name || upvoted_book.category.author.email %> on <%= upvoted_book.created_at %></h> 
  <br>

  <%= link_to upvoted_book.title, category_book_path(upvoted_book.category, upvoted_book) %>

  <% if policy(Vote.new).create? %>

    <%= render partial: "votes/vote", locals: {category: upvoted_book.category, book: upvoted_book} %>
  <br>

  <% end %>

<% else %>

  <h5>Created by <%= book.category.author.name || book.category.author.email %> on <%= book.created_at %></h> 
  <br>

  <%= link_to book.title, category_book_path(book.category, book) %>

  <%= link_to "Remove book", category_book_path(book.category, book), method: :delete, data: { confirm: "Are you sure you want to delete this book?" } %>

<% end %>`

As you can see, i refer to local variables book and upvoted_book in the partial. This is how i called the partial from the author#show view : `

<%= render partial: "categories/form", locals: {category: Category.new, author: @author} %>

<p> Categories and Books you have Writen: </p>

<%= render partial: "categories/category", collection: @categories %>

<p> Books from all authors that you have Upvoted: </p>

<%= render partial: "books/book", collection: @upvoted_books, as: :upvoted_book %>
<br>  `

Thanks for you wonderful insight again. 

Upvotes: 2

Views: 177

Answers (1)

Deepesh
Deepesh

Reputation: 6398

As you need vote partial to be rendered on each book and only in a single view, so what you can do is:

<%= render partial: "books/book", collection: @upvoted_books, locals: { vote: true } %>

Now in your partial book write down:

if vote
   <%= render partial: "votes/vote", locals: {category: book.category, book: upvoted } %>
end

And make sure from rest of the places where you are rendering book partial pass locals: { vote: false } or else it will throw error. Or what you can do in the partial is:

vote ||= false

Or instead of using if vote you can use if defined?(vote), so there would be no burden to pass it from other pages.

Also I doubt you have some wrong locals, not sure may be so correct them. But using this you can call vote partial on a single view.

Hope this helps.

Upvotes: 1

Related Questions