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!
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 %>