Tag Archives: ruby

Update: This is post should be considered outdated.

This started with the help of this Rails Messaging Tutorial which I borrowed a used a couple lines of code from this tutorial to extend this project. So many thanks to manitoba98 and the guys at PingMe for writing acts_as_network.

There are so many things acts_as_network can be used for. So far I have used acts_as_network to allow users to be able to invite friends as well as receive friend requests from other members. It was also used to implement a way for users to block other users and I am using it for my messaging system. So I thought I would put this out there just to kind of show anyone who might be interested to see just how great acts_as_network is.

So I will assume you have installed the plugin. Follow the link above if you cannot find it otherwise. I am also using restful_authentication but you can use whatever.

After you install the plugin create a new model and controller

script/generate model Mail user_id:integer user_id_target:integer subject:string body:text recipient_deleted:boolean author_deleted:boolean

script/generate controller Messages index show new edit

In the migration setup

t.boolean :author_deleted, :default => ‘false’

t.boolean :recipient_deleted, :default => ‘false’

Now in your User Model add the association

class User < ActiveRecord::Base

acts_as_network :messages, :through => :mails,

end

Now in the Mail Model

class Mail < ActiveRecord::Base
belongs_to  :user
belongs_to  :user_target, :class_name => ‘User’, :foreign_key => ‘user_id_target’
validates_presence_of :user, :user_target, :body

Setup your Controller to look something like this…

class MessagesController < ApplicationController
before_filter :login_required

def index
@messages = (params[:folder] != ’sent’) ? current_user.mails_in : current_user.mails_out
@folder = params[:folder]
end
def show
@message = Mail.find(params[:id])
@user = User.find(@message.user_id)
end

def new
@message = Mail.new
@target = User.find(params[:user_target])
end
def edit
@message = Mail.find(params[:id])
@subject = @message.subject.sub(/^(Re: )?/, “Re: “)
@target = User.find(@message.user_id)
end
def create
@message = Mail.new(:user => current_user, :user_target => User.find(params[:user_target]), :subject => params[:subject], :body => params[:body])
@message.save ? redirect_to(inbox_path) : render(:action => ‘new’, :user_targer => params[:user_target])
end
def update
@message = Mail.find(params[:id])
@message.toggle!(:recipient_deleted) ? redirect_to(inbox_path) : redirect_to(:action => ’show’, :id => params[:id])
end
def destroy
@message = Mail.find(params[:id])
if @message.user_id == current_user.id
@message.update_attribute(“author_deleted”, true)
elsif @message.user_id_target == current_user.id
@message.update_attribute(“recipient_deleted”, true)
elsif @message.user_id == current_user.id && @message.user_id_target == current_user.id
@message.update_attributes(“recipient_deleted” => true, “author_deleted” => true)
end
redirect_to inbox_path
end

end

The index.html.erb I am about to show you is for an example only. It’s wasn’t written with DRY in mind. I’ll post some better looking code at some later point but for now this is what it is.

<table width=”100%” border=”0″>
<tr>
<th>Login</th>
<th>Subject</th>
<th>Sent</th>
</tr>
<% @messages.each do |message| %>
<% user = (@folder != ’sent’)? User.find(message.user_id) : User.find(message.user_id_target) %>
<% if @folder == ‘inbox’ || @folder.blank? %>
<% if message.recipient_deleted == false %>
<tr>
<td><%= link_to user.login, user_path(user) %></td>
<td><%= link_to message.subject, message_path(message) %></td>
<td><%= distance_of_time_in_words(message.created_at, Time.now) %> ago</td>
</tr>
<% end %>
<% elsif @folder == ’sent’ %>
<% if message.author_deleted == false %>
<tr>
<td><%= link_to user.login, user_path(user) %></td>
<td><%= link_to message.subject, message_path(message) %></td>
<td><%= distance_of_time_in_words(message.created_at, Time.now) %> ago</td>
</tr>
<% end %>
<% elsif @folder == ‘trash’ %>
<% if message.recipient_deleted == true %>
<tr>
<td><%= link_to user.login, user_path(user) %></td>
<td><%= link_to message.subject, message_path(message) %></td>
<td><%= distance_of_time_in_words(message.created_at, Time.now) %> ago</td>
</tr>
<% end %>
<% end %>
<% end %>
</table>
</div>

