muck-activities 0.1.11 → 0.1.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -30,6 +30,12 @@ Adding an item to the activity feed requires 'acts_as_activity_source' which the
30
30
  Example:
31
31
  add_activity(user.feed_to, user, comment, 'comment')
32
32
 
33
+ Create an activity model that 'acts_as_muck_activity':
34
+
35
+ class Activity < ActiveRecord::Base
36
+ acts_as_muck_activity
37
+ end
38
+
33
39
  === Authorization
34
40
  By default 'has_activities' will add a simple 'can_view?' method:
35
41
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.11
1
+ 0.1.12
@@ -24,7 +24,6 @@ class Muck::ActivitiesController < ApplicationController
24
24
  @activity.source = @parent
25
25
  @activity.content.gsub!(@parent.display_name, '')
26
26
  @parent.save!
27
-
28
27
  @activity_html = get_activity_html(@activity)
29
28
  if @activity.template == 'status_update'
30
29
  @status_html = get_status_html(@parent)
@@ -77,6 +76,11 @@ class Muck::ActivitiesController < ApplicationController
77
76
  page_alert(page, message)
78
77
  end
79
78
  end
79
+ format.json do
80
+ render :json => { :success => false,
81
+ :exception => ex,
82
+ :message => t("muck.activities.create_error", :error => errors) }
83
+ end
80
84
  end
81
85
 
82
86
  end
@@ -96,10 +100,14 @@ class Muck::ActivitiesController < ApplicationController
96
100
  page << "jQuery('##{@activity.dom_id}').fadeOut();"
97
101
  page.replace_html 'current-status', @new_status if @new_status
98
102
  end
103
+ else
104
+ render(:update) do |page|
105
+ page << "jQuery('##{@activity.dom_id}').fadeOut();"
106
+ end
99
107
  end
100
108
  end
101
109
  format.json do
