social_stream-base 0.20.2 → 0.21.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Binary file
@@ -31,6 +31,8 @@ SocialStream.Timeline = (function(SS, $, undefined){
31
31
  $(fullId).hide();
32
32
  $(summaryId).tipsy({
33
33
  html: true,
34
+ hoverable: true,
35
+ opacity: 0.95,
34
36
  title: function(){
35
37
  return $(this).siblings('.activity_audience').html();
36
38
  }
@@ -38,6 +38,12 @@ SocialStream.Wall = (function(SS, $, undefined){
38
38
  });
39
39
  }
40
40
 
41
+ var changeSecurityImage = function(type) {
42
+ $('#security_chzn .chzn-choices').
43
+ css('background-image', 'url(<%= asset_path('btn/') %>' + type + '.png)');
44
+ }
45
+
46
+
41
47
  var initSecuritySelect = function(){
42
48
  var default_security_width = '100px';
43
49
 
@@ -63,6 +69,9 @@ SocialStream.Wall = (function(SS, $, undefined){
63
69
  chosen.results_update_field();
64
70
  }
65
71
  }
72
+ changeSecurityImage('public');
73
+ } else {
74
+ changeSecurityImage('restricted');
66
75
  }
67
76
  });
68
77
 
@@ -145,6 +154,6 @@ SocialStream.Wall = (function(SS, $, undefined){
145
154
  addInitCallback: addInitCallback,
146
155
  init: init,
147
156
  activateAntiRebounds: activateAntiRebounds,
148
- unblockForms: unblockForms
157
+ unblockForms: unblockForms
149
158
  };
150
159
  }) (SocialStream, jQuery)
@@ -27,7 +27,7 @@
27
27
 
28
28
  #security_chzn .chzn-choices {
29
29
  padding-left: 20px;
30
- background: url('btn/btn_security.png') no-repeat 10px center;
30
+ background: url('btn/restricted.png') no-repeat 10px center;
31
31
  }
32
32
  /******************* WALL - ACTIVITY ***************/
33
33
  .super_activity{width: 95%;}
@@ -55,7 +55,6 @@
55
55
 
56
56
  .security, .post_time_ago, .verb_comment, .verb_like, .verb_comment, .verb_delete{ display: inline-block;}
57
57
 
58
-
59
58
  /************* ACTIVITY - FOOTER *********/
60
59
  .space_comments { padding-top: 1px; padding-bottom: 1px;}
61
60
  .space_activities { text-align:center; padding: 0px 0px 0px 1px; width:100%;}
@@ -88,3 +87,15 @@
88
87
  .input_new_comments_container{min-height: 30px; position: relative; }
89
88
 
90
89
  .activity_likes{ margin-bottom: 2px; }
90
+
91
+ .timeline-130 {
92
+ width: 130px;
93
+ margin: 10px;
94
+ float: left;
95
+ }
96
+
97
+ .audience_logo {
98
+ padding: 2px;
99
+ display: inline-block;
100
+ }
101
+
@@ -137,7 +137,7 @@ div.chzn-container ul.chzn-choices li.search-field input{ cursor:pointer;}
137
137
 
138
138
  /*************MENU ICON SECTION**********/
139
139
  .menu_header{ border-bottom: thin solid $separation-color; width:14.5em; padding-left:3px; padding-right:3px;}
