social_stream-base 0.20.2 → 0.21.0

Sign up to get free protection for your applications and to get access to all the features.
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