102
- @new_status = get_status_html(@activities_object)
110
+ @new_status = get_status_html(@activities_object) if @activity.is_status_update
103
111
  render :json => { :success => true,
104
112
  :is_status_update => @activity.is_status_update,
105
113
  :html => @new_status,
@@ -123,14 +131,25 @@ class Muck::ActivitiesController < ApplicationController
123
131
  protected
124
132
 
125
133
  def get_status_html(activity)
126
- @template.template_format = :html
127
- render_to_string(:partial => 'activities/current_status', :locals => {:activities_object => activity})
134
+ render_as_html do
135
+ render_to_string(:partial => 'activities/current_status', :locals => {:activities_object => activity})
136
+ end
128
137
  end
129
138
 
130
139
  def get_activity_html(activity)
131
- render_to_string(:partial => "activity_templates/#{activity.template}", :locals => { :activity => activity })
140
+ render_as_html do
141
+ render_to_string(:partial => "activity_templates/#{activity.template}", :locals => { :activity => activity })
142
+ end
132
143
  end
133
144
 
145
+ def render_as_html
146
+ last_template_format = @template.template_format
147
+ @template.template_format = :html
148
+ result = yield
149
+ @template.template_format = last_template_format
150
+ result
151
+ end
152
+
134
153
  def find_parent
135
154
  @klass = params[:parent_type].to_s.capitalize.constantize
136
155
  @parent = @klass.find(params[:parent_id])
@@ -18,19 +18,29 @@ module MuckActivityHelper
18
18
  end
19
19
  end
20
20
 
21
+ # Renders an activity with only activities created by activities_object
22
+ def limited_activity_feed_for(activities_object)
23
+ activities = activities_object.activities.created_by(activities_object).find(:all, :include => ['comments']).paginate(:page => @page, :per_page => @per_page)
24
+ render :partial => 'activities/activity_feed', :locals => { :activities_object => activities_object, :activities => activities }
25
+ end
26
+
27
+ # Renders a full activity feed for activities_object
21
28
  def activity_feed_for(activities_object)
22
29
  activities = get_activities(activities_object)
23
30
  render :partial => 'activities/activity_feed', :locals => { :activities_object => activities_object, :activities => activities }
24
31
  end
25
32
 
33
+ # Renders a status update form for activities_object
26
34
  def status_update(activities_object)
27
35
  render :partial => 'activities/status_update', :locals => { :activities_object => activities_object }
28
36
  end
29
37
 
38
+ # Renders the last status update made by activities_object
30
39
  def current_status(activities_object)
31
40
  render :partial => 'activities/current_status_wrapper', :locals => { :activities_object => activities_object }
32
41
  end
33
42
 
43
+ # Renders a delete button for an activity
34
44
  def delete_activity(activity, button_type = :button, button_text = t("muck.activities.clear"))
35
45
  render :partial => 'activities/delete', :locals => { :delete_object => activity,
36
46
  :button_type => button_type,
@@ -39,6 +49,7 @@ module MuckActivityHelper
39
49
  :delete_path => activity_path(activity, :format => 'js') }
40
50
  end
41
51
 
52
+ # Renders a delete button for a comment inside an activity feed
42
53
  def delete_comment(comment, button_type = :button, button_text = t("muck.activities.delete"))
43
54
  render :partial => 'activities/delete', :locals => { :delete_object => comment,
44
55
  :button_type => button_type,
@@ -47,6 +58,7 @@ module MuckActivityHelper
47
58
  :delete_path => comment_path(comment, :format => 'js') }
48
59
  end
49
60
 
61
+ # Renders an activity feed filter. Filter items come from the name of the templates used to render the activities.
50
62
  def activity_filter(activities_object)
51
63
  activity_types = activities_object.activities.all(:select => "DISTINCT activities.template")
52
64
  render :partial => 'activities/template_filter', :locals => { :activity_types => activity_types }
@@ -0,0 +1,12 @@
1
+ <div class="activity <%= activity_css_class %> delete-container" id="<%= activity.dom_id %>">
2
+ <div class="actor-icon"><%= icon activity.source %></div>
3
+ <div class="activity-content">
4
+ <p><span class="actor"><%= link_to activity.source.display_name, activity.source %></span> <%= activity.content %></p>
5
+ <%= delete_activity(activity, :image) %>
6
+ <span class="activity-time"><%= t("muck.activities.time_ago", :time_in_words => time_ago_in_words(activity.created_at)) %></span>
7
+ <% if !activity.has_comments? -%>
8
+ <span><a id="make_comment_<%=activity.dom_id%>" class="make-comment" href="#"><%=t('muck.activities.make_comment')%></a></span>
9
+ <% end -%>
10
+ </div>
11
+ <%= activity_comments(activity) %>
12
+ </div>
@@ -1,12 +1 @@
1
- <div class="activity activity-status-update delete-container" id="<%= activity.dom_id %>">
2
- <div class="actor-icon"><%= icon activity.source %></div>
3
- <div class="activity-content">
4
- <p><span class="actor"><%= link_to activity.source.display_name, activity.source %></span> <%= activity.content %></p>
5
- <%= delete_activity(activity, :image) %>
6
- <span class="activity-time"><%= t("muck.activities.time_ago", :time_in_words => time_ago_in_words(activity.created_at)) %></span>
7
- <% if !activity.has_comments? -%>
8
- <span><a id="make_comment_<%=activity.dom_id%>" class="make-comment" href="#"><%=t('muck.activities.make_comment')%></a></span>
9
- <% end -%>
10
- </div>
11
- <%= activity_comments(activity) %>
12
- </div>
1
+ <%= render :partial => 'activity_templates/generic', :locals => { :activity => activity, :activity_css_class => 'activity-status-update' } %>
@@ -0,0 +1,76 @@
1
+ module ActiveRecord
2
+ module Acts #:nodoc:
3
+ module MuckActivity #:nodoc:
4
+ def self.included(base)
5
+ base.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+
10
+ def acts_as_muck_activity(options = {})
11
+
12
+ belongs_to :item, :polymorphic => true
13
+ belongs_to :source, :polymorphic => true
14
+ has_many :activity_feeds
15
+
16
+ acts_as_commentable
17
+
18
+ validates_presence_of :source
19
+
20
+ named_scope :since, lambda { |time| {:conditions => ["activities.created_at > ?", time] } }
21
+ named_scope :before, lambda {|time| {:conditions => ["activities.created_at < ?", time] } }
22
+ named_scope :newest, :order => "activities.created_at DESC"
23
+ named_scope :after, lambda {|id| {:conditions => ["activities.id > ?", id] } }
24
+ named_scope :only_public, :conditions => ["activities.is_public = true"]
25
+ named_scope :filter_by_template, lambda { |template| { :conditions => ["activities.template = ?", template] } unless template.blank? }
26
+ named_scope :created_by, lambda {|activity_object| {:conditions => ["activities.source_id = ? AND activities.source_type = ?", activity_object.id, activity_object.class.to_s] } }
27
+ named_scope :status_updates, :conditions => ["activities.is_status_update = ?", true]
28
+ class_eval <<-EOV
29
+ attr_protected :created_at, :updated_at
30
+ EOV
31
+
32
+ include ActiveRecord::Acts::MuckActivity::InstanceMethods
33
+ extend ActiveRecord::Acts::MuckActivity::SingletonMethods
34
+
35
+ end
36
+ end
37
+
38
+ # class methods
39
+ module SingletonMethods
40
+
41
+ end
42
+
43
+ # All the methods available to a record that has had <tt>acts_as_muck_activity</tt> specified.
44
+ module InstanceMethods
45
+
46
+ def validate
47
+ errors.add_to_base(I18n.t('muck.activities.template_or_item_required')) if template.blank? && item.blank?
48
+ end
49
+
50
+ # Provides a template that can be used to render a view of this activity.
51
+ # If 'template' is not specified when the object created then the item class
52
+ # name will be used to generated a template
53
+ def partial
54
+ template || item.class.name.underscore
55
+ end
56
+
57
+ def has_comments?
58
+ @has_comments ||= !self.comments.blank?
59
+ end
60
+
61
+ # Checks to see if the specified object can edit this activity.
62
+ # Most likely check_object will be a user
63
+ def can_edit?(check_object)
64
+ if check_object.is_a?(User)
65
+ return true if check(check_object, :source_id)
66
+ else
67
+ source == check_object
68
+ end
69
+ false
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+ end
76
+ end
@@ -1,9 +1,10 @@
1
1
  require 'cgi'
2
2
  require 'muck_activities/initialize_routes'
3
- require 'muck_activities/muck_activity'
3
+ require 'muck_activities/muck_activity_sources'
4
4
 
5
+ ActiveRecord::Base.class_eval { include ActiveRecord::Acts::MuckActivity }
5
6
  ActionController::Base.send :helper, MuckActivityHelper
6
- ActiveRecord::Base.send(:include, MuckActivity)
7
- ActionController::Base.send(:include, MuckActivity)
7
+ ActiveRecord::Base.send(:include, MuckActivitySources)
8
+ ActionController::Base.send(:include, MuckActivitySources)
8
9
 
9
10
  I18n.load_path += Dir[ File.join(File.dirname(__FILE__), '..', 'locales', '*.{rb,yml}') ]
@@ -1,4 +1,4 @@
1
- module MuckActivity # :nodoc:
1
+ module MuckActivitySources # :nodoc:
2
2
 
3
3
  def self.included(base) # :nodoc:
4
4
  base.extend ActMethods
@@ -19,6 +19,7 @@ module MuckActivity # :nodoc:
19
19
 
20
20
  # +acts_as_activity_source+ gives the class it is called on a method called
21
21
  # +add_activity+ that can add activities into a feed.
22
+ # This can be applied to models or controllers
22
23
  def acts_as_activity_source
23
24
  unless included_modules.include? InstanceMethods
24
25
  include InstanceMethods
@@ -43,7 +44,11 @@ module MuckActivity # :nodoc:
43
44
  # to false the activity won't be added to the object's activity feed. An example usage would be
44
45
  # letting users configure which items they want to have in their activity feed.
45
46
  def add_activity(feed_to, source, item, template, title = '', content = '', check_method = nil)
46
- feed_to = [feed_to] unless feed_to.is_a?(Array)
47
+ if feed_to.is_a?(Array)
48
+ feed_to = feed_to & feed_to # eliminate duplicates from feed_to array
49
+ else
50
+ feed_to = [feed_to]
51
+ end
47
52
  activity = Activity.create(:item => item, :source => source, :template => template, :title => title, :content => content)
48
53
  feed_to.each do |ft|
49
54
  if check_method
@@ -52,12 +57,13 @@ module MuckActivity # :nodoc:
52
57
  ft.activities << activity
53
58
  end
54
59
  end
60
+ activity
55
61
  end
56
62
 
57
63
  # +status+ returns the first activity item from the user's activity feed that is a status update.
58
64
  # Used for displaying the last status update the user made
59
65
  def status
60
- self.activities.find(:first, :conditions => ['is_status_update = true'], :order => 'created_at DESC')
66
+ self.activities.status_updates.newest.first
61
67
  end
62
68
 
63
69
  def can_view?(check_object)
@@ -1,12 +1,13 @@
1
1
  en:
2
2
  muck:
3
3
  activities:
4
- item_removed: 'Item successfully removed from the recent activities list.'
5
- item_could_not_be_removed: 'Item could not be removed from the recent activities list.'
6
- item_created: 'Added activity'
4
+ item_removed: "Item successfully removed from the recent activities list."
5
+ item_could_not_be_removed: "Item could not be removed from the recent activities list."
6
+ item_created: "Added activity"
7
+ create_error: "There was a problem adding the requested activity: {{error}}"
7
8
  permission_denied: "Sorry, you can't do that."
8
9
  status_update_prompt: "What are you doing right now?"
9
- activity_feed_title: 'Recent Activity'
10
+ activity_feed_title: "Recent Activity"
10
11
  updating_status_message: "Updating your status. Please wait."
11
12
  status_indicator: is
12
13
  invite_friends: Invite Friends
@@ -19,8 +20,8 @@ en:
19
20
  update_status_message: "update your status!"
20
21
  time_ago: "{{time_in_words}} ago"
21
22
  template_or_item_required: "An activity requires a template or an item to display correctly"
22
- paging_newer: '&laquo; Newer'
23
- paging_older: 'Older &raquo;'
23
+ paging_newer: "&laquo; Newer"
24
+ paging_older: "Older &raquo;"
24
25
  all_activities: All Activities
25
26
  make_comment: Comment
26
27
  write_prompt: "Write a comment..."
@@ -2,11 +2,11 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{muck-activities}
5
- s.version = "0.1.11"
5
+ s.version = "0.1.12"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
8
  s.authors = ["Justin Ball"]
9
- s.date = %q{2009-06-19}
9
+ s.date = %q{2009-06-24}
10
10
  s.description = %q{Activity engine for the muck system.}
11
11
  s.email = %q{justinball@gmail.com}
12
12
  s.extra_rdoc_files = [
@@ -21,8 +21,6 @@ Gem::Specification.new do |s|
21
21
  "app/controllers/muck/activities_controller.rb",
22
22
  "app/helpers/muck_activity_helper.rb",
23
23
  "app/helpers/muck_activity_helper.rb",
24
- "app/models/activity.rb",
25
- "app/models/activity.rb",
26
24
  "app/models/activity_feed.rb",
27
25
  "app/models/activity_feed.rb",
28
26
  "app/views/activities/_activity_feed.html.erb",
@@ -43,6 +41,8 @@ Gem::Specification.new do |s|
43
41
  "app/views/activities/_status_update.html.erb",
44
42
  "app/views/activities/_template_filter.html.erb",
45
43
  "app/views/activities/_template_filter.html.erb",
44
+ "app/views/activity_templates/_generic.html.erb",
45
+ "app/views/activity_templates/_generic.html.erb",
46
46
  "app/views/activity_templates/_status_update.html.erb",
47
47
  "app/views/activity_templates/_status_update.html.erb",
48
48
  "config/muck_activities_routes.rb",
@@ -50,14 +50,14 @@ Gem::Specification.new do |s|
50
50
  "db/migrate/20090402033319_add_muck_activities.rb",
51
51
  "db/migrate/20090402033319_add_muck_activities.rb",
52
52
  "install.rb",
53
+ "lib/active_record/acts/muck_activity.rb",
54
+ "lib/active_record/acts/muck_activity.rb",
53
55
  "lib/muck_activities.rb",
54
56
  "lib/muck_activities.rb",
55
- "lib/muck_activities/active_record/acts/muck_activity.rb",
56
- "lib/muck_activities/active_record/acts/muck_activity.rb",
57
57
  "lib/muck_activities/initialize_routes.rb",
58
58
  "lib/muck_activities/initialize_routes.rb",
59
- "lib/muck_activities/muck_activity.rb",
60
- "lib/muck_activities/muck_activity.rb",
59
+ "lib/muck_activities/muck_activity_sources.rb",
60
+ "lib/muck_activities/muck_activity_sources.rb",
61
61
  "lib/muck_activities/tasks.rb",
62
62
  "lib/muck_activities/tasks.rb",
63
63
  "locales/ar.yml",
@@ -126,6 +126,7 @@ Gem::Specification.new do |s|
126
126
  "locales/zh.yml",
127
127
  "muck-activities.gemspec",
128
128
  "pkg/muck-activities-0.1.10.gem",
129
+ "pkg/muck-activities-0.1.11.gem",
129
130
  "public/images/loading.gif",
130
131
  "public/images/loading.gif",
131
132
  "public/javascripts/muck_activities.js",
@@ -161,7 +162,9 @@ Gem::Specification.new do |s|
161
162
  "test/rails_root/app/controllers/default_controller.rb",
162
163
  "test/rails_root/app/helpers/application_helper.rb",
163
164
  "test/rails_root/app/models/.keep",
165
+ "test/rails_root/app/models/activity.rb",
164
166
  "test/rails_root/app/models/comment.rb",
167
+ "test/rails_root/app/models/profile.rb",
165
168
  "test/rails_root/app/models/user.rb",
166
169
  "test/rails_root/app/models/user_session.rb",
167
170
  "test/rails_root/app/views/default/index.html.erb",
@@ -185,6 +188,7 @@ Gem::Specification.new do |s|
185
188
  "test/rails_root/db/migrate/20090402234137_create_languages.rb",
186
189
  "test/rails_root/db/migrate/20090426041056_create_countries.rb",
187
190
  "test/rails_root/db/migrate/20090426041103_create_states.rb",
191
+ "test/rails_root/db/migrate/20090512013727_create_profiles.rb",
188
192
  "test/rails_root/db/migrate/20090602041838_create_users.rb",
189
193
  "test/rails_root/db/migrate/20090613173314_create_comments.rb",
190
194
  "test/rails_root/features/step_definitions/webrat_steps.rb",
@@ -356,6 +360,7 @@ Gem::Specification.new do |s|
356
360
  "test/rails_root/test/unit/.keep",
357
361
  "test/rails_root/test/unit/activity_feed_test.rb",
358
362
  "test/rails_root/test/unit/activity_test.rb",
363
+ "test/rails_root/test/unit/user_test.rb",
359
364
  "uninstall.rb"
360
365
  ]
361
366
  s.has_rdoc = true
@@ -369,7 +374,9 @@ Gem::Specification.new do |s|
369
374
  "test/rails_root/app/controllers/application_controller.rb",
370
375
  "test/rails_root/app/controllers/default_controller.rb",
371
376
  "test/rails_root/app/helpers/application_helper.rb",
377
+ "test/rails_root/app/models/activity.rb",
372
378
  "test/rails_root/app/models/comment.rb",
379
+ "test/rails_root/app/models/profile.rb",
373
380
  "test/rails_root/app/models/user.rb",
374
381
  "test/rails_root/app/models/user_session.rb",
375
382
  "test/rails_root/config/boot.rb",
@@ -387,6 +394,7 @@ Gem::Specification.new do |s|
387
394
  "test/rails_root/db/migrate/20090402234137_create_languages.rb",
388
395
  "test/rails_root/db/migrate/20090426041056_create_countries.rb",
389
396
  "test/rails_root/db/migrate/20090426041103_create_states.rb",
397
+ "test/rails_root/db/migrate/20090512013727_create_profiles.rb",
390
398
  "test/rails_root/db/migrate/20090602041838_create_users.rb",
391
399
  "test/rails_root/db/migrate/20090613173314_create_comments.rb",
392
400
  "test/rails_root/db/schema.rb",
@@ -400,7 +408,8 @@ Gem::Specification.new do |s|
400
408
  "test/rails_root/test/shoulda_macros/controller.rb",
401
409
  "test/rails_root/test/test_helper.rb",
402
410
  "test/rails_root/test/unit/activity_feed_test.rb",
403
- "test/rails_root/test/unit/activity_test.rb"
411
+ "test/rails_root/test/unit/activity_test.rb",
412
+ "test/rails_root/test/unit/user_test.rb"
404
413
  ]
