简体   繁体   中英

instance vs local variables in a partial

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

Ok, let's see. This is a lot of questions in one go, but...

  1. 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.

  2. 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.

  3. 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.

  1. Because a user's microposts are associated using 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.
  2. micropost comes from convention–Rails creates it for you. I don't know what you mean by "the @micropost variable which calls this partial".
  3. Same answer, although it's based explicitly on the template name (IIRC) rather than a singularized name. It contains a single one of whatever @feed_items contains.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM