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 ajax prepend activity
In my app I have a status model that also creates an activity item when a status is created. My activity model is polymorphic is belongs to a number of different models. Everything works fine, but I'm having trouble with my ajax status creation. On users' profile pages there's a status form and an activity list. I want users to be able to create a status through ajax and have the corresponding activity item appended to the list. Any ideas how I can do this? Thanks in advance.
statuses_controller.rb
class StatusesController < ApplicationController
before_filter :authenticate_member!, only: [:index, :new, :create, :edit, :update, :destroy]
before_filter :find_member
before_filter :find_status, only: [:edit, :update, :destroy]
rescue_from ActiveRecord::RecordNotFound do
render file: 'public/404', status: 404, formats: [:html]
end
def show
@status = Status.find(params[:id])
@commentable = @status
@comments = @commentable.comments.order('created_at desc').page(params[:page]).per_page(15)
@comment = @commentable.comments.new
respond_to do |format|
format.html # show.html.erb
format.json { redirect_to profile_path(current_member) }
end
end
def new
@status = Status.new
@status.build_document
respond_to do |format|
format.html # new.html.erb
format.json { render json: @status }
format.js
end
end
def create
@status = current_member.statuses.new(params[:status])
respond_to do |format|
if @status.save
current_member.create_activity(@status, 'created')
format.html { redirect_to :back }
format.json
format.js
else
format.html { redirect_to profile_path(current_member), alert: 'Post wasn\'t created. Please try again and ensure image attchments are under 10Mbs.' }
format.json { render json: @status.errors, status: :unprocessable_entity }
format.js
end
end
end
def destroy
@activity = Activity.find_by_targetable_id(params[:id])
@commentable = @status
@comments = @commentable.comments
if @activity
@activity.destroy
end
if @comments
@comments.destroy
end
@status.destroy
respond_to do |format|
format.html { redirect_to profile_path(current_member) }
format.json { head :no_content }
end
end
private
def find_member
@member = Member.find_by_user_name(params[:user_name])
end
def find_status
@status = current_member.statuses.find(params[:id])
end
end
activities_controller.rb
class ActivitiesController < ApplicationController
before_filter :authenticate_member!
before_filter :find_activity, only: [:destroy]
def index
params[:page] ||= 1
@activities = Activity.for_member(current_member, params)
respond_to do |format|
format.html # index.html.erb
format.js
end
end
def destroy
@status = @activity.targetable
if @activity.targetable_type == 'Status'
@status.destroy
end
@activity.destroy
respond_to do |format|
format.html { redirect_to :back }
format.json { head :no_content }
format.js
end
end
def upvote
@activity = Activity.find(params[:id])
if current_member.voted_up_on? @activity
@activity.unliked_by current_member
else
@activity.liked_by current_member
end
respond_to do |format|
format.html { redirect_to :back }
format.js
end
end
private
def find_activity
@activity = current_member.activities.find(params[:id])
end
end
activity.rb
class Activity < ActiveRecord::Base
belongs_to :member
belongs_to :targetable, polymorphic: true
acts_as_votable
self.per_page = 36
def self.for_member(member, options={})
options[:page] ||= 1
following_ids = member.following_members.map(&:id).push(member.id)
where("member_id in (?)", following_ids).
order("created_at desc").
page(options[:page])
end
end
profiles/show.html.erb
<% if @activities.count > 0 %>
<div id="media_query_stream">
<div id="activity_stream_wrap">
<%= render :partial => "activities/activities", locals: { activity: @activity} %>
</div>
</div>
<% else %>
<div class="none_message">
No Posts Yet
</div>
<% end %>
activities/_activities.html.erb
<% @activities.each do |activity| %>
<%= render partial: "activities/#{activity.targetable_type.underscore}/#{activity.action}",
locals: { activity: activity } %>
<% end %>
activities/status/_created.html.erb
<div id="activity_<%= activity.id %>_<%= activity.member.id %>" class="list_act_wrap status_fil">
<div class="act_status_top">
<span class="">
<%= avatar_profile_link activity.member, :class => "act_av", title: activity.member.full_name, alt: activity.member.full_name %>
</span>
<span class="act_name">
<%= link_to activity.member.user_name, profile_path(activity.member) %>
</span>
<span class="meta">
<%= time_ago_in_words(activity.targetable.created_at) %>
</span>
<span class="act_title stat">
wrote a new <%= link_to 'Status', status_path(activity.targetable_id) %>
</span>
</div>
<div class="act_content">
<%= Rinku.auto_link(activity.targetable.content_html).html_safe %>
</div>
</div>
I tried to append the activity through ajax like so:
statuses/create.js.erb
$("#activity_stream_wrap").prepend("<%= escape_javascript(render :partial => 'activities/status/created', :locals => {:activity => @activity}) %>");
$('#stat_count').html("280");
$('#status_form')[0].reset();
But it throws an error like:
undefined method `member' for nil:NilClass
1 Answer
Dario Hunt
2,245 PointsI wasn't defining @activity in my create action in my controller. So defining it like so made everything work.
def create @status = current_member.statuses.new(params[:status])
respond_to do |format|
if @status.save
@activity = current_member.create_activity(@status, 'created') # needed to define it here
format.html { redirect_to :back }
format.json
format.js
else
format.html { redirect_to profile_path(current_member), alert: 'Post wasn\'t created. Please try again and ensure image attchments are under 10Mbs.' }
format.json { render json: @status.errors, status: :unprocessable_entity }
format.js
end
end
end