The Dillema:
I am in a situation where I need to show a User’s activity across multiple views and controllers. The code is starting to smell a little bit, so I’d really appreciate some guidance in cleaning it up.
I have a User controller has a “show” (/user_id/) view that renders recent activity in the sidebar, as well as a “activity” (user_id/activity) view that renders all of the user’s activity. I also have a “Pages” controller that has a “dashboard” view that renders a user’s activity as well.
The Code:
users_controller.rb looks like:
@activities = []
@activities += @user.skills.map { |skill| Activity.new("skill", skill, skill.created_at) }
@activities += @user.unions.map { |union| Activity.new("union", union, union.created_at) }
@activities += @user.companies.map { |company| Activity.new("company", company, company.created_at) }
@activities += @user.clients.map { |client| Activity.new("client", client, client.created_at) }
@activities += @user.schools.map { |school| Activity.new("school", school, school.created_at) }
@activities += @following_list.map { |following| Activity.new("following", following, following.created_at) }
@activities += @recommended.map { |recommend| Activity.new("recommend", recommend, recommend.created_at) }
@activities += @user.statuses.all(:limit => 5, :order => "created_at DESC").map { |status| Activity.new("status", status, status.created_at) }
sorted_activities = @activities.sort_by(&:date).reverse
@activities = sorted_activities[0..(4)]
pages_controller.rb looks like:
@your_activity = []
@your_activity += current_user.skills.map { |skill| ActivityDashboard.new("#{current_user.first_name} #{current_user.last_name}","#{current_user.id}","#{current_user.avatar}","skill", skill, skill.created_at) }
@your_activity += current_user.unions.map { |union| ActivityDashboard.new("#{current_user.first_name} #{current_user.last_name}","#{current_user.id}","#{current_user.avatar}","union", union, union.created_at) }
@your_activity += current_user.companies.map { |company| ActivityDashboard.new("#{current_user.first_name} #{current_user.last_name}","#{current_user.id}","#{current_user.avatar}","company", company, company.created_at) }
@your_activity += current_user.clients.map { |client| ActivityDashboard.new("#{current_user.first_name} #{current_user.last_name}","#{current_user.id}","#{current_user.avatar}","client", client, client.created_at) }
@your_activity += current_user.schools.map { |school| ActivityDashboard.new("#{current_user.first_name} #{current_user.last_name}","#{current_user.id}","#{current_user.avatar}","school", school, school.created_at) }
@your_activity += current_user.statuses.map { |status| ActivityDashboard.new("#{current_user.first_name} #{current_user.last_name}","#{current_user.id}","#{current_user.avatar}","status", status, status.created_at) }
sorted_activities = @your_activity.sort_by(&:date).reverse
@your_activity = sorted_activities[0..(35)]
There’s a few ways you can do it really. You could offload it to the model, you could create a module in the lib directory and use that to build the activity arrays. One major thing too is to be sure to use a helper for displaying it on the page, and load that either into the views or a partial, depending on your needs.
You could also reduce the duplication a bit with some metaprogramming. You may need to adjust depending on your requirements. You’ll need to set it up for the first set of code as well
Gist of my working example: https://gist.github.com/3669117