Search code examples
ruby-on-railsvariablesdecoratornomethoderror

NoMethodError in RelationshipsController#edit undefined method `decorate' for nil:NilClass


So I know where the problem is, but I'm fairly new to ROR and don't know how to work out what methods are available/which variables I should be using.

What I'm trying to do:

a user should be directed to views/relationship/edit when they press 'edit relationship'. the variables should correspond so the edit relationship page deals with an accepted, pending or requested relationship between the current_user and the person they're trying to connect to (followed)

  1. if a relationship exists in any state, show the edit button. (works)
  2. click edit button (this is where the error comes up)
  3. show edit page for the relationship between current user and person theyre trying to connect to. (where can accept/delete request)

i don't know why it's saying there is no decorator method - it was working before..

error:

NoMethodError in RelationshipsController#edit
undefined method `decorate' for nil:NilClass

Extracted source (around line #71):

    # @relationship = current_user.active_relationships.find(params[:id]).decorate
    @followed = User.find_by(name: params[:id])
    @relationship = current_user.pending_relationships.find_by(followed_id: @followed).decorate
  end

view/users/index:

<% if logged_in? %>
    <ul>
        <% @users.each do |user| %>
            <li>
                <%= user.name %>
                <div id="relationship-status">
                    <% if current_user.following.include?(@followed) || current_user.pending_following.include?(user) || current_user.requested_following.include?(user) %>
                        <%= link_to "Edit Relationship", edit_relationship_path(followed_id: @followed, id: current_user.id), class: "btn btn-primary" %>
                        followed: <%= @followed %>
                        current_user: <%= current_user.id %>
                        relationship: <%= @relationship %>
                    <% else %>
                        <%= link_to "Add Relationship", new_relationship_path(follower_id: user.id), class: "btn btn-primary", id: 'add-relationship', data: { followed_id: user.id.to_param } %>
                    <% end %>
                </div>
            </li>
        <% end %>
    </ul>
<% end %>   

relationships_controller:

  def edit
    # @followed = @relationship.followed
    # @relationship = current_user.active_relationships.find(params[:id]).decorate
    @followed = User.find(name: params[:id])
    @relationship = current_user.pending_relationships.find_by(followed_id: @followed).decorate
  end

views/relationship/edit:

    <div class="page-header">
        <h1>Viewing Relationship</h1>
    </div>

    <h3><%= @relationship.sub_message %></h3>

    <div class="form-actions">
        <% if @relationship.requested? %>
            <%= form_for @relationship, url: accept_relationship_path(@relationship), method: :put do |form| %>
                <%= submit_tag "Accept Relationship", class: 'btn btn-primary' %>
            <% end %>
        <% end %>
    </div>

    <%= form_for @relationship, url: relationship_path(@relationship), method: :delete do |form| %>
        <%= submit_tag "Delete Relationship", class: 'btn btn-danger' %>

<% end %>

model/user:

class User < ActiveRecord::Base
  has_one :profile, dependent: :destroy
  has_many :pending_relationships,  class_name:  "Relationship",
                                    foreign_key: "follower_id"
  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 :following, -> { where(relationships: { state: "accepted" } ) }, through: :active_relationships,  source: :followed
  has_many :followers, through: :passive_relationships, source: :follower                              
  has_many :pending_following, -> { where(relationships: { state: "pending" } ) }, through: :pending_relationships,  source: :followed
  has_many :requested_following, -> { where(relationships: { state: "requested" } ) }, through: :pending_relationships,  source: :followed

...

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

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

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

  def pending_following?(user)
    pending_following.include?(user)
  end

  def requested_following?(user)
    pending_following.include?(user)
  end

user db table: user db table

relationship controller:

class RelationshipsController < ApplicationController
  before_action :logged_in_user,  only: [:new, :create, :index, :accept, :edit, :destroy]
  respond_to :html, :json

  def new
    if params[:followed_id]
      @followed = User.find(params[:followed_id])
      @active_relationship = current_user.active_relationships.new(followed: @followed)
    else
      flash[:danger] = "Relationship required"
    end

  rescue ActiveRecord::RecordNotFound 
    render 'public/404', status: :not_found
  end

  def create
    if params[:relationship] && params[:relationship].has_key?(:followed_id)
      @followed = User.find(params[:relationship][:followed_id])
      # @followed = User.where(name: params[:relationship][:followed_id]).first
      @relationship = Relationship.request(current_user, @followed)
      respond_to do |format|
        if @relationship.new_record?
          format.html do
            flash[:danger] = "There was a problem creating that relationship request"
            redirect_to followed_path(@followed)
          end
          format.json { render json: @relationship.to_json, status: :precondition_failed }
        else
          format.html do
            flash[:success] = "Friend request sent"
            redirect_to followed_path(@followed)
          end
          format.json { render json: @relationship.to_json }
        end
      end
    else
      flash[:danger] = "Friend Required"
      redirect_to users_path
    end
  end

  # def create
  #   if params[:followed_id]
  #     @followed = User.find(params[:followed_id])
  #     current_user.follow(@followed)
  #     redirect_to user
  #   else 
  #     flash[:danger] = "else statement"
  #   end
  # end

  def accept
    @relationship = current_user.active_relationships.find(params[:id])
    if @relationship.accept!
      flash[:success] = "You are now connected with #{@relationship.followed.name}"
    else
      flash[:danger] = "That connection could not be accepted."
    end
    redirect_to relationships_path
  end

  def index
    @relationships = current_user.active_relationships.all
    @followed = User.find_by(name: params[:id])
  end

  def edit
    #orig
    # @followed = @relationship.followed
    # @relationship = current_user.active_relationships.find(params[:id]).decorate

    #2nd
    # @followed = User.find_by(name: params[:id])
    # @relationship = current_user.pending_relationships.find_by(followed_id: @followed).decorate

    # stack
    # @followed = User.find_by(id: params[:id])
    # @relationship = current_user.pending_relationships.find_by(followed_id: @followed).decorate

    #stack2
    @followed = User.find_by(id: params[:id])
    @relationship = current_user.pending_relationships.find_by(follower_id: @followed.id).decorate
  end

  def destroy
   ...
  end
end

Solution

  • You are finding users by name but passing "ID" for the condition, so it is not able to retrieve corresponding records. Change this and Try Once:

     def edit
        # @followed = @relationship.followed
        # @relationship = current_user.active_relationships.find(params[:id]).decorate
        @followed = User.find_by(id: params[:id])
        @relationship = current_user.pending_relationships.find_by(follower_id: @followed.id).decorate
      end
    

    Update:

    You have specified follower_id as foreign key for your pending relationships try the above edit method. I have updated it.