/ members的未定义方法的NoMethodError对于nil:NilClass的`friend_id'

时间:2013-12-22 09:34:33

标签: ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2

现在我正在尝试在用户的索引页面上添加“关注按钮”。

我的目标是......当用户按下按钮一次时,按钮旁边的消息变为“跟随”。并且他或她再次推动它,消息变成“不跟随”。默认消息是“不跟随”。

然后我写了下面的代码,但收到了错误信息。你能告诉我如何解决这个问题吗?

NoMethodError at /members undefined method `friend_id' for nil:NilClass

☆index.html.erb(members_controller)

<table class="table">
  <tr>
    <th>写真</th>
    <th>名前</th>

    <th>分野</th>
    <th>場所</th>
    <th>経験</th>
     <th>Follow</th>
    <%# if Member.find(session[:user_id]).admin %>
    <%# end %>
  </tr>
<% @members.each do |member| %>
  <tr>
    <td>
     <% if member.provider %>
        <%=image_tag member.image ,:size=>'30x30'%>
     <% elsif member.avatar_file_name %> 
        <%= image_tag member.avatar.url(:thumb), :width =>'30px', :height =>'30px' %>
     <% else %> 
        <%= image_tag "love.png", :size=>'30x30'  %>  
     <% end %>
    </td>
    <td>
      <a href="/members/<%= member.id %>"><%= member.name %></a>
       <% if member.provider == "facebook" %>
           <a target="_blank" href="http://www.facebook.com/<%=member.uid %>"> <%=image_tag "fb.png" ,:size=>'20x20'%>  </a>
        <% elsif member.provider == "twitter" %>
           <a target="_blank" href="http://www.twitter.com/<%=member.name %>"> <%=image_tag "twitter.png" ,:size=>'20x20'%>  </a>
       <% end %>
    </td>

    <td><%= member.field %></td>
    <td>
         <% if member.url.present? %>
           <%=link_to member.place ,member.url ,:target=>["_blank"] %> 
         <% else %>
          <%= member.place %>
        <% end %>  
      </td>
      <td><%= member.experience %></td>
      <td>
        <div class="onoff">
            <% unless session[:user_id] == member.id %>    
               <% if @isFr.friend_id == member.id %>
                  <%= link_to'off', {:controller => 'members', :action => 'index', :id =>
                  member.id}, class: "btn btn-midium btn-primary"%><br/>
                  ※following
                <% else %>
                   <%= link_to'on', {:controller => 'members', :action => 'index', :id =>
                  member.id}, class: "btn btn-midium btn-primary"%><br/>
                  ※not following
               <% end %>
             <% end %>  
         </div>
      <%#= member.friends.count %>
    </td>
     <% if Member.find(session[:user_id]).admin %>
         <td><%= link_to 'Destroy', member, method: :delete, data: { confirm: 'Are you sure?' } %></td>
     <% end %>

  </tr>
<% end %>
</table>

☆members_controller

  def index
    if !checklogin? then return end 
     @members = Member.where("id >=1").order("created_at desc").paginate(:page => params[:page], :per_page => 10).scoped
      if params[:name].present?
       @members = @members.where("name like ?" , "%" + params[:name] + "%")

      end

      if Friend.where(:member_id => session[:user_id], :friend_id => params[:id]).exists? then
       Friend.where(:member_id => session[:user_id], :friend_id => params[:id]).each do |f|
        f.destroy
        end
    else
       Friend.new({:member_id => session[:user_id], :friend_id =>params[:id].to_i}).save
    end


      @members.each do |m|
      @isFr = Friend.where(:member_id => session[:user_id], :friend_id => 
      m.id ).first
      end


       respond_to do |format|
           format.html # index.html.erb
           format.json
        end 

  end

☆sessions_controller #session [:user_id]

 auth = request.env["omniauth.auth"]
member = Member.find_by_provider_and_uid(auth["provider"], auth["uid"])


   session[:user_id] = member.id

3 个答案:

答案 0 :(得分:0)

这里的问题是索引操作中的实例var @isFr返回nil。这意味着代码Friend.where(:member_id => session[:user_id], :friend_id => m.id ).first返回nil。

您可以在您的成员#index视图中执行<% if @isFr.try(:friend_id) == member.id %>,这样您就不会得到NoM​​ethodError。

我在索引操作中找到的以下代码有问题:

@members.each do |m|
  @isFr = Friend.where(:member_id => session[:user_id], :friend_id => m.id ).first
end

上面代码的问题是@isFr只保留@members数组中最后一个元素的值。最好在Member模型中为这种行为添加一个方法,如下所示:

#in app/models/friend.rb
scope :get_member_id, ->(member, user_id) { where(:member_id => user_id, :friend_id => member.id ).first.try(:friend_id) }

然后在您的视图中使用它,如:

<% unless session[:user_id] == member.id %>   # below this line of code
  <% if Friend.get_member_id(member, session[:user_id]) == member.id %>

希望这有帮助!

答案 1 :(得分:0)

以下查询必须返回空白AR

@members = Member.where("id >=1")
                  .order("created_at desc")
                  .paginate(:page => params[:page], :per_page => 10).scoped

@isFr最终会产生nil

  @members.each do |m|
  @isFr = Friend.where(:member_id => session[:user_id], :friend_id => 
  m.id ).first
  end

你可以做一个重构词

Friend.where(:member_id => session[:user_id], :friend_id => @members.map(&:id)) .limit(1)

但如果你考虑模型之间的associations会更好。这样它将使用连接查询进行优化

答案 2 :(得分:0)

感谢那些给我提示的人,我使用下面的代码制作了它。

☆index.html.erb(members_controller)

 <td>
        <div class="onoff">
            <% unless session[:user_id] == member.id %>    
                 <% if @Frids.include? member.id%>
                  <%= link_to'Off', {:controller => 'members', :action => 'index', :id =>
                  member.id}, class: "btn btn-midium btn-warning"%><br/>
                  ※既follow
                <% else %>
                   <%= link_to'On', {:controller => 'members', :action => 'index', :id =>
                  member.id}, class: "btn btn-midium btn-primary"%><br/>
                  ※未follow
               <% end %>
             <% end %>  
         </div>
      <%#= member.friends.count %>
    </td>

☆members_controller

def index
    if !checklogin? then return end 
     @members = Member.where("id >=1").order("created_at desc").paginate(:page => params[:page], :per_page => 10).scoped

      if Friend.where(:member_id => session[:user_id], :friend_id => params[:id]).exists? then
       Friend.where(:member_id => session[:user_id], :friend_id => params[:id]).each do |f|
        f.destroy
        end  
      else
       Friend.new({:member_id => session[:user_id], :friend_id =>params[:id].to_i}).save
      end

      @Frids =Friend.where(:member_id => session[:user_id]).map{|x| x.friend_id}

       respond_to do |format|
           format.html # index.html.erb
           format.json
        end 

  end