MKK
MKK

Reputation: 2753

How to avoid the error on nil object

Record id 116 doesn't exist so it should return nil to @conversation.
I tried to make it redirect when it gets nil, but it still shows the error when I access example.com/messages/show?id=116 .

The error is

undefined method `is_participant?' for nil:NilClass

I definitely see 'is_participant' method existing in
/usr/local/lib/ruby/gems/1.9.1/gems/mailboxer-0.7.0/app/models/conversation.rb

messages_controller.rb

def show
  @conversation = Conversation.find_by_id(params[:id])

  unless @conversation.is_participant?(current_user)
    flash[:alert] = "You do not have permission to view that conversation."
    redirect_to :controller => 'messages', :action => 'received'
  end

  @messages = Message.find_by_id(params[:id])
  current_user.read(@conversation)    
end

Upvotes: 2

Views: 2563

Answers (3)

Erez Rabih
Erez Rabih

Reputation: 15788

Christoph Petschnig answer is right, just wanted to mention there is a nice shorthand for

unless @conversation.present? && @conversation.is_participant?(current_user)

which is

unless @conversation.try(:is_participant? , current_user)

try will return nil is @conversation is nil which eventually evaluates to false in the if statement.

Upvotes: 2

Ismael
Ismael

Reputation: 16710

You can check for presence of a value or rescue for that error.

def show
  @conversation = Conversation.find_by_id(params[:id])

  redirect_to somewhere_path if @conversation.nil?

  unless @conversation.is_participant?(current_user)
    flash[:alert] = "You do not have permission to view that conversation."
    redirect_to :controller => 'messages', :action => 'received'
  end

  @messages = Message.find_by_id(params[:id])
  current_user.read(@conversation)    
end

or the Rescue!

def show
  @conversation = Conversation.find_by_id(params[:id])

  unless @conversation.is_participant?(current_user)
    flash[:alert] = "You do not have permission to view that conversation."
    redirect_to :controller => 'messages', :action => 'received'
  end

  @messages = Message.find_by_id(params[:id])
  current_user.read(@conversation)    

rescue NoMethodError
  redirect_to somewhere_path
end

Notice that the rescue way is not very friendly, since it can rescue other error and making you have a pain to debug some errors. For example if current_user has no method named read, it would throw and error that would be catch there and you wouldn't notice it came from there.

Upvotes: 1

Christoph Petschnig
Christoph Petschnig

Reputation: 4147

You need to check that @conversation is not nil before you call a method on it. Try

unless @conversation.present? && @conversation.is_participant?(current_user)

Upvotes: 3

Related Questions