405
414
 
406
415
  if s.respond_to? :specification_version then
@@ -1 +1 @@
1
- Thu, 18 Jun 2009 11:30:28 -0600
1
+ Fri, 19 Jun 2009 02:12:00 -0600
@@ -13,3 +13,4 @@ require 'muck_engine/tasks'
13
13
  require 'muck_users/tasks'
14
14
  require 'muck_comments/tasks'
15
15
  require 'muck_activities/tasks'
16
+ require 'muck_profiles/tasks'
@@ -0,0 +1,3 @@
1
+ class Activity < ActiveRecord::Base
2
+ acts_as_muck_activity
3
+ end
@@ -0,0 +1,3 @@
1
+ class Profile < ActiveRecord::Base
2
+ acts_as_muck_profile
3
+ end
@@ -2,9 +2,14 @@ class User < ActiveRecord::Base
2
2
  acts_as_authentic do |c|
3
3
  c.crypto_provider = Authlogic::CryptoProviders::BCrypt
4
4
  end
5
-
5
+ acts_as_muck_user
6
+ has_muck_profile
6
7
  has_activities
7
8
 
9
+ def feed_to
10
+ [self]
11
+ end
12
+
8
13
  def admin?
9
14
  false
10
15
  end
@@ -4,3 +4,4 @@
4
4
  <%= current_status(@user) %>
