Search code examples
ruby-on-railsmessageinbox

Creating Inbox/Outbox Pages


Apologize for the newbie question, but I'm working on a messaging feature for my web app right now, and trying to separate received messages from sent messages. Sort of like an inbox/outbox. Is it possible to create separate index pages for sent messages and received messages? If anyone has done something like this, I would really appreciate any guidance that you could offer. My code it below, Thanks!:

routes.rb:

Application.routes.draw do

  devise_for :users, :controllers => { :registrations => "registrations" }

  devise_scope :user do
    get 'register', to: 'devise/registrations#new'
    get 'login',    to: 'devise/sessions#new',     as: :login
    get 'logout',   to: 'devise/sessions#destroy', as: :logout
  end

  resources :users do
    member do
     get 'edit_profile'
   end
  resources :messages, only: [:new, :create]
  end

  resources :messages

  root to: "home#index"
  match '/about',   to: 'static_pages#about',   via: 'get'
  match '/contact', to: 'static_pages#contact', via: 'get' 
  match '/help',    to: 'static_pages#help',    via: 'get'
  match '/legal',   to: 'static_pages#legal',   via: 'get'

end

messages_controller.rb

class MessagesController < ApplicationController

  def index
    @messages = current_user.to_messages
  end

  def show
    @message = current_user.to_messages.find params[:id]
  end

  def new
    @message = Message.new
    @recipient = User.find(params[:user_id])
  end

  def create
    @message = Message.new message_params
    @message.sender_id = current_user.id
    if @message.save
      flash[:success] = "Your message has been sent!"
      redirect_to users_path
    else
      flash[:failure] = "Please try again."
      redirect_to users_path
    end
  end

  def destroy
    @message = Message.find(params[:id])
    @message.destroy
    redirect_to messages_path
  end

  private

  def message_params
    params.require(:message).permit(:content, :sender_id, :recipient_id)
  end

end

messages.rb

class Message < ActiveRecord::Base
  belongs_to :sender, class_name: 'User', foreign_key: 'recipient_id'
  belongs_to :recipient, class_name: 'User', foreign_key: 'sender_id'

  validates :content, presence: true, length: { maximum: 500 }
  validates :sender_id, presence: true
  validates :recipient_id, presence: true

  attr_accessible :sender_id, :recipient_id, :content
end

Solution

  • Messages

    Don't make different "index" views - just create inbox and outbox views for the messages controller instead:

    #config/routes.rb
    resources :users do
       resources :messages
    end
    
    resources :messages do 
         get :sent, action: "index", type: "sent", on: :collection #-> domain.com/messages/sent
    end
    

    This will give you the ability to create the following:

    #app/models/user.rb
    class User < ActiveRecord::Base
       has_many :to_messages ...
       has_many :from_messages ...
    end
    
    #app/controllers/messages_controller.rb
    class MessagesController < ApplicationController
       def inbox
           type = (params[:type] && params[:type] == "sent") ? "from_messages" : "to_messages"
           @messages = current_user.send(type)
       end
    end
    

    This will give you the ability to access the "inbox" and "outbox" routes with the following URLs:

    domain.com/messages #-> messages#index
    domain.com/messages/sent #-> messages#index(type=sent) 
    

    I estimated that you'll have authenticated the User model (IE that you'll be authenticated whenever you access it). The difference is in the data you retrieve from the model -- if you access the sent route, you'll be able to access the "from" messages, whilst if you access the standard "index", it should just show an "inbox" of the to_messages


    Associations

    One of the most important aspects of what you're trying to achieve will be how you're storing / accessing your data from your Message model.

    You'll no doubt have a way to manage who the message was "from", and who it's "to". This data allocation will determine how you can access the required data you want.

    I'd use the following:

    #app/models/user.rb
    class User < ActiveRecord::Base
       has_many :to_messages #-> messages with user_id" 
       has_many :from_messages #-> messages with "from_id"
    end
    

    If you update your question with information about your User associations - it will give me some better info to work with, hence allowing me to give you a more structured reply!