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 trialMatthew Hartwig
3,941 PointsDraper 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
Treehouse Guest TeacherYulai 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
7,625 PointsIn 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
Treehouse Guest TeacherHey Matthew, it looks like the requested state is missing from the UserFriendship state machine and User model. Try double checking that.
Matthew Hartwig
3,941 Pointsuser_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.
Matthew Hartwig
3,941 Pointsclass 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
Matthew Hartwig
3,941 PointsAlso 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
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
8,916 PointsAnd it looks like it's still looking for a user id, but using the username instead.
{"friend_id"=>"brookethomas", "id"=>"brookethomas"}
George Petrov
9,663 PointsStuck 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
7,904 PointsI'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
Treehouse Guest TeacherTry adding the following to your UserFriendshipDecorator just below the class name:
delegate_all
And let me know if that fixes it.
Dean Phillips
22,260 PointsThank you...that fixed it for me! Thanks for your help and all your contributions to this Rails library.
Niall Ryan
7,904 PointsI already have delegate_all below the class name.
Any other ideas?
Jason Seifer
Treehouse Guest TeacherNiall Can you zip up your code and email it to help@teamtreehouse.com and I'll take a look?
Yulai Fjeld
680 PointsI 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""
Philipp Antar
7,216 Pointssame problem here, same code as well.
Niall Ryan
7,904 PointsI'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.
Yulai Fjeld
680 Points@Niall, will do that and post the solution here once the error is found.
Philipp Antar
7,216 Pointsit 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
Full Stack JavaScript Techdegree Student 3,008 PointsHi 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
Full Stack JavaScript Techdegree Student 3,008 PointsThis 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
Jason Seifer
Treehouse Guest TeacherShaun Koo can you email your code to help@teamtreehouse.com?