5
5
  <%= status_update(@user) %>
6
6
  <%= activity_feed_for(@user) %>
7
+ <%= limited_activity_feed_for(@user) %>
@@ -17,10 +17,13 @@ Rails::Initializer.run do |config|
17
17
  config.time_zone = 'UTC'
18
18
  config.gem 'mislav-will_paginate', :lib => 'will_paginate', :source => 'http://gems.github.com'
19
19
  config.gem "authlogic"
20
+ config.gem "binarylogic-searchlogic", :lib => 'searchlogic', :source => 'http://gems.github.com', :version => '~> 2.0.0'
20
21
  config.gem "bcrypt-ruby", :lib => "bcrypt"
21
22
  config.gem "collectiveidea-awesome_nested_set", :lib => 'awesome_nested_set', :source => "http://gems.github.com"
23
+ config.gem 'thoughtbot-paperclip', :lib => 'paperclip', :source => "http://gems.github.com"
22
24
  config.gem 'muck-engine', :lib => 'muck_engine'
23
25
  config.gem 'muck-users', :lib => 'muck_users'
24
26
  config.gem 'muck-comments', :lib => 'muck_comments'
27
+ config.gem 'muck-profiles', :lib => 'muck_profiles'
25
28
  config.plugin_locators << TestGemLocator