edit.html.erb

<% form_tag ‘/messages/create’ do %>
<ul>
<li><label for=”user_target”>To:</label> <%=h @target.login %><%= hidden_field_tag ‘user_target’, @target.id %></li>
<li><label for=”subject”>Subject:</label> <%= text_field_tag ’subject’, @subject %></li>
<li><label for=”body”>Body:</label><br /> <%= text_area_tag ‘body’, @body %></li>
<li><%= submit_tag ‘Create’ %></li>
</ul>
<% end %>

new.html.erb

<div id=”message_new”>
<% form_tag ‘/messages/create’ do %>
<ul>
<li><label for=”user_target”>To:</label> <%=h @target.login %><%= hidden_field_tag ‘user_target’, @target.id %></li>
<li><label for=”subject”>Subject:</label> <%= text_field_tag ’subject’, ” ,:class=>”text”  %></li>
<li><label for=”body”>Body:</label><br /> <%= text_area_tag ‘body’ %></li>
<li><%= submit_tag ‘Create’ %></li>
</ul>
<% end %>
</div>

show.html.erb

<div id=”message_show”>
<ul>
<li>Subject: <%=h @message.subject %></li>
<li>From: <%=h @user.login %></li>
<li class=”body”>Body:<br /><br /><%= @message.body %></li>
<li><%= link_to ‘Reply’, edit_message_path %> | <%= link_to ‘Trash’, message_path(@message), :method => :delete %></li>
</ul>
</div>

routes.rb:     map.resources :messages

map.inbox ‘/inbox’, :controller => ‘messages’, :action => ‘index’, :folder => ‘inbox’

map.sent  ‘/sent’, :controller => ‘messages’, :action => ‘index’, :folder => ’sent’

And that should about do it.

Update: This post should be considered outdated.

The project I am working on pretty much revolves around a user’s profile. I am still pretty new to working with Rails but, I knew there was an easier way of implementing this without having to add columns to the user table. I looked around for awhile for a tutorial or blog suggesting a painless way of adding this to an application.
I really wasn’t able to find anything so I decided to write this mini-how to.

I would first recommend that you take a look at Raaum’s Rails Reader. There is some really great documentation about ActiveRecord and how associations work. It would behoove you to follow along creating the user models and the migrations following along with the text because things will make sense that way. If you are lazy like me creating a bunch of junk models that you are just going to destroy sounds tedious I know but, it’s definitely worth the effort in the long run.

Nevertheless, I needed to be able to call a user’s profile within current_user. For example current_user.profile.body. So assuming you have already created your user model and setup the inclusion within you Application Controller. Now create your profile model and the migration accordingly.

script/generate model Profile user_id:integer body:text

Now open the Profile controller and add has_one :user somewhere after the class declaration.

class Profile < ActiveRecord::Base
has_one :user
end

It is work mentioning at this point that within the scope of this text the user will be created then redirected to the edit their profile. So if you plan to add validations in your model (ie: validates_presence_of) make sure to include

validates_presence_of :your_fields, :on => :update

Otherwise you will be unable to save the profile later.
Now add the same has_one statement to your User model but you will use

class User < ActiveRecord::Base
has_one :profile

Here is an example of how your controller might look…

class UsersController < ApplicationController
after_filter :update_session, :only => :create
before_filter :login_required, :only => [:edit, :show, :update]
before_filter :logout_required, :only => [:new, :create]
def index
@users = User.find(:all, :conditions => ['status = ?', 'active'])
end
def show
@user = User.find_by_login(params[:id])
end
def create
@user = User.new(params[:user])
@user.profile = Profile.new
self.current_user = (@user.save!)? @user : render(:action => ‘new’)
redirect_to :action => ‘edit’, :id => self.current_user.login
flash[:notice] = ‘Account successfully created!’
end
def update
self.current_user.profile.update_attributes!(params[:profile])? redirect_to(:action => ’show’, :id => self.current_user.login) : render(:action => ‘edit’)
end
end

As you can see when the create method is called it creates the Profile model and after the user is saved then redirected to the edit template.

This was the solution that worked best for me.