问题
I'm having trouble getting traction on what the general ways data gets passed around from and is made available to partials.
For example:
I have a controller handing off an instance variable to a template that renders a partial:
static_pages_controller.rb:
def home
@feed_items = current_user.feed
end
home.html.erb:
<%= render 'shared/feed' %>
_feed.html.erb:
<%= render @feed_items %>
Now, inside my User model is an instance method that reaching into the database to get her posts:
user.rb:
def feed
Micropost.where("user_id = ?", id)
end
So somehow because Micropost.where(...)
returns a collection of microposts is that how Rails knows to go from _feed.html.erb
to another partial where the <li>
is defined for how microposts want to be defined?
_micropost.html.erb:
<li id="micropost-<%= micropost.id %>">
<%= link_to adorable_avatar_for(micropost.user, size: 50), micropost.user %>
</li>
And also is it just a convention that because I'm really handling a collection of microposts
that Rails knows to give the micropost
variable?
回答1:
Your questions are answered in the Ruby on Rails Guides on Layouts and Rendering. It's worth reading the information on partials that comes before the quoted passages below as well:
Every partial also has a local variable with the same name as the partial (minus the underscore). You can pass an object in to this local variable via the :object option:
<%= render partial: "customer", object: @new_customer %>
Within the customer partial, the customer variable will refer to @new_customer from the parent view. (Earlier the Guide instructs that to specify other options for render(), e.g. object:, you have to explicitly specify
partial:
and the name of the partial.)If you have an instance of a model to render into a partial, you can use a shorthand syntax:
<%= render @customer %>
Assuming that the @customer instance variable contains an instance of the Customer model, this will use _customer.html.erb to render it and will pass the local variable customer into the partial which will refer to the @customer instance variable in the parent view.
3.4.5 Rendering Collections
Partials are very useful in rendering collections. When you pass a collection to a partial via the :collection option, the partial will be inserted once for each member in the collection:
index.html.erb:
<h1>Products</h1> <%= render partial: "product", collection: @products %>
_product.html.erb:
<p>Product Name: <%= product.name %></p>
When a partial is called with a pluralized collection, then the individual instances of the partial have access to the member of the collection being rendered via a variable named after the partial. In this case, the partial is _product, and within the _product partial, you can refer to product to get the instance that is being rendered.
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. In fact, you can even create a heterogeneous collection and render it this way, and Rails will choose the proper partial for each member of the collection:
index.html.erb:
<h1>Contacts</h1> <%= render [customer1, employee1, customer2, employee2] %>
customers/_customer.html.erb:
<p>Customer: <%= customer.name %></p>
employees/_employee.html.erb:
<p>Employee: <%= employee.name %></p>
In this case, Rails will use the customer or employee partials as appropriate for each member of the collection.
In the event that the collection is empty, render will return nil, so it should be fairly simple to provide alternative content.
<h1>Products</h1> <%= render(@products) || "There are no products available." %>
来源:https://stackoverflow.com/questions/40955973/rails-5-rendering-partials-and-passing-data