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 trial

Ruby

Messaging with Rails

Hey folks,

I'm working on adding messaging to the Treebook framework. I've looked at using mailboxer - https://github.com/ging/mailboxer - and was wondering if anybody had any luck or experience with it.

3 Answers

Jason, thanks a ton for the reply! I figured that being the star that you are would preclude you from things like this. But in all seriousness I really appreciate it.

I played around with mailboxer for a couple days (including the accompanying 'rails-messaging' gem) and felt it was a little heavier-weight than I was looking for. So, I started updating an old Rails Messaging Tutorial and updating it for Rails 3.

Using this tutorial as a guide and Treebook's foundation (the same essential User and User_Friendship models) I was able to create an Inbox and Sent messages MVC (all playing nice with Devise). Where I've run into trouble is before and during the sent/create action.

I'm going to try and paste some code...

Models first:

class Message < ActiveRecord::Base
  belongs_to :author, :class_name => "User"
  has_many :message_copies
  has_many :recipients, :through => :message_copies
  before_create :prepare_copies

  attr_accessor  :to
  attr_accessible :subject, :body, :to

  def prepare_copies
  return if to.blank?

  else
    to.each do |recipient|
      recipient = User.find(recipient)
      message_copies.build(:recipient_id => recipient.id, :folder_id =>           
  recipient.inbox.id)
  end
 end
end


class MessageCopy < ActiveRecord::Base
  attr_accessible :folder_id, :message_id, :recipient_id

  belongs_to :message
  belongs_to :recipient, :class_name => "User"
  belongs_to :folder
  delegate   :author, :created_at, :subject, :body, :recipients, :to => :message
 end


class Folder < ActiveRecord::Base
 attr_accessible :name, :parent_id, :user_id

 acts_as_tree
 belongs_to :user
 has_many :messages, :class_name => "MessageCopy"
end

Controllers:

class SentController < ApplicationController
  def index
    @messages = current_user.sent_messages.paginate :per_page => 10, :page =>    params[:page], :order => "created_at DESC"
  end

  def show
    @message = current_user.sent_messages.find(params[:id])
  end

  def new
    @message = current_user.sent_messages.build
    @user_friendships = current_user.user_friendships.all
  end

  def create
    @message = current_user.sent_messages.build(params[:message])

   if @message.save
     flash[:notice] = "Message sent."
     redirect_to :action => "index"
   else
     render :action => "new"
    end
   end
  end


class MessagesController < ApplicationController
  def show
   @message = current_user.received_messages.find(params[:id])
  end
end


class MailboxController < ApplicationController
 def index
   @folder = current_user.inbox
 show
   render action: :show
 end

 def show
   @folder ||= current_user.folders.find(params[:id])
@messages = @folder.messages.paginate :per_page => 10, :page => params[:page], :include => :message, :order => "messages.created_at DESC"
  end
end

View:

sent/new

<h2>Compose</h2>

<%= simple_form_for :message, :url => {:controller => "sent", :action => "create"} do |f| %>
 <p>
To:
<select name="message[to][]">
  <%= options_from_collection_for_select(@user_friendships.find(:all), :id, @message.to) %>
</select>
 </p>
  <p>Subject: <%= f.input :subject %></p>
  <p>Body:<br /> <%= f.input :body %></p>
 <p><%= submit_tag "Send" %></p>
<% end %>

So, unless I'm mistaken, what I need to do is somehow iterate over the current_user's friends and make them selectable (or even better typeahead) -> then send that friend/user's user_id (not user_friendship_id or friend_id) and have that create a message_copy in def prepare_copies in the Message model when it iterates over the user_id param passed in :to. I've been playing around with options_from_collection_for_select and prepare_copies but I'm still getting errors.

Any thoughts on getting sent/new.html.erb and message.rb (model) to pass the right params?

Thanks again!

Jason Seifer
STAFF
Jason Seifer
Treehouse Guest Teacher

Try this:

In your user friendship model:

def friend_name
  friend.full_name
end

In your new page:

  <%= options_from_collection_for_select(@user_friendships, :id, :friend_name) %>

I'm not 100% sure that will work but give it a shot.

Jason Seifer
STAFF
Jason Seifer
Treehouse Guest Teacher

Hey Alexander, I've never used the mailboxer gem but it looks fine. I'd try following along with the sample application and making sure you know exactly what's going on in the gem first. You could even try using it as an example to implement your own version of a messaging system.