Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

Ruby

Draper Decorator Causing Problems

edit method

def edit 
    @friend = User.where(profile_name: params[:id]).first
    @user_friendship = current_user.user_friendships.where(friend_id: @friend.id).first.decorate
end

Decorator

class UserFriendshipDecorator < Draper::Decorator

  decorates :user_friendship

  def friendship_state
    model.state.titleize
  end

  def sub_message
    case model.state
    when 'pending'
        "Do you really want to be friends with #{model.friend.first_name}?"
    when 'accepted'
        "You are friends with #{model.friend.first_name}"
    end
  end
end

edit.html.erb

   <div class= "page-header">
    <h1>Edit Friendships</h1>
</div>

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

<div class="form_actions">
        <% if @user_friendship.requested? %>
            <%= form_for @user_friendship, url:     accept_user_friendship_path(@user_friendship), method: 
                :put do |form| %>
            <%= submit_tag "Accept Friendship", class: 'btn btn-primary' %>
            <% end %>
    <% end %>

    <%= form_for @user_friendship, url: user_friendship_path(@user_friendship), method: 
    :delete do |form| %>
            <%= submit_tag "Delete Friendship", class: 'btn btn-danger' %>
        <% end %>

</div>

When I try to edit the friendship it produces this error in the browser

undefined method 'requested?' for <UserFriendshipDecorator:0xb66ed28>

My tests cause errors as well

test: #edit when logged in should get edit and return success.   (UserFriendshipsControllerTest):
RuntimeError: Called id for nil, which would mistakenly be 4 -- if you really wanted the  id of nil, use object_id

20 Answers

Jason Seifer
STAFF
Jason Seifer
Treehouse Guest Teacher

Yulai sent me over the code and the issue is in app/views/user_friendships/index.html.erb. In the lessons, we change the code to use the profile name rather than the id when viewing/editing friendships. The solution is to change the following:

edit_user_friendship_path(friendship)

To:

edit_user_friendship_path(friendship.friend.profile_name)
Alan Johnson
Alan Johnson
7,625 Points

In the case of the test failure, I would double check that your test is calling edit with a valid id parameter. User.where(...).first will return nil if it doesn't find anything.

I'm not sure about the decorator, but I'd definitely do a quick check to make sure that your db has the requested column. That could be the issue. Every once in a while migrations will get in a weird spot, and columns that you think should be there won't be.

Jason Seifer
STAFF
Jason Seifer
Treehouse Guest Teacher

Hey Matthew, it looks like the requested state is missing from the UserFriendship state machine and User model. Try double checking that.

user_friendship.rb has the requested state

class UserFriendship < ActiveRecord::Base

    belongs_to :user
    belongs_to :friend, class_name: 'User', foreign_key: 'friend_id'

    attr_accessible :user, :friend, :friend_id, :user_id, :state

    after_destroy :delete_mutual_friendship!

    state_machine :state, initial: :pending do

        state :requested

        after_transition on: :accept, do: :accept_mutual_friendship!
            after_transition on: :accept, do: [:send_acceptance_email, :a   ccept_mutual_friendship!]
        event :accept do
            transition any => :accepted
        end

    end

Everything functioned and all tests passed until I added the decorator.

class User < ActiveRecord::Base
  # Include default devise modules. Others available are:
  # :token_authenticatable, :confirmable,
  # :lockable, :timeoutable and :omniauthable
  devise :database_authenticatable, :registerable,
         :recoverable, :rememberable, :trackable, :validatable

  # Setup accessible (or protected) attributes for your model
  attr_accessible :email, :password, :password_confirmation, :remember_me,
                  :first_name, :last_name, :profile_name

  validates :first_name, presence: true
  validates :last_name, presence: true
  validates :profile_name, presence: true,
                           uniqueness: true,
                           :format => { :with => /^[a-z0-9\-_]+$/,
    :message => 'Must be formatted correctly'}

  has_many :statuses
  has_many :user_friendships
  has_many :friends, through: :user_friendships,
                     conditions: {user_friendships: {state: 'accepted'}}
  has_many :pending_user_friendships, class_name: 'UserFriendship',
                                      foreign_key: :user_id,
                                      conditions: {state: 'pending'}
  has_many  :pending_friends, through: :pending_user_friendships, source: :friend 

Also when I try to delete a pending request I get the following:

RuntimeError in UserFriendshipsController#edit

Called id for nil, which would mistakenly be 4 -- if you really wanted the id of nil, use     object_id

