Ruby error NoMethodError for nil:NilClass



我正在使用rails在teamtreehouse.com上学习Treebook教程(制作一个facebook克隆)。我创建了一个用户友谊控制器,当我试图在友谊视图的index.html页面中引用朋友的全名时,出现了这个错误:未定义的nil:NilClass方法"full_name"。问题出现在这里的第4行,(这是/views/user_friendships/index.html)

<div class="page-header">
  <h1>Friends</h1>
</div>
<hr />
<% if @user_friendships.empty? %>
<em>No <%= params[:list] %> friends yet!</em>
<% end %>
<% @user_friendships.each do |friendship| %>
 <% friend = friendship.friend %>
 <div id="<%= dom_id(friendship) %>" class="friend panel">
    <div class="panel-heading">
      <span class="pull-right label>"><%= "#{friendship.state}".upcase %></span>
      <h3 class="panel-title"><%= friend.full_name %></h3>
    </div>
    <div class="panel-body">
      <div class="row">
        <div class="col-md-1">Put gravatar url here</div>
          <div class="col-md-11">
            <em>Friends since time_ago_in_words ago</em>
          </div>
        </div>
    </div>
    <div class="panel-footer clearfix">
        <%= link_to "Update friendship", edit_user_friendship_path( friend.profile_name), class: 'btn btn-primary pull-right' %>
    </div>
 </div>
<% end %>

这是用户友谊控制器:

class UserFriendshipsController < ApplicationController
before_filter :authenticate_user!
  def index
    @user_friendships = current_user.user_friendships.all
  end
  def new
    if params[:friend_id]
      @friend = User.where(profile_name: params[:friend_id]).first
      raise ActiveRecord::RecordNotFound if @friend.nil?
      @user_friendship = current_user.user_friendships.new(friend: @friend)
    else
      flash[:error] = "Friend required"
    end
    rescue ActiveRecord::RecordNotFound 
      render file: 'public/404', status: :not_found
  end
  def create
    if params[:user_friendship] && params[:user_friendship].has_key?(:friend_id)
      @friend = User.where(profile_name: params[:user_friendship][:friend_id]).first
      @user_friendship = UserFriendship.request(current_user, @friend)
      respond_to do |format|
        if @user_friendship.new_record?
          format.html do
            flash[:error] = "There was a problem creating that friend request."
            redirect_to profile_path(@friend)
          end
          format.json { render json: @user_friendship.to_json, status: :precondition_failed }
        else
          format.html do
            flash[:success] = "Friend request sent to #{@friend.full_name}."
            redirect_to profile_path(@friend.profile_name)
          end
          format.json { render json: @user_friendship.to_json }
        end
      end
    else
      flash[:error] = "Friend required"
      redirect_to root_path
    end
  end
  def edit
    @friend =  User.where(profile_name: params[:id]).first
    @user_friendship = current_user.user_friendships.find(params[:id])
  end
  def destroy
    @user_friendship = current_user.user_friendships.find(params[:id])
    if @user_friendship.destroy
      flash[:success] = "Friendship destroyed."
    end
    redirect_to user_friendships_path
  end
  def accept
    @user_friendship = current_user.user_friendships.find(params[:id])
    if @user_friendship.accept!
      flash[:success] = "You are now friend with #{@user_friendship.friend.full_name}"
    else
      flash[:error] = "That friendship could not be accepted."
    end
    redirect_to user_friendships_path
  end
  def block
    @user_friendship = current_user.user_friendships.find(params[:id])
    if @user_friendship.block!
      flash[:success] = "You have blocked #{@user_friendship.friend.full_name}."
    else
      flash[:error] = "That friendship could not be blocked."
    end
    redirect_to user_friendships_path
  end
  private
  def friendship_association
    case params[:list]
    when nil
      current_user.user_friendships
    when 'blocked'
      current_user.blocked_user_friendships
    when 'pending'
      current_user.pending_user_friendships
    when 'requested'
      current_user.requested_user_friendships
    when 'accepted'
      current_user.accepted_user_friendships
    end
  end
  private
  def user_friendship_attributes
    params.require(:user_friendship).permit(:user, :friend, :user_id, :friend_id, :state)
  end
end

最后,我将包括用户友谊模型:

class UserFriendship < ActiveRecord::Base
    belongs_to :user
    belongs_to :friend, class_name: 'User', foreign_key: 'friend_id'
    state_machine :state, initial: :pending do
        after_transition on: :accept, do: :send_acceptance_email
        state :requested
        event :accept do
            transition any => :accepted
        end
    end
    def self.request(user1, user2)
      transaction do
        friendship1 = create(user: user1, friend: user2, state: 'pending')
        friendship2 = create(user: user2, friend: user1, state: 'requested')
        friendship1.send_request_email
        friendship1
      end
    end

    def send_request_email
        UserNotifier.friend_requested(id).deliver
    end
    def send_acceptance_email
        UserNotifier.friend_request_accepted(id).deliver
    end
    def mutual_friendship
        self.class.where({user_id: friend_id, friend_id: user_id}).first
    end
