Ruby on rails Rails教程:nil:NilClass的未定义方法

Ruby on rails Rails教程:nil:NilClass的未定义方法,ruby-on-rails,railstutorial.org,Ruby On Rails,Railstutorial.org,我成功地完成了MichaelHartl的Rails教程,您正在构建一个类似twitter的应用程序。现在,我想添加一些其他内容,但在尝试向MicroPost添加类似函数时遇到了困难 作为这一点的基础,我采取了追随者之间的关系 所以一个用户有很多“喜欢”的微用户,而一个微用户有很多“喜欢”的用户 我一直在犯错误 ActionView::Template::Error: undefined method 'likers' for nil:NilClass 在MicroPost接口测试和用户

我成功地完成了MichaelHartl的Rails教程,您正在构建一个类似twitter的应用程序。现在,我想添加一些其他内容,但在尝试向MicroPost添加类似函数时遇到了困难

作为这一点的基础,我采取了追随者之间的关系

所以一个用户有很多“喜欢”的微用户,而一个微用户有很多“喜欢”的用户

我一直在犯错误

    ActionView::Template::Error: undefined method 'likers' for nil:NilClass
在MicroPost接口测试和用户配置文件测试中

这是我的密码:

routes.rb:

Rails.application.routes.draw do
  root                'static_pages#home'
  get    'help'    => 'static_pages#help'
  get    'about'   => 'static_pages#about'
  get    'contact' => 'static_pages#contact'
  get    'signup'  => 'users#new'
  get    'login'   => 'sessions#new'
  post   'login'   => 'sessions#create'
  delete 'logout'  => 'sessions#destroy'
    resources :users do
      member do
        get :following, :followers, :liked
      end
    end


    resources :microposts do
      member do
        get :likers
      end
    end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :microposts,          only: [:create, :destroy]
  resources :relationships,       only: [:create, :destroy]
end
app/models/like.rb:

class Like < ActiveRecord::Base
  belongs_to :liker, class_name: "User"
  belongs_to :micropost, class_name: "Micropost"
  validates :liker_id, presence: true
  validates :micropost_id, presence: true
end
app/models/micropost.rb:

class Micropost < ActiveRecord::Base
  belongs_to :user
  has_many :passive_likes, class_name:  "Like",
                           foreign_key: "micropost_id",
                           dependent:   :destroy
  has_many :likers, through: :passive_likes, source: :micropost
  default_scope -> { order(created_at: :desc) }
  mount_uploader :picture, PictureUploader
  validates :user_id, presence: true
  validates :content, presence: true, length: { maximum: 140 }
  validate  :picture_size

  private

    # Validates the size of an uploaded picture.
    def picture_size
      if picture.size > 5.megabytes
        errors.add(:picture, "maximal 5MB")
      end
    end
end
app/models/user.rb:

class User < ActiveRecord::Base
  has_many :microposts, dependent: :destroy
  has_many :active_relationships,  class_name:  "Relationship",
                                   foreign_key: "follower_id",
                                   dependent:   :destroy
  has_many :passive_relationships, class_name:  "Relationship",
                                   foreign_key: "followed_id",
                                   dependent:   :destroy
  has_many :active_likes, class_name:  "Like",
                          foreign_key: "liker_id",
                          dependent:   :destroy
  has_many :liked, through: :active_likes, source: :micropost
  has_many :following, through: :active_relationships,  source: :followed
  has_many :followers, through: :passive_relationships, source: :follower

  mount_uploader :avatar, AvatarUploader

  attr_accessor :remember_token, :activation_token, :reset_token
  before_save   :downcase_email
  before_create :create_activation_digest
  validates :name,  presence: true, length: { maximum: 50 }
  VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+\.[a-z]+\z/i
  validates :email, presence: true, length: { maximum: 255 },
                    format: { with: VALID_EMAIL_REGEX },
                    uniqueness: { case_sensitive: false }
  has_secure_password
  validates :password, length: { minimum: 6 }, allow_blank: true

  # Returns the hash digest of the given string.
  def self.digest(string)
    cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST :
                                                  BCrypt::Engine.cost
    BCrypt::Password.create(string, cost: cost)
  end

  # Returns a random token.
  def self.new_token
    SecureRandom.urlsafe_base64
  end

  # Remembers a user in the database for use in persistent sessions.
  def remember
    self.remember_token = User.new_token
    update_attribute(:remember_digest, User.digest(remember_token))
  end

  # Returns true if the given token matches the digest.
  def authenticated?(attribute, token)
    digest = send("#{attribute}_digest")
    return false if digest.nil?
    BCrypt::Password.new(digest).is_password?(token)
  end

  # Forgets a user.
  def forget
    update_attribute(:remember_digest, nil)
  end

   # Activates an account.
  def activate
    update_attribute(:activated,    true)
    update_attribute(:activated_at, Time.zone.now)
  end

  # Sends activation email.
  def send_activation_email
    UserMailer.account_activation(self).deliver_now
  end

  # Sets the password reset attributes.
  def create_reset_digest
    self.reset_token = User.new_token
    update_attribute(:reset_digest,  User.digest(reset_token))
    update_attribute(:reset_sent_at, Time.zone.now)
  end

  # Sends password reset email.
  def send_password_reset_email
    UserMailer.password_reset(self).deliver_now
  end

  # Returns true if a password reset has expired.
  def password_reset_expired?
    reset_sent_at < 2.hours.ago
  end

  # Defines a proto-feed.
  # See "Following users" for the full implementation.
  # Returns a user's status feed.
  def feed
    following_ids = "SELECT followed_id FROM relationships
                     WHERE  follower_id = :user_id"
    Micropost.where("user_id IN (#{following_ids})
                     OR user_id = :user_id", user_id: id)
  end

  # Follows a user.
  def follow(other_user)
    active_relationships.create(followed_id: other_user.id)
  end

  # Unfollows a user.
  def unfollow(other_user)
    active_relationships.find_by(followed_id: other_user.id).destroy
  end

  # Returns true if the current user is following the other user.
  def following?(other_user)
    following.include?(other_user)
  end

  # Likes a micropost
  def like(any_post)
    active_like.create(micropost_id: any_post.id)
  end

  # Unlikes a micropost
  def unlike(any_post)
    active_like.find_by(micropost_id: any_post.id).destroy
  end

  # Returns true if the current user is liking the micropost
  def liked?(any_post)
    liked.include?(any_post)
  end

  private

    # Converts email to all lower-case.
    def downcase_email
      self.email = email.downcase
    end

    # Creates and assigns the activation token and digest.
    def create_activation_digest
      self.activation_token  = User.new_token
      self.activation_digest = User.digest(activation_token)
    end
end
app/views/users/show.html.erb:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Posts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <%= render 'shared/morestats' %>
      <%= render 'microposts/like_form' if logged_in? %>
    <% if current_user?(micropost.user) %>

      <%= link_to "löschen", micropost, method: :delete,
                                       data: { confirm: "Diesen Post wirklich löschen?" } %>
    <% end %>
  </span>
</li>
<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @micropost.liked?(@user) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<% @micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= @micropost.likers.count %>
  </strong>
  likers
</div>
app/views/micropost/_micropost.html.erb:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Posts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <%= render 'shared/morestats' %>
      <%= render 'microposts/like_form' if logged_in? %>
    <% if current_user?(micropost.user) %>

      <%= link_to "löschen", micropost, method: :delete,
                                       data: { confirm: "Diesen Post wirklich löschen?" } %>
    <% end %>
  </span>
</li>
<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @micropost.liked?(@user) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<% @micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= @micropost.likers.count %>
  </strong>
  likers
</div>
app/views/microposts/_like_form.html.erb:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Posts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <%= render 'shared/morestats' %>
      <%= render 'microposts/like_form' if logged_in? %>
    <% if current_user?(micropost.user) %>

      <%= link_to "löschen", micropost, method: :delete,
                                       data: { confirm: "Diesen Post wirklich löschen?" } %>
    <% end %>
  </span>
</li>
<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @micropost.liked?(@user) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<% @micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= @micropost.likers.count %>
  </strong>
  likers
</div>
app/views/microposts/_like.html.erb:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Posts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <%= render 'shared/morestats' %>
      <%= render 'microposts/like_form' if logged_in? %>
    <% if current_user?(micropost.user) %>

      <%= link_to "löschen", micropost, method: :delete,
                                       data: { confirm: "Diesen Post wirklich löschen?" } %>
    <% end %>
  </span>
</li>
<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @micropost.liked?(@user) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<% @micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= @micropost.likers.count %>
  </strong>
  likers
</div>
app/views/microposts/_.html.erb:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Posts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <%= render 'shared/morestats' %>
      <%= render 'microposts/like_form' if logged_in? %>
    <% if current_user?(micropost.user) %>

      <%= link_to "löschen", micropost, method: :delete,
                                       data: { confirm: "Diesen Post wirklich löschen?" } %>
    <% end %>
  </span>
</li>
<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @micropost.liked?(@user) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<% @micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= @micropost.likers.count %>
  </strong>
  likers
</div>
如果有任何代码丢失,请告诉我。提前谢谢

以下是全部错误:

ERROR["test_micropost_interface", MicropostsInterfaceTest, 4.72409967]
 test_micropost_interface#MicropostsInterfaceTest (4.72s)
ActionView::Template::Error:         ActionView::Template::Error: undefined method `likers' for nil:NilClass
            app/views/shared/_morestats.html.erb:4:in `_app_views_shared__morestats_html_erb___939926434685355917_93681000'
            app/views/microposts/_micropost.html.erb:10:in `_app_views_microposts__micropost_html_erb___1029196025817541101_93766560'
            app/views/users/show.html.erb:19:in `_app_views_users_show_html_erb___2389533090581269630_85562520'
            test/integration/microposts_interface_test.rb:33:in `block in <class:MicropostsInterfaceTest>'
        app/views/shared/_morestats.html.erb:4:in `_app_views_shared__morestats_html_erb___939926434685355917_93681000'
        app/views/microposts/_micropost.html.erb:10:in `_app_views_microposts__micropost_html_erb___1029196025817541101_93766560'
        app/views/users/show.html.erb:19:in `_app_views_users_show_html_erb___2389533090581269630_85562520'
        test/integration/microposts_interface_test.rb:33:in `block in <class:MicropostsInterfaceTest>'
测试/集成/microposts_接口_test.rb的代码:

require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:peter)
  end

  test "micropost interface" do
    log_in_as(@user)
    get root_path
    assert_select 'div.pagination'
    # Invalid submission
    assert_no_difference 'Micropost.count' do
      post microposts_path, micropost: { content: "" }
    end
    assert_select 'div#error_explanation'
    # Valid submission
    content = "This micropost really ties the room together"
    assert_difference 'Micropost.count', 1 do
      post microposts_path, micropost: { content: content }
    end
    assert_redirected_to root_url
    follow_redirect!
    assert_match content, response.body
    # Delete a post.
    assert_select 'a', text: 'löschen'
    first_micropost = @user.microposts.paginate(page: 1).first
    assert_difference 'Micropost.count', -1 do
      delete micropost_path(first_micropost)
    end
    # Visit a different user.
    get user_path(users(:archer))
    assert_select 'a', text: 'löschen', count: 0
  end
end
require 'test_helper'

class UsersProfileTest < ActionDispatch::IntegrationTest
  include ApplicationHelper

  def setup
    @user = users(:peter)
  end

  test "profile display" do
    get user_path(@user)
    assert_template 'users/show'
    assert_select 'title', full_title(@user.name)
    assert_select 'h1', text: @user.name
    assert_select 'h1>img.gravatar'
    assert_match @user.microposts.count.to_s, response.body
    assert_select 'div.pagination'
    @user.microposts.paginate(page: 1).each do |micropost|
      assert_match micropost.content, response.body
    end
  end
end
测试/集成/用户\u配置文件\u test.rb的代码:

require 'test_helper'

class MicropostsInterfaceTest < ActionDispatch::IntegrationTest

  def setup
    @user = users(:peter)
  end

  test "micropost interface" do
    log_in_as(@user)
    get root_path
    assert_select 'div.pagination'
    # Invalid submission
    assert_no_difference 'Micropost.count' do
      post microposts_path, micropost: { content: "" }
    end
    assert_select 'div#error_explanation'
    # Valid submission
    content = "This micropost really ties the room together"
    assert_difference 'Micropost.count', 1 do
      post microposts_path, micropost: { content: content }
    end
    assert_redirected_to root_url
    follow_redirect!
    assert_match content, response.body
    # Delete a post.
    assert_select 'a', text: 'löschen'
    first_micropost = @user.microposts.paginate(page: 1).first
    assert_difference 'Micropost.count', -1 do
      delete micropost_path(first_micropost)
    end
    # Visit a different user.
    get user_path(users(:archer))
    assert_select 'a', text: 'löschen', count: 0
  end
end
require 'test_helper'

class UsersProfileTest < ActionDispatch::IntegrationTest
  include ApplicationHelper

  def setup
    @user = users(:peter)
  end

  test "profile display" do
    get user_path(@user)
    assert_template 'users/show'
    assert_select 'title', full_title(@user.name)
    assert_select 'h1', text: @user.name
    assert_select 'h1>img.gravatar'
    assert_match @user.microposts.count.to_s, response.body
    assert_select 'div.pagination'
    @user.microposts.paginate(page: 1).each do |micropost|
      assert_match micropost.content, response.body
    end
  end
end
shared/_morests.html.erb的代码:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Posts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>
<li id="micropost-<%= micropost.id %>">
  <%= link_to gravatar_for(micropost.user, size: 50), micropost.user %>
  <span class="user"><%= link_to micropost.user.name, micropost.user %></span>
  <span class="content">
    <%= micropost.content %>
    <%= image_tag micropost.picture.url if micropost.picture? %>
  </span>
  <span class="timestamp">
    Posted <%= time_ago_in_words(micropost.created_at) %> ago.
    <%= render 'shared/morestats' %>
      <%= render 'microposts/like_form' if logged_in? %>
    <% if current_user?(micropost.user) %>

      <%= link_to "löschen", micropost, method: :delete,
                                       data: { confirm: "Diesen Post wirklich löschen?" } %>
    <% end %>
  </span>
</li>
<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @micropost.liked?(@user) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<%= form_for(current_user.active_likes.build) do |f| %>
  <div><%= hidden_field_tag :micropost_id, @user.id %></div>
  <%= f.submit "Like", class: "btn btn-primary" %>
<% end %>
<% @micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= @micropost.likers.count %>
  </strong>
  likers
</div>

问题是您编写的@micropost引用了一个对所有视图可见的变量,而@micropost对象是您从未分配的。如果您在不使用@的情况下编写micropost,那么您引用的是一个分配了:locals=>{:micropost=>micropost}的局部变量

在shared/morestats的第4行中,您正在执行@microspost.likers,但如果您注意,您不会将任何microspost传递给部分。参见microspost,第10行:

<%= render 'shared/morestats' %>
您必须将其更改为以下内容:

<% micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= micropost.likers.count %>
  </strong>
  likers
</div>
<% @micropost = micropost %>
<%= render 'shared/morestats' %>
“共享/morestats',:locals=>{:microspost=>microspost}%>

并从morestats中的micropost中删除“@”。就这样,

<% micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= micropost.likers.count %>
  </strong>
  likers
</div>
<% @micropost = micropost %>
<%= render 'shared/morestats' %>
您在这里遇到了同样的问题:

<%= render 'microposts/like_form' %>
您必须将其更改为以下内容:

<% micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= micropost.likers.count %>
  </strong>
  likers
</div>
<% @micropost = micropost %>
<%= render 'shared/morestats' %>
‘micropost/like_form’,:locals=>{:micropost=>micropost}%>

像这样:

<% unless current_user?(@user) %>
  <div id="like_form">
  <% if @user.liked?(micropost) %>
    <%= render 'unlike' %>
  <% else %>
    <%= render 'like' %>
  <% end %>
  </div>
<% end %>
另一个解决方案是,如果您不想更改@,您可以修改_microstop部分,如下所示:

<% micropost %>
<div class="morestats">
  <strong id="likers" class="morestat">
    <%= micropost.likers.count %>
  </strong>
  likers
</div>
<% @micropost = micropost %>
<%= render 'shared/morestats' %>

但这并没有以前的解决方案那么优雅。

错误指向哪里?我在问题的底部添加了完整的错误。您是否也可以添加测试代码?谢谢您的回答!这是有道理的,但我仍然收到相同的错误消息。我在问题中添加了shared/_morests.html.erb的代码。这有用吗?我真的不知道还能尝试什么。我已经尝试过了,但只有一条错误信息消失了。MicropostsInterfaceTest的错误保持不变。对于microposts/_like_form.html.erb第3行中的nil:Nilclass,错误现在是一个未定义的方法“liked?”。再次出现相同问题:将局部变量添加到liked_form部分调用中,并从MicroPost中删除@。还考虑到喜欢吗?是一种用户方法,而不是micropost方法。