Problem:
Private messaging in Rails.
Solution:
What it do?
acts_as_messageable is a plugin for enabling private messaging between users. Conversations, multiple recipients, trash, sentbox... its all in there.
to install:
> script/plugin install http://actsasmessageable.googlecode.com/svn/tags/acts_as_messageable-1.0.1 > script/generate messageable > rake db:migrate
to use:
class User < ActiveRecord::Base acts_as_messageable end
sending:
phil = User.find(3123) todd = User.find(4141) phil.send_message(todd, "whats up for tonight?", "hey guy")
sends a mail to todd's inbox and puts the sent message in phil's sentbox.
retrieving:
todd.mailbox[:inbox].unread_mail
returns an array of all unread mail messages in todd's inbox.
replying:
mail = todd.mailbox[:inbox].unread_mail[0] todd.reply_to_sender(mail, "not sure, probably having a few dozen cocktails.")
replys to the sender of the mail message. (Messages can be sent to multiple users, and are conversation based. See the RDoc.)
moving / deleting:
convo = mail.conversation todd.mailbox.move_to(:trash, :conversation => convo)
moves all mail messages to the 'trash' that are part of the given conversation. There are 3 default mailboxes for each user (:inbox, :sentbox, :trash), although any name can be passed to this method if you wanted to implement folders.
bonus:
todd.mailbox[:inbox].latest_mail
returns the last message received for each conversation you are involved in. Pretty sweet for an inbox view.
Check the RDoc.