26
29
  end
@@ -0,0 +1,21 @@
1
+ class CreateProfiles < ActiveRecord::Migration
2
+
3
+ def self.up
4
+
5
+ create_table :profiles, :force => true do |t|
6
+ t.integer :user_id
7
+ t.string :photo_file_name
8
+ t.string :photo_content_type
9
+ t.integer :photo_file_size
10
+ t.timestamps
11
+ end
12
+
13
+ add_index :profiles, ['user_id']
14
+
15
+ end
16
+
17
+ def self.down
18
+ drop_table :profiles
19
+ end
20
+
21
+ end
@@ -3,7 +3,7 @@ class CreateComments < ActiveRecord::Migration
3
3
  create_table :comments, :force => true do |t|
4
4
  t.integer :commentable_id, :default => 0
5
5
  t.string :commentable_type, :limit => 15, :default => ""
6
- t.text :body, :default => ""
6
+ t.text :body
7
7
  t.integer :user_id, :default => 0, :null => false
8
8
  t.integer :parent_id
9
9
  t.integer :lft
@@ -11,30 +11,56 @@ class Muck::ActivitiesControllerTest < ActionController::TestCase
11
11
  login_as @user
12
12
  end
13
13
 
14
- context 'on GET to index (js)' do
14
+ context "on GET to index" do
15
15
  setup do
16
- @activity = Factory(:activity)
17
- get :index, :parent_type => @user.type, :parent_id => @user, :format => 'js', :latest_activity_id => @activity.to_param
16
+ @activity = Factory(:activity, :template => 'status_update')
17
+ @user.activities << @activity
18
+ end
19
+
20
+ context 'on GET to index (js)' do
21
+ setup do
22
+ get :index, :parent_type => @user.type, :parent_id => @user, :format => 'js', :latest_activity_id => @activity.to_param
23
+ end
24
+ should_respond_with :success
25
+ end
26
+
27
+ context 'on GET to index (js) no latest activity id' do
28
+ setup do
29
+ get :index, :parent_type => @user.type, :parent_id => @user, :format => 'js', :latest_activity_id => nil
30
+ end
31
+ should_respond_with :success
18
32
  end
19
- should_respond_with :success
20
33
  end
21
34
 
22
- context 'on GET to index (js) no latest activity id' do
35
+ context 'fail on POST to create (json)' do
23
36
  setup do
24
- get :index, :parent_type => @user.type, :parent_id => @user, :format => 'js', :latest_activity_id => nil
25
- end
37
+ post :create, :activity => { :content => 'test activity' }, :parent_type => @user.type, :parent_id => @user, :format => 'json'
38
+ end
26
39
  should_respond_with :success
40
+ should_not_set_the_flash
41
+ should "return create json errors" do
42
+ json = ActiveSupport::JSON.decode(@response.body).symbolize_keys!
43
+ assert !json[:success]
44
+ assert_equal json[:message], I18n.t("muck.activities.create_error", :error => assigns(:activity).errors.full_messages.to_sentence)
45
+ end
27
46
  end
28
-
29
- context 'on GET to comment (json)' do
47
+
48
+ context 'on POST to create (json)' do
30
49
  setup do
31
- @activity = Factory(:activity, :source => @user)
32
- @comment = Factory(:comment, :user => @user)
33
- get :comment, :id => @activity.id, :comment_id => @comment.id, :format => 'json'
34
- end
50
+ @activity_content = 'test content for my new activity'
51
+ post :create, :activity => { :content => @activity_content, :template => 'status_update' }, :parent_type => @user.type, :parent_id => @user, :format => 'json'
52
+ end
35
53
  should_respond_with :success
