Reputation: 5382
I'm currently going through Michael Hartl's tutorial Ruby on Rails Tutorial http://ruby.railstutorial.org/ruby-on-rails-tutorial-book. I'm confused about where certain partial variables come from. In his tutorial he creates Users and Microposts. A User can create a Micropost on his main page (called a Feed) and have them posted there. The layout looks like this http://ruby.railstutorial.org/chapters/user-microposts#fig:proto_feed_mockup. Now the User model looks like this (I'm not posting the entire thing):
class User < ActiveRecord::Base
has_many :microposts, dependent: :destroy
def feed
Micropost.where("user_id = ?", id)
end
end
The Micropost model looks like this:
class Micropost < ActiveRecord::Base
belongs_to :user
end
In the text the author says that the feed method inside the User model can be written equivalently like this:
def feed
microposts
end
Why are they the same?
My next questions have to do with partials. On the user's show page (show.html.erb) the _microposts.html.erb is called with this if I'm not mistaken:
<%= render @microposts %>
_microposts.html.erb looks like this:
<li>
<span class="content"><%= micropost.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(micropost.created_at) %> ago.
</span>
<% if current_user?(micropost.user) %>
<%= link_to "delete", micropost, method: :delete,
data: { confirm: "You sure?" },
title: micropost.content %>
<% end %>
</li>
My question here is where is the micropost variable come from? Is it the same as the @micropost variable which calls this partial?
Now on the users home page (home.html.erb) there is a call to the _feed.html.erb partial like this:
<%= render 'shared/feed' %>
_feed.html.erb looks like this:
<% if @feed_items.any? %>
<ol class="microposts">
<%= render partial: 'shared/feed_item', collection: @feed_items %>
</ol>
<%= will_paginate @feed_items %>
<% end %>
I know where @feed_items comes from. It's set in a controller. Now _feed_item.html.erb looks like this:
<li id="<%= feed_item.id %>">
<%= link_to gravatar_for(feed_item.user), feed_item.user %>
<span class="user">
<%= link_to feed_item.user.name, feed_item.user %>
</span>
<span class="content"><%= feed_item.content %></span>
<span class="timestamp">
Posted <%= time_ago_in_words(feed_item.created_at) %> ago.
</span>
<% if current_user?(feed_item.user) %>
<%= link_to "delete", feed_item, method: :delete,
data: { confirm: "You sure?" },
title: feed_item.content %>
<% end %>
</li>
So a similar question is where does the variable feed_item come from and what does it contain?
thanks, mike
Upvotes: 1
Views: 209
Reputation: 9700
Ok, let's see. This is a lot of questions in one go, but...
Why is 'feed' equivalent to 'microposts'?
This is Rails' associations at work. When you use has_many
to describe an association, Rails creates a whole bunch of methods based on the association name. In this case, you say that User has_many :microposts
, which, among others, creates a User#microposts
method.
The instance variable used in the render call (@microposts
) is presumably set in a controller action. When you call render in this fashion (with an array of ActiveRecord objects), Rails looks for a partial with a name matching the class name of those objects. In this case, they're MicroPost objects, so it looks for a partial named _micropost
and renders it once for each object in the array. When rendering a partial, the object that the partial is associated with can be referred to using a local variable with the same name as the partial. Since this is the _micropost
partial, the local micropost
variable refers to the object it's rendering.
Once again, the local variable with the same name as the partial refers to the object the partial is rendering. @feed_items is a collection, and for each object in it, you get one rendering of the _feed_item
partial, in which the feed_item
local variable refers to that object.
Upvotes: 1
Reputation: 160191
has_many
, and internally, the relationship is based on the user's id. Getting them "by hand" does essentially the same thing, but with more work.micropost
comes from convention–Rails creates it for you. I don't know what you mean by "the @micropost
variable which calls this partial".@feed_items
contains.Upvotes: 0