app/controllers/user_friendships_controller.rb:63:in `edit'
Request

Parameters:

{"id"=>"1"}

user_friendships_controller.rb:63

def edit 
        @friend = User.where(profile_name: params[:id]).first
        @user_friendship = current_user.user_friendships.where(friend_id:     @friend.id).first.decorate
    end
Jon Thomas
Jon Thomas
8,916 Points

:( I keep getting a similar error as well. I just did a file diff compare and I cannot find what I did wrong. My app is broken and I'm so close to done!!!

Rendered user_friendships/edit.html.erb within layouts/application (2.0ms)
Completed 500 Internal Server Error in 10ms

ActionView::Template::Error (undefined method `user' for #    <UserFriendshipDecorator:0x007fb943ecaf78>):
    4: 
    5: <div class="row">
    6:   <div class="avatar span2">
    7:     <%= image_tag @user_friendship.user.gravatar_url %><br />
    8:     <%= @user_friendship.user.first_name %>
    9:   </div>
    10:   <div class="avatar span2">
  app/views/user_friendships/edit.html.erb:7:in     `_app_views_user_friendships_edit_html_erb___4442761444483375981_70216842643    040'
Jon Thomas
Jon Thomas
8,916 Points

And it looks like it's still looking for a user id, but using the username instead.

{"friend_id"=>"brookethomas", "id"=>"brookethomas"}

George Petrov
George Petrov
9,663 Points

Stuck on the same part, same error, code matches the files I downloaded from the course.

It started failing around the 3-rd AJAX video with 3 errors concerning the #edit test in user_friendships_controller_test.rb

Niall Ryan
Niall Ryan
7,904 Points

I'm having the same problem with the edit action in the User Friendships Controller, code returns nil instead of an id.

Anyone able to shed some light on this?

Jason Seifer
STAFF
Jason Seifer
Treehouse Guest Teacher

Try adding the following to your UserFriendshipDecorator just below the class name:

delegate_all

And let me know if that fixes it.

Dean Phillips
Dean Phillips
22,260 Points

Thank you...that fixed it for me! Thanks for your help and all your contributions to this Rails library.

Niall Ryan
Niall Ryan
7,904 Points

I already have delegate_all below the class name.

Any other ideas?

Jason Seifer
STAFF
Jason Seifer
Treehouse Guest Teacher

Niall Can you zip up your code and email it to help@teamtreehouse.com and I'll take a look?

I am running into the same problem. Whenever trying to accept, delete or update a friendship, I get the following error message:

RuntimeError (Called id for nil, which would mistakenly be 8 -- if you really wanted the id of nil, use object_id):
app/controllers/user_friendships_controller.rb:58:in `edit'

My user_friendships_controller.rb:58:in 'edit' reads:

    def edit
    @friend = User.where(profile_name: params[:id]).first
    @user_friendship = current_user.user_friendships.where(friend_id:@friend.id).first.decorate
end

Any ideas on how to fix this would be highly appreciated.

** I already have delegate_all in the UserFriendshipController file""

same problem here, same code as well.

Niall Ryan
Niall Ryan
7,904 Points

I'm away from my code until Monday but I was getting the same error as Yulai.

Yulai or Philipp, perhaps you could forward your code to Jason in my place if we're all getting the same error.

@Niall, will do that and post the solution here once the error is found.

it works! No more 'calling id for nil'. Thanks Jason!

I spent an hour pondering the controller code and didn't realize the view was causing trouble.

Shaun Koo
seal-mask
.a{fill-rule:evenodd;}techdegree
Shaun Koo
Full Stack JavaScript Techdegree Student 3,008 Points

Hi all, I made the changes to the view and I am still running into the decorator nil NilClass error.

This is my user_friendship_controller_test module:

```context "#edit" do context "when not logged in" do should "redirect to the login page" do get :edit, id: 1 assert_response :redirect end end

context "when logged in" do
    setup do
        @user_friendship = create(:pending_user_friendship, user: users(:shaun))
        sign_in users(:shaun)
        get :edit, id: @user_friendship.friend.profile_name
    end

    should "get edit page and return success" do
        assert_response :success
    end

    should "assign to user friendship" do
        assert assigns(:user_friendship)
    end

    should "assign to friend" do
        assert assigns(:friend)
    end

end

end ```

Shaun Koo
seal-mask
.a{fill-rule:evenodd;}techdegree
Shaun Koo
Full Stack JavaScript Techdegree Student 3,008 Points

This is my user_friendship controller:

def edit @friend = User.where(profile_name: params[:id]).first @user_friendship = current_user.user_friendships.where(friend_id: @friend_id).first.decorate end