54
+ should_not_set_the_flash
55
+ should "return valid create json" do
56
+ json = ActiveSupport::JSON.decode(@response.body).symbolize_keys!
57
+ assert json[:success]
58
+ assert !json[:is_status_update]
59
+ assert json[:html].include?(@activity_content)
60
+ assert_equal json[:message], I18n.t("muck.activities.created")
61
+ end
36
62
  end
37
-
63
+
38
64
  context 'on POST to create (js)' do
39
65
  setup do
40
66
  post :create, :activity => { :content => 'test activity' }, :parent_type => @user.type, :parent_id => @user, :format => 'js'
@@ -42,7 +68,7 @@ class Muck::ActivitiesControllerTest < ActionController::TestCase
42
68
  should_respond_with :success
43
69
  should_not_set_the_flash
44
70
  end
45
-
71
+
46
72
  context 'on POST to create' do
47
73
  setup do
48
74
  post :create, :activity => { :content => 'test activity' }, :parent_type => @user.type, :parent_id => @user
@@ -61,13 +87,53 @@ class Muck::ActivitiesControllerTest < ActionController::TestCase
61
87
 
62
88
  context 'on DELETE to destroy (js)' do
63
89
  setup do
64
- @activity = Factory(:activity, :source => @user)
90
+ @activity = Factory(:activity, :source => @user, :is_status_update => false)
65
91
  delete :destroy, :id => @activity.id, :format => 'js'
66
92
  end
67
93
  should_respond_with :success
68
94
  should_not_set_the_flash
69
95
  end
70
96
 
97
+ context 'on DELETE to destroy, status update (js)' do
98
+ setup do
99
+ @activity = Factory(:activity, :source => @user, :is_status_update => true)
100
+ delete :destroy, :id => @activity.id, :format => 'js'
101
+ end
102
+ should_respond_with :success
103
+ should_not_set_the_flash
104
+ end
105
+
106
+ context 'on DELETE to destroy (json)' do
107
+ setup do
108
+ @activity = Factory(:activity, :source => @user, :is_status_update => false)
109
+ delete :destroy, :id => @activity.id, :format => 'json'
110
+ end
111
+ should_respond_with :success
112
+ should_not_set_the_flash
113
+ should "return valid delete json" do
114
+ json = ActiveSupport::JSON.decode(@response.body).symbolize_keys!
115
+ assert json[:success]
116
+ assert !json[:is_status_update]
117
+ assert json[:html].blank?
118
+ assert_equal json[:message], I18n.t("muck.activities.item_removed")
119
+ end
120
+ end
121
+
122
+ context 'on DELETE to destroy, status update (json)' do
123
+ setup do
124
+ @activity = Factory(:activity, :source => @user, :is_status_update => true)
125
+ delete :destroy, :id => @activity.id, :format => 'json'
126
+ end
127
+ should_respond_with :success
128
+ should_not_set_the_flash
129
+ should "return valid delete json" do
130
+ json = ActiveSupport::JSON.decode(@response.body).symbolize_keys!
131
+ assert json[:success]
132
+ assert json[:is_status_update]
133
+ assert json[:html].length > 0
134
+ assert_equal json[:message], I18n.t("muck.activities.item_removed")
135
+ end
136
+ end
71
137
  end
72
138
 
73
139
  end
@@ -15,7 +15,7 @@ class DefaultControllerTest < ActionController::TestCase
15
15
  # the default view calls some of the helpers
16
16
  # this is a sanity check to make sure they don't blow up
17
17
  setup do
18
- @user.activities << Factory(:activity)
18
+ @user.activities << Factory(:activity, :template => 'status_update')
19
19
  get :index
20
20
  end
21
21
  should_respond_with :success
@@ -1,5 +1,6 @@
1
1
  require File.dirname(__FILE__) + '/../test_helper'
2
2
 
3
3
  class ActivityFeedTest < ActiveSupport::TestCase
4
-
4
+ should_belong_to :activity
5
+ should_belong_to :ownable
5
6
  end
@@ -9,12 +9,15 @@ class ActivityTest < ActiveSupport::TestCase
9
9
  should_belong_to :item
10
10
  should_belong_to :source
11
11
  should_have_many :activity_feeds
12
+ should_have_many :comments
12
13
 
13
14
  should_have_named_scope :since
14
15
  should_have_named_scope :before
15
- should_have_named_scope :recent
16
+ should_have_named_scope :newest
16
17
  should_have_named_scope :only_public
17
18
  should_have_named_scope :filter_by_template
19
+ should_have_named_scope :status_updates
20
+
18
21
  end
19
22
 
20
23
  should "require template or item" do
@@ -54,4 +57,18 @@ class ActivityTest < ActiveSupport::TestCase
54
57
  assert user.activities.filter_by_template(@template_name).include?(activity)
55
58
  end
56
59
 