140
- .menu_icon{ vertical-align: middle; padding-bottom: 3px; padding-right: 3px; padding-left: 3px;
140
+ .menu_icon{ vertical-align: middle; padding-bottom: 3px; padding-right: 2px; padding-left: 2px;
141
141
  display: inline-block;}
142
142
 
143
143
  /*************SPACES SECTION *************/
@@ -0,0 +1,16 @@
1
+ class AudienceController < ApplicationController
2
+ before_filter :read_activity
3
+
4
+ respond_to :js
5
+
6
+ def index
7
+ end
8
+
9
+ private
10
+
11
+ def read_activity
12
+ @activity = Activity.find params[:activity_id]
13
+
14
+ authorize! :read, @activity
15
+ end
16
+ end
@@ -1,21 +1,32 @@
1
1
  # Activities follow the {Activity Streams}[http://activitystrea.ms/] standard.
2
2
  #
3
- # == {Activity Activities}, {Channel Channels} and Audiences
4
- # Every activity is attached to a {Channel}, which defines the sender and the receiver of the {Activity}
3
+ # Every {Activity} has an {#author}, {#user_author} and {#owner}
5
4
  #
6
- # Besides, the activity is attached to one or more relations, which define the audience of the activity,
7
- # in other words, the {actors Actor} that can reach it and their {permissions Permission}
5
+ # author:: Is the {SocialStream::Models::Subject subject} that originated
6
+ # the activity. The entity that posted something, liked, etc..
8
7
  #
9
- # == Wall
10
- # The Activity.wall(args) scope provides all the activities appearing in a wall
8
+ # user_author:: The {User} logged in when the {Activity} was created.
9
+ # If the {User} has not changed the session to represent
10
+ # other entity (a {Group} for example), the user_author
11
+ # will be the same as the author.
11
12
  #
12
- # There are two types of wall, :home and :profile. Check {Actor#wall} for more information
13
+ # owner:: The {SocialStream::Models::Subject subject} whose wall was posted
14
+ # or comment was liked, etc..
15
+ #
16
+ # == {Audience Audiences} and visibility
17
+ # Each activity is attached to one or more {Relation relations}, which define
18
+ # the {SocialStream::Models::Subject subject} that can reach the activity
19
+ #
20
+ # In the case of a {Relation::Public public relation} everyone will be
21
+ # able to see the activity.
22
+ #
23
+ # In the case of {Relation::Custom custom relations}, only the subjects
24
+ # that have a {Tie} with that relation (in other words, the contacts that
25
+ # have been added as friends with that relation} will be able to reach the {Activity}
13
26
  #
14
- include NotificationsHelper
15
-
16
27
  class Activity < ActiveRecord::Base
17
- # See {SocialStream::Models::Channeled}
18
- channeled
28
+ # FIXME: this does not follow the Rails way
29
+ include NotificationsHelper
19
30
 
20
31
  # This has to be declared before 'has_ancestry' to work around rails issue #670
21
32
  # See: https://github.com/rails/rails/issues/670
@@ -27,6 +38,13 @@ class Activity < ActiveRecord::Base
27
38
 
28
39
  belongs_to :activity_verb
29
40
 
41
+ belongs_to :author,
42
+ :class_name => "Actor"
43
+ belongs_to :owner,
44
+ :class_name => "Actor"
45
+ belongs_to :user_author,
46
+ :class_name => "Actor"
47
+
30
48
  has_many :audiences, :dependent => :destroy
31
49
  has_many :relations, :through => :audiences
32
50
 
@@ -35,10 +53,26 @@ class Activity < ActiveRecord::Base
35
53
  has_many :activity_objects,
36
54
  :through => :activity_object_activities
37
55
 
56
+ scope :authored_by, lambda { |subject|
57
+ where(:author_id => Actor.normalize_id(subject))
58
+ }
59
+ scope :owned_by, lambda { |subject|
60
+ where(:owner_id => Actor.normalize_id(subject))
61
+ }
62
+ scope :authored_or_owned_by, lambda { |subjects|
63
+ ids = Actor.normalize_id(subjects)
64
+
65
+ where(arel_table[:author_id].in(ids).or(arel_table[:owner_id].in(ids)))
66
+ }
67
+
68
+ scope :shared_with, lambda { |subject|
69
+ joins(:audiences).
70
+ merge(Audience.where(:relation_id => Relation.ids_shared_with(subject)))
71
+ }
72
+
38
73
  scope :wall, lambda { |args|
39
74
  q =
40
75
  select("DISTINCT activities.*").
41
- joins(:channel).
42
76
  joins(:audiences).
43
77
  joins(:relations).
44
78
  roots
@@ -48,14 +82,13 @@ class Activity < ActiveRecord::Base
48
82
  where('activity_objects.object_type' => args[:object_type])
49
83
  end
50
84
 
51
- channels = Channel.arel_table
52
85
  audiences = Audience.arel_table
53
86
  relations = Relation.arel_table
54
87
 
55
88
  owner_conditions =
56
- channels[:author_id].eq(Actor.normalize_id(args[:owner])).
57
- or(channels[:user_author_id].eq(Actor.normalize_id(args[:owner]))).
58
- or(channels[:owner_id].eq(Actor.normalize_id(args[:owner])))
89
+ arel_table[:author_id].eq(Actor.normalize_id(args[:owner])).
90
+ or(arel_table[:user_author_id].eq(Actor.normalize_id(args[:owner]))).
91
+ or(arel_table[:owner_id].eq(Actor.normalize_id(args[:owner])))
59
92
 
60
93
  audience_conditions =
61
94
  audiences[:relation_id].in(args[:relation_ids]).
@@ -65,16 +98,16 @@ class Activity < ActiveRecord::Base
65
98
  case args[:type]
66
99
  when :home
67
100
  followed_conditions =
68
- channels[:author_id].in(args[:followed]).
69
- or(channels[:owner_id].in(args[:followed]))
101
+ arel_table[:author_id].in(args[:followed]).
102
+ or(arel_table[:owner_id].in(args[:followed]))
70
103
 
71
104
  owner_conditions.
72
105
  or(followed_conditions.and(audience_conditions))
73
106
  when :profile
74
107
  if args[:for].present?
75
108
  visitor_conditions =
76
- channels[:author_id].eq(Actor.normalize_id(args[:for])).
77
- or(channels[:owner_id].eq(Actor.normalize_id(args[:for])))
109
+ arel_table[:author_id].eq(Actor.normalize_id(args[:for])).
110
+ or(arel_table[:owner_id].eq(Actor.normalize_id(args[:for])))
78
111
 
79
112
  owner_conditions.
80
113
  and(visitor_conditions.or(audience_conditions))
@@ -93,7 +126,7 @@ class Activity < ActiveRecord::Base
93
126
  after_create :increment_like_count
94
127
  after_destroy :decrement_like_count, :delete_notifications
95
128
 
96
- validates_presence_of :relations
129
+ validates_presence_of :author_id, :user_author_id, :owner_id, :relations
97
130
 
98
131
  #For now, it should be the last one
99
132
  #FIXME
@@ -109,12 +142,37 @@ class Activity < ActiveRecord::Base
109
142
  self.activity_verb = ActivityVerb[name]
110
143
  end
111
144
 
145
+ # The {SocialStream::Models::Subject subject} author
146
+ def author_subject
147
+ author.subject
148
+ end
149
+
150
+ # The {SocialStream::Models::Subject subject} owner
151
+ def owner_subject
152
+ owner.subject
153
+ end
154
+
155
+ # The {SocialStream::Models::Subject subject} user actor
156
+ def user_author_subject
157
+ user_author.subject
158
+ end
159
+
160
+ # Does this {Activity} have the same sender and receiver?
161
+ def reflexive?
162
+ author_id == owner_id
163
+ end
164
+
165
+ # Is the author represented in this {Activity}?
166
+ def represented_author?
167
+ author_id != user_author_id
168
+ end
169
+
112
170
  # The {Actor} author of this activity
113
171
  #
114
172
  # This method provides the {Actor}. Use {#sender_subject} for the {SocialStream::Models::Subject Subject}
115
173
  # ({User}, {Group}, etc..)
116
174
  def sender
117
- channel.author
175
+ author
118
176
  end
119
177
 
120
178
  # The {SocialStream::Models::Subject Subject} author of this activity
@@ -122,7 +180,7 @@ class Activity < ActiveRecord::Base
122
180
  # This method provides the {SocialStream::Models::Subject Subject} ({User}, {Group}, etc...).
123
181
  # Use {#sender} for the {Actor}.
124
182
  def sender_subject
125
- channel.author_subject
183
+ author_subject
126
184
  end
127
185
 
128
186
  # The wall where the activity is shown belongs to receiver
@@ -130,7 +188,7 @@ class Activity < ActiveRecord::Base
130
188
  # This method provides the {Actor}. Use {#receiver_subject} for the {SocialStream::Models::Subject Subject}
131
189
  # ({User}, {Group}, etc..)
132
190
  def receiver
133
- channel.owner
191
+ owner
134
192
  end
135
193
 
136
194
  # The wall where the activity is shown belongs to the receiver
@@ -138,7 +196,7 @@ class Activity < ActiveRecord::Base
138
196
  # This method provides the {SocialStream::Models::Subject Subject} ({User}, {Group}, etc...).
139
197
  # Use {#receiver} for the {Actor}.
140
198
  def receiver_subject
141
- channel.owner_subject
199
+ owner_subject
142
200
  end
143
201
 
144
202
  # The comments about this activity
@@ -152,7 +210,7 @@ class Activity < ActiveRecord::Base
152
210
  end
153
211
 
154
212
  def liked_by(user) #:nodoc:
155
- likes.joins(:channel).merge(Channel.subject_authored_by(user))
213
+ likes.authored_by(user)
156
214
  end
157
215
 
158
216
  # Does user like this activity?
@@ -162,12 +220,11 @@ class Activity < ActiveRecord::Base
162
220
 
163
221
  # Build a new children activity where subject like this
164
222
  def new_like(subject, user)
165
- channel = Channel.new :author => Actor.normalize(subject),
166
- :user_author => Actor.normalize(user),
167
- :owner => owner
168
- a = children.new :verb => "like",
169
- :channel => channel,
170
- :relation_ids => self.relation_ids
223
+ a = children.new :verb => "like",
224
+ :author_id => Actor.normalize_id(subject),
225
+ :user_author_id => Actor.normalize_id(user),
226
+ :owner_id => owner_id,
227
+ :relation_ids => self.relation_ids
171
228
 
172
229
  if direct_activity_object.present?
173
230
  a.activity_objects << direct_activity_object
@@ -218,7 +275,7 @@ class Activity < ActiveRecord::Base
218
275
  participants.each do |p|
219
276
  p.notify(notification_subject, "Youre not supposed to see this", self) unless p == sender
220
277
  end
221
- elsif ['like','follow','make-friend','post','update'].include? verb and !channel.reflexive?
278
+ elsif ['like','follow','make-friend','post','update'].include? verb and !reflexive?
222
279
  receiver.notify(notification_subject, "Youre not supposed to see this", self)
223
280
  end
224
281
  true
@@ -241,15 +298,15 @@ class Activity < ActiveRecord::Base
241
298
 
242
299
  # Is subject allowed to perform action on this {Activity}?
243
300
  def allow?(subject, action)
244
- return false if channel.blank?
301
+ return false if author.blank?
245
302
 
246
303
  case action
247
304
  when 'create'
248
- return false if subject.blank? || channel.author_id != Actor.normalize_id(subject)
305
+ return false if subject.blank? || author_id != Actor.normalize_id(subject)
249
306
 
250
307
  rels = Relation.normalize(relation_ids)
251
308
 
252
- own_rels = rels.select{ |r| r.actor_id == channel.author_id }
309
+ own_rels = rels.select{ |r| r.actor_id == author_id }
253
310
  # Consider Relation::Single as own_relations
254
311
  own_rels += rels.select{ |r| r.is_a?(Relation::Single) }
255
312
 
@@ -268,12 +325,12 @@ class Activity < ActiveRecord::Base
268
325
 
269
326
  return false if subject.blank?
270
327
 
271
- return true if [channel.author_id, channel.owner_id].include?(Actor.normalize_id(subject))
328
+ return true if [author_id, owner_id].include?(Actor.normalize_id(subject))
272
329
  when 'update'
273
- return true if [channel.author_id, channel.owner_id].include?(Actor.normalize_id(subject))
330
+ return true if [author_id, owner_id].include?(Actor.normalize_id(subject))
274
331
  when 'destroy'
275
332
  # We only allow destroying to sender and receiver by now
276
- return [channel.author_id, channel.owner_id].include?(Actor.normalize_id(subject))
333
+ return [author_id, owner_id].include?(Actor.normalize_id(subject))
277
334
  end
278
335
 
279
336
  Relation.
@@ -298,6 +355,21 @@ class Activity < ActiveRecord::Base
298
355
  allow?(subject, 'update')
299
356
  end
300
357
 
358
+ # Is this activity public?
359
+ def public?
360
+ relation_ids.include? Relation::Public.instance.id
361
+ end
362
+
363
+ # The {Actor Actors} this activity is shared with
364
+ def audience
365
+ raise "Cannot get the audience of a public activity!" if public?
366
+
367
+ [ author, user_author, owner ].uniq |
368
+ Actor.
369
+ joins(:received_ties).
370
+ merge(Tie.where(:relation_id => relation_ids))
371
+ end
372
+
301
373
  # The {Relation} with which activity is shared
302
374
  def audience_in_words(subject, options = {})
303
375
  options[:details] ||= :full
@@ -217,15 +217,7 @@ class ActivityObject < ActiveRecord::Base
217
217
 
218
218
  @valid_relations = true
219
219
 
220
- self.relation_ids =
221
- if SocialStream.relation_model == :custom
222
- owner.
223
- relations.
224
- allowing('read', 'activity').
225
- map(&:id)
226
- else
227
- Array.wrap Relation::Public.instance.id
228
- end
220
+ self.relation_ids = owner.activity_relation_ids
229
221
  end
230
222
 
231
223
  # validate method
data/app/models/actor.rb CHANGED
@@ -73,16 +73,6 @@ class Actor < ActiveRecord::Base
73
73
  has_many :relations,
74
74
  :dependent => :destroy
75
75
 
76
- has_many :authored_channels,
77
- :class_name => "Channel",
78
- :foreign_key => :author_id,
79
- :dependent => :destroy
80
-
81
- has_many :owned_channels,
82
- :class_name => "Channel",
83
- :foreign_key => :owner_id,
84
- :dependent => :destroy
85
-
86
76
  has_many :sent_actions,
87
77
  :class_name => "ActivityAction",
88
78
  :dependent => :destroy
@@ -328,11 +318,6 @@ class Actor < ActiveRecord::Base
328
318
  ties_to(subject).with_permissions(action, object).any?
329
319
  end
330
320
 
331
- # The {Channel} of this {Actor} to self (totally close!)
332
- def self_channel
333
- Channel.find_or_create_by_author_id_and_user_author_id_and_owner_id id, id, id
334
- end
335
-
336
321
  # Return the {ActivityAction} model to an {ActivityObject}
337
322
  def action_to(activity_object)
338
323
  sent_actions.received_by(activity_object).first
@@ -391,12 +376,26 @@ class Actor < ActiveRecord::Base
391
376
  any?
392
377
  end
393
378
 
394
- # An {Activity} can be shared with multiple {audicences Audience}, which corresponds to a {Relation}.
395
- #
396
- # This method returns all the {relations Relation} that this actor can use to broadcast an Activity
379
+ # The default {Relation Relations} for sharing an {Activity} owned
380
+ # by this {Actor}
381
+ def activity_relations
382
+ SocialStream.relation_model == :custom ?
383
+ relations.
384
+ allowing('read', 'activity') :
385
+ [ Relation::Public.instance ]
386
+ end
387
+
388
+ # The ids of the default {Relation Relations} for sharing an {Activity}
389
+ # owned by this {Actor}
390
+ def activity_relation_ids
391
+ activity_relations.map(&:id)
392
+ end
393
+
394
+ # This method returns all the {relations Relation} that subject can choose to broadcast an Activity in this {Actor}'s wall
397
395
  #
396
+ # See {Activity} on how they can be shared with multiple {audicences Audience}, which corresponds to a {Relation}.
398
397
  #
399
- def activity_relations(subject, options = {})
398
+ def activity_relations_for(subject, options = {})
400
399
  if Actor.normalize(subject) == self
401
400
  return relation_customs + Array.wrap(Relation::Public.instance)
402
401
  else
@@ -404,9 +403,9 @@ class Actor < ActiveRecord::Base
404
403
  end
405
404
  end
406
405
 
407
- # Are there any activity_relations present?
408
- def activity_relations?(*args)
409
- activity_relations(*args).any?
406
+ # Are {#activity_relations} available for subject?
407
+ def activity_relations_for?(subject, options = {})
408
+ activity_relations(subject, options).any?
410
409
  end
411
410
 
412
411
  # Is this {Actor} allowed to create a comment on activity?
@@ -459,37 +458,30 @@ class Actor < ActiveRecord::Base
459
458
  # the wall for members of the group.
460
459
  #
461
460
  def wall(type, options = {})
462
- args = {}
463
-
464
- args[:type] = type
465
- args[:owner] = self
466
- # Preserve this options
467
- [ :for, :object_type ].each do |opt|
468
- args[opt] = options[opt]
469
- end
461
+ options[:for] = self if type == :home
470
462
 
471
- if type == :home
472
- args[:followed] = Actor.followed_by(self).map(&:id)
473
- end
463
+ wall =
464
+ Activity.
465
+ select("DISTINCT activities.*").
466
+ roots.
467
+ includes(:author, :user_author, :owner, :activity_objects, :activity_verb, :relations)
474
468
 
475
- # TODO: this is not scalling for sure. We must use a fact table in the future
476
- args[:relation_ids] =
469
+ actor_ids =
477
470
  case type
478
471
  when :home
479
- # The relations from followings that can be read
480
- Relation.allow(self, 'read', 'activity').map(&:id)
472
+ following_actor_and_self_ids
481
473
  when :profile
482
- # FIXME: options[:relation]
483
- #
484
- # The relations that can be read by options[:for]
485
- options[:for].present? ?
486
- Relation.allow(options[:for], 'read', 'activity').map(&:id) :
487
- []
474
+ id
488
475
  else
489
476
  raise "Unknown type of wall: #{ type }"
490
477
  end
491
478
 
492
- Activity.wall args
479
+ wall = wall.authored_or_owned_by(actor_ids)
480
+
481
+ # Authentication
482
+ wall = wall.shared_with(options[:for])
483
+
484
+ wall = wall.order("created_at desc")
493
485
  end
494
486
 
495
487
  def logo
@@ -507,7 +499,7 @@ class Actor < ActiveRecord::Base
507
499
  end
508
500
 
509
501
  def liked_by(subject) #:nodoc:
510
- likes.joins(:channel).merge(Channel.subject_authored_by(subject))
502
+ likes.authored_by(subject)
511
503
  end
512
504
 
513
505
  # Does subject like this {Actor}?
@@ -517,14 +509,11 @@ class Actor < ActiveRecord::Base
517
509
 
518
510
  # Build a new activity where subject like this
519
511
  def new_like(subject, user)
520
- channel =
521
- Channel.
522
- find_or_create_by_author_id_and_user_author_id_and_owner_id Actor.normalize_id(subject),
523
- Actor.normalize_id(user),
524
- id
525
- a = Activity.new :verb => "like",
526
- :channel => channel,
527
- :relation_ids => Array(Relation::Public.instance.id)
512
+ a = Activity.new :verb => "like",
513
+ :author_id => Actor.normalize_id(subject),
514
+ :user_author_id => Actor.normalize_id(user),
515
+ :owner_id => id,
516
+ :relation_ids => Array(Relation::Public.instance.id)
528
517
 
529
518
  a.activity_objects << activity_object
530
519
 
@@ -164,27 +164,6 @@ class Contact < ActiveRecord::Base
164
164
  end
165
165
  end
166
166
 
167
- # The related {Channel} to this {Contact}.
168
- #
169
- # If the sender of this {Contact} is a user, the {Channel} is defined. If it is
170
- # other kind of {SocialStream::Models::Subject}, the {Channel#user_author} must
171
- # be provided.
172
- def channel(user = nil)
173
- user_id =
174
- if sender.subject_type == "User"
175
- sender_id
176
- elsif user.present? && Actor.normalize(user).subject_type == "User"
177
- Actor.normalize_id(user)
178
- else
179
- raise "Invalid channel user_author: #{ user.inspect }"
180
- end
181
-
182
- Channel.
183
- find_or_create_by_author_id_and_user_author_id_and_owner_id sender_id,
184
- user_id,
185
- receiver_id
186
- end
187
-
188
167
  private
189
168
 
190
169
  def build_user_author
data/app/models/tie.rb CHANGED
@@ -146,7 +146,7 @@ class Tie < ActiveRecord::Base
146
146
  Activity.create! :author => contact.sender,
147
147
  :user_author => contact.user_author,
148
148
  :owner => contact.receiver,
149
- :relation_ids => contact.relation_ids,
149
+ :relation_ids => contact.receiver.activity_relation_ids,
150
150
  :activity_verb => ActivityVerb[contact.verb]
151
151
  end
152
152
 
@@ -21,7 +21,7 @@
21
21
  <%= javascript_tag do %>
22
22
  var relation_public = <%= Relation::Public.instance.id %>;
23
23
  var public_selected = false;
24
- var relation_options = <%= escape_javascript(current_subject.activity_relations(receiver).sort.map{ |r| r.id }.to_json) %>;
24
+ var relation_options = <%= escape_javascript(current_subject.activity_relations_for(receiver).sort.map{ |r| r.id }.to_json) %>;
25
25
  var relation_public_pos = 0;
26
26
  for(id in relation_options){
27
27
  if(relation_options[id]==relation_public){
@@ -32,7 +32,7 @@
32
32
  }
33
33
  //For security with check "var default_security_width = '100px';" in activities.js.erb
34
34
  <% end %>
35
- <%= select_tag :relation_ids, options_for_select(current_subject.activity_relations(receiver).sort.map{ |r| [ r.name, r.id ] }), :id => 'security', :multiple => true, :title => t("activity.privacy.myself.contacts.#{ receiver.class.to_s.underscore }") %>
35
+ <%= select_tag :relation_ids, options_for_select(current_subject.activity_relations_for(receiver).sort.map{ |r| [ r.name, r.id ] }), :id => 'security', :multiple => true, :title => t("activity.privacy.myself.contacts.#{ receiver.class.to_s.underscore }") %>
36
36
  <% else %>
37
37
  <div id="security_chzn" class="chzn-container chzn-container-multi">
38
38
  <ul class="chzn-choices">
@@ -8,11 +8,17 @@
8
8
 
9
9
  <% if user_signed_in? %>
10
10
  ·
11
- <%= link_to activity.audience_in_words(current_subject, :details => :summary),
11
+ <%= link_to image_tag("btn/#{ activity.public? ? 'public' : 'restricted' }.png", :class => 'menu_icon') + activity.audience_in_words(current_subject, :details => :summary),
12
12
  'javascript:;',
13
13
  :class => 'activity_audience_summary' %>
14
14
  <div class="activity_audience">
15
15
  <%= activity.audience_in_words(current_subject) %>
16
+ <% unless activity.public? %>
17
+ ·
18
+ <%= link_to t('activity.audience.show'), audience_path(:activity_id => activity.id), :remote => true %>
19
+ <div class="activity-audience-list-<%= activity.id %>">
20
+ </div>
21
+ <% end %>
16
22
  </div>
17
23
  <% end %>
18
24
 
@@ -0,0 +1,8 @@
1
+ <% @activity.audience.each do |a| %>
2
+ <div class="audience_logo">
3
+ <%= link_to image_tag(a.logo.url(:contact),
4
+ :alt => a.name),
5
+ a.subject,
6
+ :title => a.name %>
7
+ </div>
8
+ <% end %>
@@ -0,0 +1 @@
1
+ $('.activity-audience-list-<%= @activity.id %>').html('<%= j render(:partial => 'list') %>');
@@ -38,6 +38,7 @@ en:
38
38
  public:
39
39
  summary: "Public"
40
40
  full: "Shared with all the Internet"
41
+ show: "Mostrar"
41
42
  visible:
42
43
  summary: "Restricted"
43
44
  full: "Shared with %{audience}"
@@ -38,6 +38,7 @@ es:
38
38
  public:
39
39
  summary: "Público"
40
40
  full: "Accesible por toda Internet"
41
+ show: "Show"
41
42
  visible:
42
43
  summary: "Restringido"
43
44
  full: "Compartido con %{audience}"
data/config/routes.rb CHANGED
@@ -86,6 +86,8 @@ Rails.application.routes.draw do
86
86
  resources :activities do
87
87
  resource :like
88
88
  end
89
+
90
+ get 'audience/index', :as => :audience
89
91
 
90
92
  match 'cheesecake' => 'cheesecake#index', :as => :cheesecake
91
93
  match 'update_cheesecake' => 'cheesecake#update', :as => :update_cheesecake
@@ -0,0 +1,35 @@
1
+ class RemoveActivityChannels < ActiveRecord::Migration
2
+ class Channel < ActiveRecord::Base; end
3
+
4
+ def up
5
+ change_table :activities do |t|
6
+ t.references :author
7
+ t.references :user_author
8
+ t.references :owner
9
+ end
10
+
11
+ Activity.record_timestamps = false
12
+ Activity.reset_column_information
13
+
14
+ Activity.all.each do |a|
15
+ c = Channel.find a.channel_id
16
+ %w{ author_id user_author_id owner_id }.each do |m|
17
+ a.__send__ "#{ m }=", c.__send__(m) # a.author_id = c.author_id
18
+ end
19
+ a.save!
20
+ end
21
+
22
+ Activity.record_timestamps = true
23
+
24
+ remove_foreign_key :activities, :name => 'index_activities_on_channel_id'
25
+ remove_column :activities, :channel_id
26
+
27
+ Activity.reset_column_information
28
+
29
+ drop_table :channels
30
+ end
31
+
32
+ def down
33
+ raise ActiveRecord::IrreversibleMigration
34
+ end
35
+ end
@@ -58,7 +58,9 @@ module SocialStream
58
58
  end
59
59
 
60
60
  can :read, Activity do |a|
61
- a.allow?(subject, 'read')
61
+ a.public? ||
62
+ subject.present? &&
63
+ a.audience.include?(subject.actor)
62
64
  end
63
65
 
64
66
  can :update, Activity do |a|
@@ -20,7 +20,6 @@ module SocialStream
20
20
 
21
21
  initializer "social_stream-base.model.supertypes" do
22
22
  ActiveSupport.on_load(:active_record) do
23
- include SocialStream::Models::Channeled::ActiveRecord
24
23
  include SocialStream::Models::Subtype::ActiveRecord
25
24
  include SocialStream::Models::Supertype::ActiveRecord
26
25
  end
@@ -1,5 +1,5 @@
1
1
  module SocialStream
2
2
  module Base
3
- VERSION = "0.20.2".freeze
3
+ VERSION = "0.21.0".freeze
4
4
  end
5
5
  end
@@ -19,7 +19,6 @@ module SocialStream
19
19
  end
20
20
 
21
21
  module Models
22
- autoload :Channeled, 'social_stream/models/channeled'
23
22
  autoload :Object, 'social_stream/models/object'
24
23
  autoload :Subject, 'social_stream/models/subject'
25
24
  autoload :Subtype, 'social_stream/models/subtype'
@@ -112,14 +112,16 @@ namespace :db do
112
112
  ties_start = Time.now
113
113
 
114
114
  @available_actors.each do |a|
115
- actors = @available_actors.dup - Array(a)
116
- relations = a.relation_customs + Array.wrap(Relation::Reject.instance)
117
- break if actors.size==0
115
+ actors = @available_actors.dup
116
+ actors.delete(a)
117
+
118
+ relations = a.relation_customs + [ Relation::Reject.instance ]
119
+
118
120
  Forgery::Basic.number(:at_most => actors.size).times do
119
121
  actor = actors.delete_at((rand * actors.size).to_i)
120
122
  contact = a.contact_to!(actor)
121
123
  contact.user_author = a.user_author if a.subject_type != "User"
122
- contact.relation_ids = Array(Forgery::Extensions::Array.new(relations).random.id) unless a==actor
124
+ contact.relation_ids = [ Forgery::Extensions::Array.new(relations).random.id ]
123
125
  end
124
126
  end
125
127
 
@@ -0,0 +1,40 @@
1
+ require 'spec_helper'
2
+
3
+ describe AudienceController do
4
+ include SocialStream::TestHelpers
5
+ include SocialStream::TestHelpers::Controllers
6
+
7
+ render_views
8
+
9
+ context "with activity" do
10
+ before :all do
11
+ @activity = Factory(:activity)
12
+ end
13
+
14
+ it "should not be redered to public" do
15
+ get :index, :activity_id => @activity.id, :format => :js
16
+
17
+ response.should redirect_to(:new_user_session)
18
+ end
19
+
20
+ it "should not be rendered to anyone" do
21
+ sign_in Factory(:user)
22
+
23
+ begin
24
+ get :index, :activity_id => @activity.id, :format => :js
25
+
26
+ assert false
27
+ rescue CanCan::AccessDenied
28
+ assert true
29
+ end
30
+ end
31
+
32
+ it "should not be rendered to author" do
33
+ sign_in @activity.author_subject
34
+
35
+ get :index, :activity_id => @activity.id, :format => :js
36
+
37
+ response.should be_success
38
+ end
39
+ end
40
+ end
@@ -13,7 +13,7 @@ describe CommentsController do
13
13
 
14
14
  describe "comment from user" do
15
15
  before do
16
- activity = Factory(:self_activity, :channel => @user.self_channel)
16
+ activity = Factory(:self_activity, :author => @user.actor)
17
17
 
18
18
  model_attributes[:author_id] = @user.actor_id
19
19
  model_attributes[:owner_id] = @user.actor_id
@@ -38,7 +38,7 @@ describe CommentsController do
38
38
  describe "comment to friend" do
39
39
  before do
40
40
  f = Factory(:friend, :contact => Factory(:contact, :receiver => @user.actor)).sender
41
- activity = Factory(:self_activity, :channel => f.contact_to!(f).channel)
41
+ activity = Factory(:self_activity, :author => f)
42
42
 
43
43
  model_attributes[:author_id] = @user.actor_id
44
44
  model_attributes[:owner_id] = f.id
@@ -52,7 +52,7 @@ describe CommentsController do
52
52
  describe "post to acquaintance" do
53
53
  before do
54
54
  a = Factory(:acquaintance, :contact => Factory(:contact, :receiver => @user.actor)).sender
55
- activity = Factory(:self_activity, :channel => a.self_channel)
55
+ activity = Factory(:self_activity, :author => a)
56
56
 
57
57
  model_attributes[:author_id] = @user.actor_id
58
58
  model_attributes[:owner_id] = a.id
@@ -23,9 +23,11 @@ end
23
23
  ## End of helpers
24
24
 
25
25
  Factory.define :activity do |a|
26
- a.channel { Factory(:friend).contact.channel }
26
+ a.author { Factory(:user).actor }
27
+ a.user_author { |b| b.author }
28
+ a.owner { |b| Factory(:friend, :contact => Factory(:contact, :receiver => b.author)).sender }
27
29
  a.activity_verb { ActivityVerb["post"] }
28
- a.relation_ids { |b| Array(b.sender.relation_custom('friend').id) }
30
+ a.relation_ids { |b| [ b.owner.relation_custom('friend').id ] }
29
31
  a.activity_object_ids { |b|
30
32
  # Create post
31
33
  post = Factory(:post,
@@ -40,8 +42,10 @@ Factory.define :activity do |a|
40
42
  end
41
43
 
42
44
  Factory.define :self_activity, :parent => :activity do |a|
43
- a.channel { Factory(:self_contact).channel }
44
- a.relation_ids { |b| Array(b.sender.relation_custom('friend').id) }
45
+ a.author { Factory(:user).actor }
46
+ a.user_author { |b| b.author }
47
+ a.owner { |b| b.author }
48
+ a.relation_ids { |b| [ b.author.relation_custom('friend').id ] }
45
49
  a.activity_object_ids { |b|
46
50
  # Create post
47
51
  post = Factory(:post,
@@ -63,10 +67,12 @@ end
63
67
 
64
68
  Factory.define :like_activity, :class => 'Activity' do |a|
65
69
  a.association :parent, :factory => :activity
66
- a.channel { |b| Factory(:friend, :sender => b.parent.sender).receiver.contact_to!(b.parent.sender).channel }
70
+ a.author { |b| Factory(:friend, :sender => b.parent.owner).receiver }
71
+ a.user_author { |b| b.author }
72
+ a.owner { |b| b.parent.owner }
67
73
  a.activity_verb { ActivityVerb["like"] }
68
74
  a.relation_ids { |b| b.parent.relation_ids }
69
- a.after_build{ |b| b.activity_object_ids = b.parent.activity_object_ids }
75
+ a.after_build { |b| b.activity_object_ids = b.parent.activity_object_ids }
70
76
  end
71
77
 
72
78
 
@@ -41,8 +41,9 @@ describe Tie do
41
41
  end
42
42
 
43
43
  it "should create activity with follow verb" do
44
- @tie.contact.channel.activities.should be_present
45
- @tie.contact.channel.activities.first.verb.should eq('follow')
44
+ activity = Activity.authored_by(@tie.sender).owned_by(@tie.receiver).first
45
+ activity.should be_present
46
+ activity.verb.should eq('follow')
46
47
  end
47
48
 
48
49
  context "reciprocal" do
@@ -51,8 +52,10 @@ describe Tie do
51
52
  end
52
53
 
53
54
  it "should create activity with make-friend verb" do
54
- @reciprocal.contact.channel.activities.should be_present
55
- @reciprocal.contact.channel.activities.first.verb.should eq('make-friend')
55
+ activity = Activity.authored_by(@reciprocal.sender).owned_by(@reciprocal.receiver).first
56
+
57
+ activity.should be_present
58
+ activity.verb.should eq('make-friend')
56
59
  end
57
60
  end
58
61
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: social_stream-base
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.20.2
4
+ version: 0.21.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-17 00:00:00.000000000 Z
13
+ date: 2012-05-27 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: deep_merge
@@ -596,7 +596,6 @@ files:
596
596
  - app/assets/images/btn/btn_profile.png
597
597
  - app/assets/images/btn/btn_rank.png
598
598
  - app/assets/images/btn/btn_read.png
599
- - app/assets/images/btn/btn_security.png
600
599
  - app/assets/images/btn/btn_send.png
601
600
  - app/assets/images/btn/btn_spam.png
602
601
  - app/assets/images/btn/btn_star.png
@@ -636,6 +635,8 @@ files:
636
635
  - app/assets/images/btn/point_blue.png
637
636
  - app/assets/images/btn/point_gray.png
638
637
  - app/assets/images/btn/post.png
638
+ - app/assets/images/btn/public.png
639
+ - app/assets/images/btn/restricted.png
639
640
  - app/assets/images/btn/search.png
640
641
  - app/assets/images/btn/search_icon.png
641
642
  - app/assets/images/btn/shadow.png
@@ -770,6 +771,7 @@ files:
770
771
  - app/controllers/activities_controller.rb
771
772
  - app/controllers/activity_actions_controller.rb
772
773
  - app/controllers/api_controller.rb
774
+ - app/controllers/audience_controller.rb
773
775
  - app/controllers/authentications_controller.rb
774
776
  - app/controllers/cheesecake_controller.rb
775
777
  - app/controllers/comments_controller.rb
@@ -821,7 +823,6 @@ files:
821
823
  - app/models/actor.rb
822
824
  - app/models/audience.rb
823
825
  - app/models/authentication.rb
824
- - app/models/channel.rb
825
826
  - app/models/comment.rb
826
827
  - app/models/contact.rb
827
828
  - app/models/group.rb
@@ -858,6 +859,8 @@ files:
858
859
  - app/views/actors/_actor.html.erb
859
860
  - app/views/actors/_actor_cheesecake.html.erb
860
861
  - app/views/api/activity_atom_feed.atom.builder
862
+ - app/views/audience/_list.html.erb
863
+ - app/views/audience/index.js.erb
861
864
  - app/views/avatars/index.html.erb
862
865
  - app/views/avatars/update.js.erb
863
866
  - app/views/cheesecake/_cheesecake.html.erb
@@ -1055,6 +1058,7 @@ files:
1055
1058
  - db/migrate/20120403175913_create_activity_object_audiences.rb
1056
1059
  - db/migrate/20120411132550_add_visit_count_to_activity_object.rb
1057
1060
  - db/migrate/20120411151413_relation_public_permissions.rb
1061
+ - db/migrate/20120526171311_remove_activity_channels.rb
1058
1062
  - lib/acts_as_taggable_on/acts_as_taggable_on/dirty.rb
1059
1063
  - lib/acts_as_taggable_on/social_stream.rb
1060
1064
  - lib/generators/social_stream/base/install_generator.rb
@@ -1109,7 +1113,6 @@ files:
1109
1113
  - lib/social_stream/d3.rb
1110
1114
  - lib/social_stream/migrations/base.rb
1111
1115
  - lib/social_stream/migrations/components.rb
1112
- - lib/social_stream/models/channeled.rb
1113
1116
  - lib/social_stream/models/object.rb
1114
1117
  - lib/social_stream/models/subject.rb
1115
1118
  - lib/social_stream/models/subtype.rb
@@ -1132,6 +1135,7 @@ files:
1132
1135
  - lib/tasks/workers.rake
1133
1136
  - lib/thinking-sphinx/social_stream.rb
1134
1137
  - social_stream-base.gemspec
1138
+ - spec/controllers/audience_controller_spec.rb
1135
1139
  - spec/controllers/comments_controller_spec.rb
1136
1140
  - spec/controllers/contacts_controller_spec.rb
1137
1141
  - spec/controllers/followers_controller_spec.rb
Binary file
@@ -1,64 +0,0 @@
1
- # A {Channel} is the union of the three {Actors} that are involved in an {Activity}:
2
- #
3
- # * The author that creates a post, comment, etc. This can be a {User}, {Group}
4
- # or any kind of {SocialStream::Models::Subject subject}
5
- # * The user_author representing the author. When users change session and
6
- # act in behalf of a {Group}, Social Stream still records which user is responsible
7
- # for an {Activity}
8
- # * The owner in whose wall the Activity is performed.
9
- #
10
- class Channel < ActiveRecord::Base
11
- # Author can be any type of Actor: User, Group, etc.
12
- belongs_to :author,
13
- :class_name => "Actor"
14
- # Owner is the wall's subject this object is posted to
15
- belongs_to :owner,
16
- :class_name => "Actor"
17
-
18
- # UserAuthor is the real user behind the Author
19
- belongs_to :user_author,
20
- :class_name => "Actor"
21
-
22
- has_many :activities, :dependent => :destroy
23
-
24
- validates_uniqueness_of :author_id, :scope => [ :owner_id, :user_author_id ]
25
- validates_uniqueness_of :owner_id, :scope => [ :author_id, :user_author_id ]
26
- validates_uniqueness_of :user_author_id, :scope => [ :author_id, :owner_id ]
27
-
28
- scope :authored_by, lambda { |subject|
29
- id = Actor.normalize_id subject
30
-
31
- where(arel_table[:author_id].eq(id).or(arel_table[:user_author_id].eq(id)))
32
- }
33
-
34
- scope :subject_authored_by, lambda { |subject|
35
- id = Actor.normalize_id subject
36
-
37
- where(:author_id => id)
38
- }
39
-
40
- # The {SocialStream::Models::Subject subject} author
41
- def author_subject
42
- author.subject
43
- end
44
-
45
- # The {SocialStream::Models::Subject subject} owner
46
- def owner_subject
47
- owner.subject
48
- end
49
-
50
- # The {SocialStream::Models::Subject subject} user actor
51
- def user_author_subject
52
- user_author.subject
53
- end
54
-
55
- # Does this {Channel} have the same sender and receiver?
56
- def reflexive?
57
- author_id == owner_id
58
- end
59
-
60
- # Is the author represented in this {Channel}?
61
- def represented_author?
62
- author_id != user_author_id
63
- end
64
- end
@@ -1,56 +0,0 @@
1
- module SocialStream
2
- module Models
3
- # Models that have author, user_author and owner, properties saved in {Channel}.
4
- # Currently {Activity} and {ActivityObject}
5
- module Channeled
6
- # Add the method {#channeled} to ActiveRecord
7
- module ActiveRecord
8
- extend ActiveSupport::Concern
9
-
10
- module ClassMethods
11
- # This class is channeled. See {Channel}
12
- def channeled
13
- include SocialStream::Models::Channeled
14
- end
15
- end
16
- end
17
-
18
- extend ActiveSupport::Concern
19
-
20
- included do
21
- # Channeled models are subtypes of {Channel}
22
- # Author, owner and user_author are defined in its channel
23
- subtype_of :channel,
24
- :belongs => { :dependent => nil }
25
-
26
- # before_validation :set_owner_id, :on => :create
27
-
28
- before_validation :check_existing_channel
29
- end
30
-
31
- protected
32
-
33
- # Use existing channel, do not create a new one
34
- def check_existing_channel
35
- return unless channel!.new_record?
36
-
37
- existing_channel =
38
- Channel.
39
- where(:author_id => author_id,
40
- :owner_id => owner_id,
41
- :user_author_id => user_author_id).
42
- first
43
-
44
- return if existing_channel.blank?
45
-
46
- self.channel = existing_channel
47
- end
48
-
49
- private
50
-
51
- def set_owner_id
52
- self.owner_id ||= author_id
53
- end
54
- end
55
- end
56
- end