# Manually updating the state to avoid callbacks and infinite loops
    def accept_mutual_friendship
        mutual_friendship.update_attribute(:state, 'accepted')
    end
end

我知道我必须以某种方式改变这一点,但我不知道该怎么做。我希望这个页面显示用户的所有朋友,无论是处于接受状态还是挂起状态。有人能看到我需要做什么吗?

谢谢!

编辑:如果我将视图/user_friendships/index.html更改为friend.full_name,而不是@friend.ffull_name

另一个编辑:这是一个rails控制台条目,显示我在数据库中确实有用户友谊:

2.1.2 :003 > UserFriendship.all
  UserFriendship Load (0.3ms)  SELECT "user_friendships".* FROM "user_friendships"
 => #<ActiveRecord::Relation [#<UserFriendship id: 1, user_id: 6, friend_id: nil, created_at: "2014-10-04 14:20:42", updated_at: "2014-10-04 14:20:42", state: nil>, #<UserFriendship id: 2, user_id: 6, friend_id: nil, created_at: "2014-10-04 14:21:32", updated_at: "2014-10-04 14:21:32", state: nil>, #<UserFriendship id: 3, user_id: 6, friend_id: 3, created_at: "2014-10-04 14:21:50", updated_at: "2014-10-04 14:21:50", state: nil>, #<UserFriendship id: 4, user_id: 6, friend_id: 6, created_at: "2014-10-04 14:23:58", updated_at: "2014-10-04 14:23:58", state: nil>, #<UserFriendship id: 5, user_id: 6, friend_id: 6, created_at: "2014-10-04 14:25:05", updated_at: "2014-10-04 14:25:05", state: nil>, #<UserFriendship id: 6, user_id: 6, friend_id: 4, created_at: "2014-10-04 14:25:15", updated_at: "2014-10-04 14:25:15", state: nil>, #<UserFriendship id: 7, user_id: 6, friend_id: 6, created_at: "2014-10-04 20:42:40", updated_at: "2014-10-04 20:42:40", state: nil>, #<UserFriendship id: 8, user_id: 6, friend_id: 6, created_at: "2014-10-04 20:45:44", updated_at: "2014-10-04 20:45:44", state: nil>, #<UserFriendship id: 9, user_id: 6, friend_id: 6, created_at: "2014-10-04 21:38:17", updated_at: "2014-10-04 21:38:17", state: nil>, #<UserFriendship id: 10, user_id: 6, friend_id: 6, created_at: "2014-10-09 16:53:44", updated_at: "2014-10-09 16:53:44", state: "pending">, ...]>
2.1.2 :004 >

另一个编辑:这里是用户模型模型/user.rb:

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :confirmable, :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable
    validates :first_name, presence: true
    validates :last_name, presence: true
    validates :profile_name, presence: true, 
                             uniqueness: true,
                             format: {
                                with: /A.+z/,
                                message: "must be formatted correctly"
                             }
    has_many :statuses
    has_many :user_friendships
    has_many :friends, -> { where user_friendships: { state: 'accepted'} }, through: :user_friendships
    has_many :pending_user_friendships, -> { where state: 'pending' },
                                      class_name: 'UserFriendship', 
                                      foreign_key: :user_id
    has_many :pending_friends, through: :pending_user_friendships, source: :friend
    def full_name
        first_name + " " + last_name
    end
    def gravatar_url
        stripped_email = email.strip
        downcased_email = stripped_email.downcase
        hash = Digest::MD5.hexdigest(downcased_email)
        "http://gravatar.com/avatar/#{hash}"
    end
end

使用friend.full_name 代替@friend.fall_name

您已在此处定义<%friend=friendship.friend%>

所以我很确定发生的事情是,在我运行的rake db:migrate过程中,我的一些数据库表被删除了。我这么做是因为我在看一个类似的rails应用程序,它正在构建一个社交网站,并在两者之间来回切换我的数据库。不确定migrate是如何或为什么删除某些内容的(我相信它删除了名字和姓氏,这就是为什么full_name是一个零错误的原因)。我将恢复到以前的承诺,在那里一切都正常,并尝试从那里重建。

谢谢你的帖子!

tl;dr:不要在不知道自己在做什么的情况下运行db:migrate

相关内容

最新更新