60
+ should "only find activities created by the source" do
61
+ user = Factory(:user)
62
+ activity = Factory(:activity, :source => user, :template => @template_name)
63
+ user.activities << activity
64
+
65
+ user2 = Factory(:user)
66
+ activity2 = Factory(:activity, :source => user2, :template => @template_name)
67
+ user2.activities << activity2
68
+
69
+ assert user.activities.created_by(user).include?(activity)
70
+ assert !user.activities.created_by(user).include?(activity2)
71
+
72
+ end
73
+
57
74
  end
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../test_helper'
2
+
3
+ class UserTest < ActiveSupport::TestCase
4
+ context "activities" do
5
+ setup do
6
+ @user = Factory(:user)
7
+ end
8
+ should_have_many :activity_feeds
9
+ should_have_many :activities
10
+ should "create an activity" do
11
+ assert_difference "Activity.count", 1 do
12
+ @user.add_activity(@user.feed_to, @user, @user, 'status_update', 'status', 'a status update')
13
+ end
14
+ end
15
+ should "set the user's current status" do
16
+ activity = @user.add_activity(@user.feed_to, @user, @user, 'status_update', 'status', 'a status update')
17
+ activity.is_status_update = true
18
+ activity.save!
19
+ assert_equal @user.status, activity
20
+ end
21
+ end
22
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: muck-activities
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.11
4
+ version: 0.1.12
5
5
  platform: ruby
6
6
  authors:
7
7
  - Justin Ball
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-06-19 00:00:00 -06:00
12
+ date: 2009-06-24 00:00:00 -06:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -57,7 +57,6 @@ files:
57
57
  - VERSION
58
58
  - app/controllers/muck/activities_controller.rb
59
59
  - app/helpers/muck_activity_helper.rb
60
- - app/models/activity.rb
61
60
  - app/models/activity_feed.rb
62
61
  - app/views/activities/_activity_feed.html.erb
63
62
  - app/views/activities/_cached_activities.html.erb
@@ -68,14 +67,15 @@ files:
68
67
  - app/views/activities/_delete.html.erb
69
68
  - app/views/activities/_status_update.html.erb
70
69
  - app/views/activities/_template_filter.html.erb
70
+ - app/views/activity_templates/_generic.html.erb
71
71
  - app/views/activity_templates/_status_update.html.erb
72
72
  - config/muck_activities_routes.rb
73
73
  - db/migrate/20090402033319_add_muck_activities.rb
74
74
  - install.rb
75
+ - lib/active_record/acts/muck_activity.rb
75
76
  - lib/muck_activities.rb
76
- - lib/muck_activities/active_record/acts/muck_activity.rb
77
77
  - lib/muck_activities/initialize_routes.rb
78
- - lib/muck_activities/muck_activity.rb
78
+ - lib/muck_activities/muck_activity_sources.rb
79
79
  - lib/muck_activities/tasks.rb
80
80
  - locales/ar.yml
81
81
  - locales/bg.yml
@@ -111,6 +111,7 @@ files:
111
111
  - locales/zh.yml
112
112
  - muck-activities.gemspec
113
113
  - pkg/muck-activities-0.1.10.gem
114
+ - pkg/muck-activities-0.1.11.gem
114
115
  - public/images/loading.gif
115
116
  - public/javascripts/muck_activities.js
116
117
  - rails/init.rb
@@ -142,7 +143,9 @@ files:
142
143
  - test/rails_root/app/controllers/default_controller.rb
143
144
  - test/rails_root/app/helpers/application_helper.rb
144
145
  - test/rails_root/app/models/.keep
146
+ - test/rails_root/app/models/activity.rb
145
147
  - test/rails_root/app/models/comment.rb
148
+ - test/rails_root/app/models/profile.rb
146
149
  - test/rails_root/app/models/user.rb
147
150
  - test/rails_root/app/models/user_session.rb
148
151
  - test/rails_root/app/views/default/index.html.erb
@@ -166,6 +169,7 @@ files:
166
169
  - test/rails_root/db/migrate/20090402234137_create_languages.rb
167
170
  - test/rails_root/db/migrate/20090426041056_create_countries.rb
168
171
  - test/rails_root/db/migrate/20090426041103_create_states.rb
172
+ - test/rails_root/db/migrate/20090512013727_create_profiles.rb
169
173
  - test/rails_root/db/migrate/20090602041838_create_users.rb
170
174
  - test/rails_root/db/migrate/20090613173314_create_comments.rb
171
175
  - test/rails_root/features/step_definitions/webrat_steps.rb
@@ -337,6 +341,7 @@ files:
337
341
  - test/rails_root/test/unit/.keep
338
342
  - test/rails_root/test/unit/activity_feed_test.rb
339
343
  - test/rails_root/test/unit/activity_test.rb
344
+ - test/rails_root/test/unit/user_test.rb
340
345
  - uninstall.rb
341
346
  has_rdoc: true
342
347
  homepage: http://github.com/jbasdf/muck_activities
@@ -368,7 +373,9 @@ test_files:
368
373
  - test/rails_root/app/controllers/application_controller.rb
369
374
  - test/rails_root/app/controllers/default_controller.rb
370
375
  - test/rails_root/app/helpers/application_helper.rb
376
+ - test/rails_root/app/models/activity.rb
371
377
  - test/rails_root/app/models/comment.rb
378
+ - test/rails_root/app/models/profile.rb
372
379
  - test/rails_root/app/models/user.rb
373
380
  - test/rails_root/app/models/user_session.rb
374
381
  - test/rails_root/config/boot.rb
@@ -386,6 +393,7 @@ test_files:
386
393
  - test/rails_root/db/migrate/20090402234137_create_languages.rb
387
394
  - test/rails_root/db/migrate/20090426041056_create_countries.rb
388
395
  - test/rails_root/db/migrate/20090426041103_create_states.rb
396
+ - test/rails_root/db/migrate/20090512013727_create_profiles.rb
389
397
  - test/rails_root/db/migrate/20090602041838_create_users.rb
