Ruby错误NoMethodError for nil:NilClass

时间:2014-10-13 01:13:09

标签: ruby-on-rails ruby

我正在使用rails跟踪teamtreehouse.com上的Treebook教程(制作一个facebook克隆)。我创建了一个userfriendships控制器,并且在友谊视图的index.html页面中尝试引用朋友的全名时出现此错误:未定义的方法`full_name'为nil:NilClass 。问题出现在第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

我知道我必须以某种方式改变这一点,但我不知道如何做到这一点。我希望此页面显示用户拥有的所有朋友,无论是处于已接受状态还是待处理状态。谁能看到我需要做什么?

谢谢!

编辑:如果我将views / user_friendships / index.html更改为 friend.full_name 而不是 @ friend.full_name ,我仍然会收到相同的错误。我可以验证当前在db中的用户是否都有一个有效的名字和姓氏(因此全名方法应该有效)。

另一个编辑:这是一个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 >

另一个编辑:这是用户模型models / 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

2 个答案:

答案 0 :(得分:0)

而不是@ friend.full_name使用friend.full_name

您已在此处定义&lt;%friend = friendship.friend%&gt;

答案 1 :(得分:0)

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

感谢帖子!

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