33 comments:
Phil,
Are you currently using this in a project, and if so how large? If I may ask.
yes I am currently using this on bandsintown.com.
Awesome! Thanks Phil! This is a really nice little plugin and fairly well documented. I'm trying to implement a little message system with it now and I think I'm missing something (like confusing Messages and Mail) because I can't figure out how to get individual Message objects directly from the mailbox...
I'd like to do something like this:
@messages = current_user.mailbox[:inbox].messages
but, instead I'm using the very cludgy:
current_user.mailbox[:inbox].mail.each do |mail|
@messages << Message.find(mail.message_id)
end
Can someone post an example of the best way to get an individual message or array of messages to send to an inbox or message view?
Thanks!
Peter
ps. Bandsintown.com is pretty sweet...
A mail is just basically a wrapper for a message which holds individual info on the message (read, trashed, mailbox). So if someone sent a message to 20 recipients there would only be 1 message created and 20 mails.
It was confusing for me building it too but I believe this is the correct approach.
I think what you are actually after are the mail objects. If you go directly to the messages then you can not see the read state.
so you could just render the mail array as a collection and access the info with:
mail.message.message
mail.message.subject
mail.read
I also use CachedModel on my messages which really speeds this up.
latest_mail() is also really nice for an inbox view if you are going with the conversation approach... similar to how gmail inbox works, only showing you the latest message for each convo you are involved in.
Im on no sleep so I hope im making sense... let me know if you have any other questions.
glad you like bandsintown.
Aahhh, I see... yes, that's exactly what I wanted. I'll check out CachedModel next and maybe dive into the folder & conversation features later... Thanks again!
no problem... glad to see youre using it.
Could you please post some examples how to write the controller and views? The stuff posted above doesn't really say anything. Nor does the Rdoc...
I will post some more examples later on tonight.
I don't want to push you or anything... ;) Put you got some examples up your sleeve? Else I move on to another plugin that I know works out-of-the-box.
It does work out of the box i just chose not to include controller/views because they tend to be very custom... anyway here are some examples:
example url:
-------------
#user/:id/mail/:type
/user/3/mail/inbox
controller:
-------------
def mail()
@user = User.find(params[:id])
@mail = @user.mailbox[params[:type]].latest_mail
end
view:
------------
<%= render(:partial => '/shared/mail', :collection => @mail %>
in that partial you could just access the mail info through:
mail.message.message
mail.message.subject
mail.read
Just a simple example but that should get you going.
-Phil
looks cool. I am going to use it right way in my project. Will post the experience
I have posted an issue that was occurring in migration
http://code.google.com/p/actsasmessageable/issues/detail?id=1
Also can you plz post the routes that you are using in your project esp the nested one.
Thanks,
Aroop
@aroop
Thanks for reporting that bug, I have applied a fix and the new version is available here:
http://actsasmessageable.googlecode.com/svn/tags/acts_as_messageable-1.0.1
also for the routes im using something like this:
/user/:id/mail/:mailbox_type
(for inbox, sentbox, trash, etc.)
/user/:id/convo/:convo_id
(for reading conversations)
here is the new version link if you can't see it in my last comment:
new version
Phil,
Your site (BandsInTown) absolutely rocks! Congrats!
Is the acts_as_messageable plugin already Rails 2.0 compatible?
Cheers, Sazima
I am not sure, I havent made the switch yet. If you find out please let me know.
Phil,
Apparently "acts_as_messageable" is Rails 2.0.2 compatible!
But unfortunately I'm very confused on how to use it...
Any chance you could post or send me an example application (basically routes, controllers and views)?
Cheers, Sazima
Hello. This post is likeable, and your blog is very interesting, congratulations :-). I will add in my blogroll =). If possible gives a last there on my blog, it is about the Celular, I hope you enjoy. The address is http://telefone-celular-brasil.blogspot.com. A hug.
Phil,
This is a wicked plugin, great job!!! I am however, trying to implement this plugin along with the Goldberg authentication plugin, and running into problems. The Goldberg plugin has a user table, with a user.rb which includes a Goldberg module. I basically tried to change reference class_names from User to Goldberg::User and encounter an error stating 'undefined method 'mail' for Goldberg::User:class..I also tried to create a user.rb with the following inheritance
User < Goldberg::User and get the same error..but stating 'undefined method 'mail' for User:Class?
Is this due to the line in the mail.rb? self.table_name = "mail", any clues on how to integrate both.
Thanks, in advance,
Dmarc
Phil, it is a good plugin. good work.
I wonder if it is possible that you share your views also. I know views could vary very much but you know, it is messaging, it will be almost same everywhere, if not it will present a good example for the people.
simply the views in bandsintown.com will do..
thanks!
I am trying to get this plugin to work within a rails 2.0.2 application but i run into a weird problem.
When trying to access the mailbox and its mails from the rails console everything works as expected:
u = User.find(:first)
mb = u.mailbox[:inbox]
mb.mail.each { |mail| puts mail.message.subject }
But when used within a controller/view in a similar way only the first call works.
Every call after throws
undefined method `message' for #< Mail:0x6878614 >
Any Ideas whats going wrong?
Does your plugin integrate with will_paginate?
hmm I have not actually tried it with that plugin, but I believe that will_paginate just wraps find so I dont see why it would not work.
Let me know if you try it.
I am also using the rails 2.0.2 environment and am getting the same undefined method `message' for #< Mail:0x6878614 > error as described above. It works if I set @mail to the first element of the array, but not when I try and iterate through the array in the view. Has this problem been addressed. Does it work in rails 2.0 and above? Thanks, this looks like a great plugin!
can you paste an example of what you are trying to do? I am currently using this with rails 2.1 without any issues.
Hey Phil, I actually just got it working and it seems to be functioning without a hitch. Thanks though!
Hey, everything is working great. Better than I anticipated. I am trying to add another couple fields to the mail object so that I can define a message type(message type and message_type_id), so that I can display icons for different message types in the inbox(i.e. a request versus just a message). I have been trying to decipher the code to find how a mail object is saved and I get lost. Any advice for the first step?
Hi,
I'd like to use this plugin in my project. The only difference is that instead of a model named 'User' I need to have a model named 'Person'. So I have modified the plugin a bit (changing user_id to person_id from Mail model, and all usages of User class point to Person).
However, something still seems to be broken. When I put the line 'acts_as_messageable' in my Person model, I get an error when I try to access the view in a browser. The error states: "undefined local variable or method `acts_as_messageable' for #Class:0x20594b4". Do you have any idea what might cause this? Is there any additional changes I need to perform in order to get the plugin to work in my Person model?
Phil, reply_to_conversation throws errors in Rails 2.1.
ArgumentError: Unknown key(s): order
I traced this down to the mail_count method which does add_conversation_condition, line 299 is the offender.
I overrode the has_conversation? method with:
#return mail_count(:all, :conversation => conversation) != 0
return Mail.exists?(['user_id = ? and conversation_id = ? and mailbox = ?', @user.id, conversation.id, @type.to_s])
The error went away, and it "seems" to give me the result I need. Is there a better way of handling this error, and am I missing any conditions/options in my version?
I love the implementation on your site. I was wondering if you had come across anyone who had written a short write up about using this plugin. I would love to be able to use it in my project but as a rails beginner I'm not sure how to set up the controllers, views, and routes.
I know you have provided some examples but have you come across anyone who had written a little more in depth?
Anyways, thanks for sharing this great code!
Hello Phil,
First thanks for this realy nice plugin.
I am currently using it in one of my projects but I have this error and i can't figure out how to correct it.
Here is the error :
Mail(#25465460) expected, got Mail(#49802630)
Maybe you'll have an idea.
Thanks in adavance.
Olivier
Post a Comment