390
398
  - test/rails_root/db/migrate/20090613173314_create_comments.rb
391
399
  - test/rails_root/db/schema.rb
@@ -400,3 +408,4 @@ test_files:
400
408
  - test/rails_root/test/test_helper.rb
401
409
  - test/rails_root/test/unit/activity_feed_test.rb
402
410
  - test/rails_root/test/unit/activity_test.rb
411
+ - test/rails_root/test/unit/user_test.rb
@@ -1,62 +0,0 @@
1
- # == Schema Information
2
- #
3
- # Table name: activities
4
- #
5
- # id :integer(4) not null, primary key
6
- # item_id :integer(4)
7
- # item_type :string(255)
8
- # template :string(255)
9
- # source_id :integer(4)
10
- # source_type :string(255)
11
- # content :text
12
- # title :string(255)
13
- # status_update :boolean(1)
14
- # created_at :datetime
15
- # updated_at :datetime
16
- #
17
-
18
- class Activity < ActiveRecord::Base
19
- unloadable
20
-
21
- belongs_to :item, :polymorphic => true
22
- belongs_to :source, :polymorphic => true
23
- has_many :activity_feeds
24
-
25
- acts_as_commentable
26
-
27
- validates_presence_of :source
28
-
29
- named_scope :since, lambda { |time| {:conditions => ["activities.created_at > ?", time] } }
30
- named_scope :before, lambda {|time| {:conditions => ["activities.created_at < ?", time] } }
31
- named_scope :recent, :order => "activities.created_at DESC"
32
- named_scope :after, lambda {|id| {:conditions => ["activities.id > ?", id] } }
33
- named_scope :only_public, :conditions => ["activities.is_public = true"]
34
- named_scope :filter_by_template, lambda { |template| { :conditions => ["activities.template = ?", template] } unless template.blank? }
35
-
36
- def validate
37
- errors.add_to_base(I18n.t('muck.activities.template_or_item_required')) if template.blank? && item.blank?
38
- end
39
-
40
- # Provides a template that can be used to render a view of this activity.
41
- # If 'template' is not specified when the object created then the item class
42
- # name will be used to generated a template
43
- def partial
44
- template || item.class.name.underscore
45
- end
46
-
47
- def has_comments?
48
- @has_comments ||= !self.comments.blank?
49
- end
50
-
51
- # Checks to see if the specified object can edit this activity.
52
- # Most likely check_object will be a user
53
- def can_edit?(check_object)
54
- if check_object.is_a?(User)
55
- return true if check(check_object, :source_id)
56
- else
57
- source == check_object
58
- end
59
- false
60
- end
61
-
62
- end
@@ -1,68 +0,0 @@
1
- module MuckActivity # :nodoc:
2
-
3
- def self.included(base) # :nodoc:
4
- base.extend ActMethods
5
- end
6
-
7
- module ActMethods
8
-
9
- # +has_activities+ gives the class it is called on an activity feed and a method called
10
- # +add_activity+ that can add activities into a feed. Retrieve activity feed items
11
- # via object.activities. ie @user.activities.
12
- def has_activities
13
- unless included_modules.include? InstanceMethods
14
- has_many :activity_feeds, :as => :ownable
15
- has_many :activities, :through => :activity_feeds, :order => 'created_at desc'
16
- include InstanceMethods
17
- end
18
- end
19
-
20
- # +acts_as_activity_source+ gives the class it is called on a method called
21
- # +add_activity+ that can add activities into a feed.
22
- def acts_as_activity_source
23
- unless included_modules.include? InstanceMethods
24
- include InstanceMethods
25
- end
26
- end
27
-
28
- end
29
-
30
- module InstanceMethods
31
-
32
- # +add_activity+ adds an activity to all activites feeds that belong to the objects found in feed_to.
33
- # * +feed_to+: an array of objects that have +has_activities+ declared on them. The generated activity
34
- # will be pushed into the feed of each of these objects.
35
- # * +source+: the object that peformed the activity ie a user or group
36
- # * +item+: an object that will be used to generated the entry in an activity feed
37
- # * +template+: name of an partial that will be used to generated the entry in the activity feed. Place
38
- # templates in /app/views/activity_templates
39
- # * +title+: optional title that can be used in the template
40
- # * +content+: option content that can be used in the template. Useful for activities that might not have
41
- # an item but instead might have a message or other text.
42
- # * +check_method+: method that will be called on each item in the feed_to array. If the method evaluates
43
- # to false the activity won't be added to the object's activity feed. An example usage would be
44
- # letting users configure which items they want to have in their activity feed.
45
- def add_activity(feed_to, source, item, template, title = '', content = '', check_method = nil)
46
- feed_to = [feed_to] unless feed_to.is_a?(Array)
47
- activity = Activity.create(:item => item, :source => source, :template => template, :title => title, :content => content)
48
- feed_to.each do |ft|
49
- if check_method
50
- ft.activities << activity if ft.send(check_method)
51
- else
52
- ft.activities << activity
53
- end
54
- end
55
- end
56
-
57
- # +status+ returns the first activity item from the user's activity feed that is a status update.
58
- # Used for displaying the last status update the user made
59
- def status
60
- self.activities.find(:first, :conditions => ['is_status_update = true'], :order => 'created_at DESC')
61
- end
62
-
63
- def can_view?(check_object)
64
- self == check_object
65
- end
66
- end
67
-
68
- end