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
Dario Hunt
2,245 PointsRails notification routing
In my app I'm using the gem mailboxer to handle my notifications and I've gotten everything up and running but I'm having trouble figuring out how to link_to the object that caused the notification. For example, I have a comment model that belongs to multiple models and I want to be able to display a link to the commentable model that the comment belongs to. I can't just call <%= link_to "View", notification.notified_object %> as that will try to link to the actual comment, I want the link to the status/project/event that it belongs to and I can't just call commentable. Any ideas on how to accomplish this? Thanks in advance.
Controller
class CommentsController < ApplicationController
before_filter :authenticate_member!
before_filter :load_commentable
before_filter :find_member
def index
redirect_to root_path
end
def new
@comment = @commentable.comments.new
end
def create
@comment = @commentable.comments.new(params[:comment])
@comment.member = current_member
if @comment.save
redirect_to :back
else
redirect_to :back
end
end
def destroy
@comment = Comment.find(params[:id])
respond_to do |format|
if @comment.member == current_member || @commentable.member == current_member
@comment.destroy
format.html { redirect_to :back }
else
format.html { redirect_to :back, alert: 'You can\'t delete this comment.' }
end
end
end
private
def load_commentable
klass = [Status, Medium, Project, Event, Listing].detect { |c| params["#{c.name.underscore}_id"] }
@commentable = klass.find(params["#{klass.name.underscore}_id"])
end
def find_member
@member = Member.find_by_user_name(params[:user_name])
end
end
Model
class Comment < ActiveRecord::Base
belongs_to :member
belongs_to :commentable, polymorphic: true
attr_accessible :content
validates :content, presence: true,
length: { minimum: 2, maximum: 280 }
after_create :create_notification, on: :create
def create_notification
subject = "#{member.user_name}"
body = "wrote you a <b>Comment</b> <p><i>#{content}</i></p>"
commentable.member.notify(subject, body, self)
end
end
View
<% @notifications.each do |notification|%>
<% @notification = notification %>
<div>
<%= link_to(notification.subject, "#{root_url}#{notification.subject}") %> <%= Rinku.auto_link(truncate(notification.body, :length => 400)).html_safe %>
<span class="not_meta"><%= time_ago_in_words(notification.created_at) %></span>
</div>
<div class="view">
<% if notification.notified_object_type == 'Comment' %>
<%= link_to("#") do %>
<i class="icon-eye-open icon-green"></i> View
<% end %>
</div>
<% end %>
Migrations
class CreateComments < ActiveRecord::Migration
def change
create_table :comments do |t|
t.text :content
t.belongs_to :commentable, polymorphic: true
t.references :member
t.timestamps
end
add_index :comments, [:commentable_id, :commentable_type]
add_index :comments, :member_id
end
end
#Notifications and Messages
create_table :mailboxer_notifications do |t|
t.column :type, :string
t.column :body, :text
t.column :subject, :string, :default => ""
t.references :sender, :polymorphic => true
t.column :conversation_id, :integer
t.column :draft, :boolean, :default => false
t.string :notification_code, :default => nil
t.references :notified_object, :polymorphic => true
t.column :attachment, :string
t.column :updated_at, :datetime, :null => false
t.column :created_at, :datetime, :null => false
t.boolean :global, default: false
t.datetime :expires
end
My comment resource route is nested under each model it belongs to.
1 Answer
Brandon Barrette
20,485 PointsYou should be able to call comment.commentable since you have the belongs_to association set up on that. How i did this was define a notification model:
class Notification < ActiveRecord::Base
belongs_to :user
belongs_to :sender, :class_name => "User", :foreign_key => :sender_id
belongs_to :notifiable, polymorphic: true
Then I can call notification.notifiable and this will return the model (Status, comment, picture, etc) on the other side of the polymorphic association. You can then interact with that model as if it was called originally.
Dario Hunt
2,245 PointsDario Hunt
2,245 PointsNot sure how I missed this but you're correct I could have just called
notification.notified_object.commentable. Thanks!