Search code examples
ruby-on-railsrubyruby-on-rails-4rubygemsmailboxer

(undefined method `receipts_for' for nil:NilClass - MailBoxer Gem Rails


I'm using the mailboxer gem to build a messaging system between users for my rails application. For some reason, I'm getting this error:

(undefined method `receipts_for' for nil:NilClass)

Maybe it's because I should define 'receipts_for' somewhere in my controller or in the mailboxer.rb? I tried a few things.. but unfortunately none of them were successful.

This is my routes.rb:

Rails.application.routes.draw do
  root   'static_pages#home'
  get    '/help',    to: 'static_pages#help'
  get    '/about',   to: 'static_pages#about'
  get    '/contact', to: 'static_pages#contact'
  get    '/signup',  to: 'users#new'
  get    '/login',   to: 'sessions#new'
  get    'search/index'
  post   '/login',   to: 'sessions#create'
  delete '/logout',  to: 'sessions#destroy'
  resources :users do
    member do
      get :following, :followers
    end
  end
  resources :conversations do
    resources :messages
  end
  resources :account_activations, only: [:edit]
  resources :password_resets,     only: [:new, :create, :edit, :update]
  resources :microposts,          only: [:create, :destroy]
  resources :relationships,       only: [:create, :destroy]
  resources :searches
end

This is my conversations controller:

class ConversationsController < ApplicationController

  def show
    @conversation = current_user.mailbox.conversation.find(params[:id])
  end


  def new
    @recipients = User.find(params[:user_id])
  end

  def create
    recipient = User.find(params[:user_id])
    receipt = current_user.send_message(recipient, params[:body])
    redirect_to conversation_path(receipt.conversation)
  end

end

This is my messages_controller:

class MessagesController < ApplicationController
  before_action :set_conversation

  def create
    receipt = current_user.send_message(@conversation, body)
    redirect_to receipt.conversation
  end

  private

  def set_conversation
    @conversation = current_user.mailbox.conversations.find(params[:conversation_id])
  end

end

The messaging system I'm building precisely, is a messaging system where the 'current_user' can go to the profile page of any user on the application and message him/her via the profile page. So this means that I'm rendering show.html.erb of the conversation model inside the show.html.erb of my users model. Here is the code of both views:

show.html.erb - Users Model:

<% provide(:title, @user.name) %>
<div class="row">
  <aside class="col-md-4">
    <section>
      <h1>
        <%= gravatar_for @user %>
        <%= @user.name %>
      </h1>
    </section>
    <section class="stats">
      <%= render 'shared/stats' %>
    </section>
      <h6>
        <%= @user.gender %>
      </h6>
    <%= render "conversations/conversation" %>
  </aside>
  <div class="col-md-8">
    <%= render 'follow_form' if logged_in? %>
    <% if @user.microposts.any? %>
      <h3>Microposts (<%= @user.microposts.count %>)</h3>
      <ol class="microposts">
        <%= render @microposts %>
      </ol>
      <%= will_paginate @microposts %>
    <% end %>
  </div>
</div>

_conversation.html.erb - show view of the conversations model.

<% @conversation.receipts_for(current_user).each do |receipt| %>
    <div>
        <%= receipt.message.body %>
    </div>
<% end %>


<%= form_tag conversation_messages_path(@conversation), method: post do  %>
    <div>
        <%= text_area_tag :body %>
    </div>

    <%= submit_tag %>
<% end %>

So how exactly can I define the 'receipts_for' method for my mailboxer? Or is something else wrong with my code?

Any help would be much appreciated!

Thanks!


Solution

  • I’ll piggy-back on what @mu is too short said. It’s important to pay attention to the whole error message. “undefined method receipts_for for nil:NilClass” is telling you that the receiver of the receipts_for method is nil. @conversation.receipts_for(current_user) looks to be the only place where receipts_for is used, so I would start debugging by making sure @conversation is assigned the value of an existing ActiveRecord-backed conversation object.

    There seems to be too a lot going on, so I don't know how to offer you a quick fix. The value assignment in your ConversationsController#show method, @conversation= current_user.mailbox.conversation.find(params[:id]) looks cumbersome. That suggests to me that you're looking for a conversation based on a mailbox belonging to the current_user, which might be what you want (in which case, you need to have the appropriate associations defined in your models).

    However, since the chain ends with conversation.find(params[:id]), I'm guessing that current_user.mailbox is not needed. Alternatively, if your params don't actually have a conversation id, then maybe that's what you need to focus on.

    The good news is you can probably figure out how to define @conversation if you stick byebug (or binding.pry, depending on what you have installed) at the top of your show method and in your view partial:

    # In the controller:
    
      def show
        binding.pry
        @conversation = current_user.mailbox.conversation.find(params[:id])
      end
    
    
    # in the view
    <% binding.pry %>