social_stream 0.4.3 → 0.4.4

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.
Files changed (94) hide show
  1. data/app/controllers/api_controller.rb +1 -1
  2. data/app/controllers/contacts_controller.rb +1 -1
  3. data/app/controllers/conversations_controller.rb +5 -5
  4. data/app/controllers/groups_controller.rb +1 -0
  5. data/app/controllers/likes_controller.rb +17 -5
  6. data/app/controllers/messages_controller.rb +3 -1
  7. data/app/controllers/profiles_controller.rb +4 -0
  8. data/app/controllers/representations_controller.rb +12 -1
  9. data/app/controllers/tags_controller.rb +15 -0
  10. data/app/controllers/users_controller.rb +3 -0
  11. data/app/helpers/activities_helper.rb +13 -6
  12. data/app/models/activity.rb +53 -52
  13. data/app/models/activity_object.rb +2 -0
  14. data/app/models/actor.rb +85 -19
  15. data/app/models/avatar.rb +2 -1
  16. data/app/models/like.rb +28 -13
  17. data/app/models/permission.rb +7 -7
  18. data/app/models/profile.rb +1 -1
  19. data/app/models/relation/custom.rb +111 -0
  20. data/app/models/relation/public.rb +42 -0
  21. data/app/models/relation.rb +1 -89
  22. data/app/models/sphere.rb +7 -0
  23. data/app/models/tie.rb +65 -52
  24. data/app/models/tie_activity.rb +38 -0
  25. data/app/views/activities/_new.html.erb +4 -4
  26. data/app/views/activities/_options.html.erb +2 -2
  27. data/app/views/actors/_actor.html.erb +0 -0
  28. data/app/views/avatars/index.html.erb +5 -2
  29. data/app/views/comments/_new.html.erb +2 -2
  30. data/app/views/contacts/index.html.erb +5 -1
  31. data/app/views/conversations/edit.html.erb +4 -0
  32. data/app/views/conversations/index.html.erb +5 -1
  33. data/app/views/conversations/show.html.erb +4 -0
  34. data/app/views/frontpage/index.html.erb +4 -0
  35. data/app/views/groups/_sidebar_index.html.erb +7 -42
  36. data/app/views/groups/index.html.erb +3 -0
  37. data/app/views/groups/new.html.erb +3 -0
  38. data/app/views/groups/show.html.erb +7 -0
  39. data/app/views/layouts/_account.html.erb +16 -0
  40. data/app/views/layouts/_footer.html.erb +1 -1
  41. data/app/views/layouts/_header.erb +7 -22
  42. data/app/views/layouts/_representation.html.erb +25 -12
  43. data/app/views/layouts/application.html.erb +6 -3
  44. data/app/views/layouts/frontpage.html.erb +1 -1
  45. data/app/views/likes/create.js.erb +1 -1
  46. data/app/views/likes/destroy.js.erb +1 -1
  47. data/app/views/messages/new.html.erb +7 -5
  48. data/app/views/profiles/_profile.html.erb +20 -0
  49. data/app/views/profiles/edit.html.erb +42 -0
  50. data/app/views/profiles/show.html.erb +4 -0
  51. data/app/views/profiles/update.js.erb +5 -0
  52. data/app/views/subjects/_toolbar_profile_menu_tie_options.html.erb +3 -1
  53. data/app/views/ties/_new.html.erb +1 -1
  54. data/app/views/users/index.html.erb +4 -0
  55. data/app/views/users/show.html.erb +5 -0
  56. data/config/locales/en.yml +54 -1
  57. data/config/routes.rb +3 -1
  58. data/lib/generators/social_stream/install_generator.rb +2 -1
  59. data/lib/generators/social_stream/templates/migration.rb +23 -27
  60. data/lib/generators/social_stream/templates/public/images/btn/error.png +0 -0
  61. data/lib/generators/social_stream/templates/public/images/btn/info.png +0 -0
  62. data/lib/generators/social_stream/templates/public/images/btn/like.png +0 -0
  63. data/lib/generators/social_stream/templates/public/images/btn/nolike.png +0 -0
  64. data/lib/generators/social_stream/templates/public/images/btn/success.png +0 -0
  65. data/lib/generators/social_stream/templates/public/images/btn/warning.png +0 -0
  66. data/lib/generators/social_stream/templates/public/javascripts/ajax.paginate.js +12 -19
  67. data/lib/generators/social_stream/templates/public/javascripts/jquery.validate.js +1 -1
  68. data/lib/generators/social_stream/templates/public/javascripts/main.js +20 -10
  69. data/lib/generators/social_stream/templates/public/stylesheets/default/base.css +21 -4
  70. data/lib/generators/social_stream/templates/public/stylesheets/default/header.css +8 -3
  71. data/lib/generators/social_stream/templates/relations.yml +7 -13
  72. data/lib/social_stream/ability.rb +39 -20
  73. data/lib/social_stream/controllers/helpers.rb +6 -0
  74. data/lib/social_stream/models/object.rb +8 -4
  75. data/lib/social_stream/models/subject.rb +6 -0
  76. data/lib/social_stream/rails.rb +6 -3
  77. data/lib/social_stream/version.rb +1 -1
  78. data/lib/tasks/db/populate.rake +11 -1
  79. data/social_stream.gemspec +7 -8
  80. data/spec/controllers/comments_controller_spec.rb +6 -2
  81. data/spec/controllers/posts_controller_spec.rb +93 -5
  82. data/spec/controllers/profiles_controller_spec.rb +58 -1
  83. data/spec/controllers/representations_controller_spec.rb +51 -0
  84. data/spec/controllers/users_controller_spec.rb +28 -0
  85. data/spec/dummy/config/relations.yml +7 -13
  86. data/spec/dummy/db/schema.rb +2 -13
  87. data/spec/factories/tie.rb +1 -1
  88. data/spec/models/activity_spec.rb +28 -67
  89. data/spec/models/profile_spec.rb +38 -0
  90. data/spec/models/tie_activity_spec.rb +88 -31
  91. data/spec/models/tie_spec.rb +20 -14
  92. data/spec/support/db.rb +8 -10
  93. data/spec/support/migrations.rb +24 -0
  94. metadata +74 -59
@@ -43,10 +43,10 @@
43
43
  #
44
44
  # Available functions are:
45
45
  #
46
- # +tie+:: apply the permission to the established tie only.
46
+ # nil:: apply the permission to the established tie only.
47
47
  #
48
48
  # Example: if the _friend_ relation has the permission
49
- # <tt>create activity tie</tt>, the _friend_ can create activities
49
+ # <tt>create activity nil</tt>, the _friend_ can create activities
50
50
  # attached to this tie only. _Bob_ can create activities only at _Alice_'s
51
51
  # _friend_ level.
52
52
  #
@@ -90,17 +90,17 @@ class Permission < ActiveRecord::Base
90
90
  # The SQL and ARel conditions for permission queries
91
91
  ParameterConditions = {
92
92
  :table => {
93
- 'tie' =>
93
+ nil =>
94
94
  "ties_as.sender_id = ties.sender_id AND ties_as.receiver_id = ties.receiver_id AND ties_as.relation_id = ties.relation_id",
95
95
  'weak_ties' =>
96
- "ties_as.sender_id = ties.sender_id AND ties_as.receiver_id = ties.receiver_id AND relations.lft BETWEEN relations_as.lft AND relations_as.rgt",
96
+ "ties_as.sender_id = ties.sender_id AND ties_as.receiver_id = ties.receiver_id AND (relations.id = relations_as.id OR relations.ancestry = relations_as.id OR relations.ancestry = (relations_as.ancestry || '/' || relations_as.id) OR relations.ancestry LIKE (relations_as.id || '/%') OR relations.ancestry LIKE (relations_as.ancestry || '/' || relations_as.id || '/%'))",
97
97
  'star_ties' =>
98
98
  "ties_as.sender_id = ties.sender_id AND ties_as.relation_id = ties.relation_id",
99
99
  'weak_star_ties' =>
100
- "ties_as.sender_id = ties.sender_id AND relations.lft BETWEEN relations_as.lft AND relations_as.rgt"
100
+ "ties_as.sender_id = ties.sender_id AND (relations.id = relations_as.id OR relations.ancestry = relations_as.id OR relations.ancestry = (relations_as.ancestry || '/' || relations_as.id) OR relations.ancestry LIKE (relations_as.id || '/%') OR relations.ancestry LIKE (relations_as.ancestry || '/' || relations_as.id || '/%'))"
101
101
  },
102
102
  :arel => {
103
- 'tie' => lambda { |as, t|
103
+ nil => lambda { |as, t|
104
104
  # The same sender, receiver and relation
105
105
  as[:sender_id].eq(t.sender_id).and(
106
106
  as[:receiver_id].eq(t.receiver_id)).and(
@@ -141,7 +141,7 @@ class Permission < ActiveRecord::Base
141
141
  else
142
142
  ParameterConditions[:table].inject([]){ |result, pc|
143
143
  result <<
144
- sanitize_sql([ "#{ pc.last } AND permissions.function = ?", pc.first ])
144
+ "#{ pc.last } AND #{ sanitize_sql('permissions.function' => pc.first) }"
145
145
  }.join(" OR ")
146
146
  end
147
147
  end
@@ -1,6 +1,6 @@
1
1
  class Profile < ActiveRecord::Base
2
2
  belongs_to :actor
3
-
3
+
4
4
  accepts_nested_attributes_for :actor
5
5
 
6
6
  validates_presence_of :actor_id
@@ -0,0 +1,111 @@
1
+ # When a new {SocialStream::Models::Subject subject} is created, a initial set
2
+ # of relations is created for him. Afterwards, the {SocialStream::Models::Subject subject}
3
+ # can customize them and adapt them to his own preferences.
4
+ #
5
+ # Default relations are defined at config/relations.yml
6
+ #
7
+ class Relation::Custom < Relation
8
+ # Default relations are defined in this configuration file
9
+ CONFIG = File.join(::Rails.root, 'config', 'relations.yml')
10
+
11
+ # This is weird. We must call #inspect before has_ancestry for Relation::Custom
12
+ # to recognize STI
13
+ inspect
14
+ has_ancestry
15
+
16
+ belongs_to :sphere
17
+ has_one :actor, :through => :sphere
18
+
19
+ validates_presence_of :name, :sphere_id
20
+
21
+ after_create :initialize_tie
22
+
23
+ class << self
24
+ # Relations configuration
25
+ def config
26
+ @config ||= YAML.load_file(CONFIG)
27
+ end
28
+
29
+ def defaults_for(actor)
30
+ cfg_rels = config[actor.subject_type.underscore]
31
+
32
+ if cfg_rels.nil?
33
+ raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG }"
34
+ end
35
+
36
+ rels = {}
37
+
38
+ cfg_rels.each_pair do |name, cfg_rel|
39
+ raise("Must associatiate relation #{ cfg_rel['name'] } to a sphere") if cfg_rel['sphere'].blank?
40
+ sphere = actor.spheres.find_or_create_by_name(cfg_rel['sphere'])
41
+
42
+ rels[name] =
43
+ create! :sphere => sphere,
44
+ :receiver_type => cfg_rel['receiver_type'],
45
+ :name => cfg_rel['name']
46
+
47
+ if (ps = cfg_rel['permissions']).present?
48
+ ps.each do |p|
49
+ rels[name].permissions <<
50
+ Permission.find_or_create_by_action_and_object_and_function(*p)
51
+ end
52
+ end
53
+ end
54
+
55
+ # Parent, relations must be set after creation
56
+ # FIXME: Can fix with ruby 1.9 and ordered hashes
57
+ cfg_rels.each_pair do |name, cfg_rel|
58
+ rels[name].update_attribute(:parent, rels[cfg_rel['parent']]) if cfg_rel['parent'].present?
59
+ end
60
+
61
+ rels.values
62
+ end
63
+
64
+ # A relation in the top of a strength hierarchy
65
+ def strongest
66
+ roots
67
+ end
68
+ end
69
+
70
+ # Compare two relations
71
+ def <=> rel
72
+ return -1 if rel.is_a?(Public)
73
+
74
+ if ancestor_ids.include?(rel.id)
75
+ 1
76
+ elsif rel.ancestor_ids.include?(id)
77
+ -1
78
+ else
79
+ 0
80
+ end
81
+ end
82
+
83
+ # Other relations below in the same hierarchy that this relation
84
+ def weaker
85
+ descendants
86
+ end
87
+
88
+ # Relations below or at the same level of this relation
89
+ def weaker_or_equal
90
+ subtree
91
+ end
92
+
93
+ # Other relations above in the same hierarchy that this relation
94
+ def stronger
95
+ ancestors
96
+ end
97
+
98
+ # Relations above or at the same level of this relation
99
+ def stronger_or_equal
100
+ path
101
+ end
102
+
103
+
104
+ private
105
+
106
+ # Create reflexive tie for the owner of this {Relation::Custom custom relation}
107
+ def initialize_tie
108
+ ties.create! :sender => sphere.actor,
109
+ :receiver => sphere.actor
110
+ end
111
+ end
@@ -0,0 +1,42 @@
1
+ class Relation::Public < Relation
2
+ attr_accessor :actor
3
+
4
+ after_create :initialize_tie
5
+
6
+ scope :actor, lambda { |a|
7
+ joins(:ties).merge(Tie.sent_by(a))
8
+ }
9
+
10
+ class << self
11
+ def default_for(actor)
12
+ create! :actor => actor
13
+ end
14
+
15
+ # The {Relation::Public} belonging to actor
16
+ def of(actor)
17
+ actor(actor).first
18
+ end
19
+ end
20
+
21
+ # A {Relation::Public public relation} is always the weakest
22
+ def <=>(relation)
23
+ 1
24
+ end
25
+
26
+ # The name of public relation
27
+ def name
28
+ I18n.t('relation.public.name')
29
+ end
30
+
31
+ # Are we supporting custom permissions for {Relation::Public}? Not by the moment.
32
+ def allow?(user, action, object)
33
+ action == 'read' && object == 'activity'
34
+ end
35
+
36
+ private
37
+
38
+ def initialize_tie
39
+ ties.create! :sender => actor,
40
+ :receiver => actor
41
+ end
42
+ end
@@ -3,14 +3,6 @@
3
3
  # resources (transactions, lending and borrowing), messages or conversations,
4
4
  # physical connection and affiliation to same organizations.
5
5
  #
6
- # = Default relations
7
- #
8
- # When a new {SocialStream::Models::Subject subject} is created, a initial set
9
- # of relations is created for him. Afterwards, the {SocialStream::Models::Subject subject}
10
- # can customize them and adapt them to his own preferences.
11
- #
12
- # Default relations are defined at config/relations.yml
13
- #
14
6
  # = Strength hierarchies
15
7
  #
16
8
  # Relations are arranged in strength hierarchies, denoting that some ties between
@@ -27,66 +19,18 @@
27
19
  # See the documentation of {Permission} for more details on permission definition.
28
20
  #
29
21
  class Relation < ActiveRecord::Base
30
- # The actor this relation belongs to
31
- attr_accessor :actor
32
-
33
- # Default relations are defined in this configuration file
34
- CONFIG = File.join(::Rails.root, 'config', 'relations.yml')
35
-
36
- acts_as_nested_set
37
-
38
22
  scope :mode, lambda { |st, rt|
39
23
  where(:sender_type => st, :receiver_type => rt)
40
24
  }
41
25
 
42
- validates_presence_of :name
43
-
44
26
  has_many :relation_permissions, :dependent => :destroy
45
27
  has_many :permissions, :through => :relation_permissions
46
28
 
47
29
  has_many :ties, :dependent => :destroy
48
30
 
49
31
  before_create :initialize_sender_type
50
- after_create :initialize_ties
51
32
 
52
33
  class << self
53
- # Relations configuration
54
- def config
55
- @config ||= YAML.load_file(CONFIG)
56
- end
57
-
58
- def defaults_for(actor)
59
- cfg_rels = config[actor.subject_type.underscore]
60
-
61
- if cfg_rels.nil?
62
- raise "Undefined relations for subject type #{ actor.subject_type }. Please, add an entry to #{ CONFIG }"
63
- end
64
-
65
- rels = {}
66
-
67
- cfg_rels.each_pair do |name, cfg_rel|
68
- rels[name] =
69
- Relation.create! :actor => actor,
70
- :receiver_type => cfg_rel['receiver_type'],
71
- :name => cfg_rel['name']
72
-
73
- if (ps = cfg_rel['permissions']).present?
74
- ps.each do |p|
75
- rels[name].permissions <<
76
- Permission.find_or_create_by_action_and_object_and_function(*p)
77
- end
78
- end
79
- end
80
-
81
- # Parent, relations must be set after creation
82
- # FIXME: Can fix with ruby 1.9 and ordered hashes
83
- cfg_rels.each_pair do |name, cfg_rel|
84
- rels[name].update_attribute(:parent, rels[cfg_rel['parent']]) if cfg_rel['parent'].present?
85
- end
86
-
87
- rels.values
88
- end
89
-
90
34
  # Get relation from object, if possible
91
35
  #
92
36
  # Options::
@@ -120,31 +64,6 @@ class Relation < ActiveRecord::Base
120
64
  normalize(r, options).id
121
65
  end
122
66
  end
123
-
124
- # A relation in the top of a strength hierarchy
125
- def strongest
126
- root
127
- end
128
- end
129
-
130
- # Other relations below in the same hierarchy that this relation
131
- def weaker
132
- descendants
133
- end
134
-
135
- # Relations below or at the same level of this relation
136
- def weaker_or_equal
137
- self_and_descendants
138
- end
139
-
140
- # Other relations above in the same hierarchy that this relation
141
- def stronger
142
- ancestors
143
- end
144
-
145
- # Relations above or at the same level of this relation
146
- def stronger_or_equal
147
- self_and_ancestors
148
67
  end
149
68
 
150
69
  # Relation class scoped in the same mode that this relation
@@ -160,12 +79,5 @@ class Relation < ActiveRecord::Base
160
79
 
161
80
  self.sender_type = actor.subject_type
162
81
  end
163
-
164
- # Create reflexive ties for this actor
165
- def initialize_ties
166
- return if actor.blank?
167
-
168
- ties.create! :sender => actor,
169
- :receiver => actor
170
- end
171
82
  end
83
+
@@ -0,0 +1,7 @@
1
+ class Sphere < ActiveRecord::Base
2
+ belongs_to :actor
3
+
4
+ has_many :relations
5
+
6
+ validates_presence_of :name
7
+ end
data/app/models/tie.rb CHANGED
@@ -1,16 +1,19 @@
1
- # A tie is a link between two {Actor actors} with a {Relation relation}.
1
+ # A {Tie} is a link between two {Actor Actors} with a {Relation}.
2
2
  #
3
- # The first {Actor actor} is the sender of the {Tie tie}. The second {Actor actor}
4
- # is the receiver of the {Tie tie}.
3
+ # The first {Actor} is the sender of the {Tie}. The second {Actor}
4
+ # is the receiver of the {Tie}.
5
5
  #
6
6
  # = {Tie Ties} and {Activity activities}
7
- # {Activity Activities} are attached to {Tie ties}.
8
- # * The sender of the tie is the target of the {Activity}.
9
- # The wall-profile of an {Actor} is composed by the resources assigned to
10
- # the {Tie Ties} in which the {Actor} is the sender.
11
- # * The receiver {Actor} of the {Tie} is the author of the {Activity}.
7
+ # {Activity Activities} are attached to {Tie ties}. When _Alice_ post in _Bob_'s wall,
8
+ # the {Activity} is attached to the {Tie} from _Alice_ to _Bob_
9
+ #
10
+ # * The sender of the {Tie} is the author of the {Activity}.
12
11
  # It is the user that uploads a resource to the website or the social entity that
13
- # originates the {Activity}.
12
+ # originates the {Activity} (for example: add as contact).
13
+ #
14
+ # * The receiver {Actor} of the {Tie} is the receiver of the {Activity}.
15
+ # The {Activity} will appear in the wall of the receiver, depending on the permissions
16
+ #
14
17
  # * The {Relation} sets up the mode in which the {Activity} is shared.
15
18
  # It sets the rules, or {Permission Permissions}, by which {Actor} have access
16
19
  # to the {Activity}.
@@ -35,7 +38,6 @@
35
38
  # = Scopes
36
39
  # There are several scopes defined:
37
40
  #
38
- # original:: ties created by actors. It excludes ties created in the weaker set.
39
41
  # sent_by(actor):: ties whose sender is actor
40
42
  # received_by(actor):: ties whose receiver is actor
41
43
  # sent_or_received_by(actor):: the union of the former
@@ -45,13 +47,12 @@
45
47
  # is replied if there is a tie from b to a
46
48
  #
47
49
  class Tie < ActiveRecord::Base
48
- attr_accessor :message
49
- attr_accessor :relation_permissions
50
-
51
50
  # Facilitates relation assigment along with find_relation callback
52
51
  attr_writer :relation_name
53
52
  # Facilitates new relation permissions assigment along with find_or build_relation callback
54
- attr_reader :relation_permissions
53
+ attr_accessor :relation_sphere, :relation_permissions
54
+ # Send a message when this tie is created
55
+ attr_accessor :message
55
56
 
56
57
  belongs_to :sender,
57
58
  :class_name => "Actor",
@@ -65,9 +66,7 @@ class Tie < ActiveRecord::Base
65
66
  has_many :tie_activities, :dependent => :destroy
66
67
  has_many :activities, :through => :tie_activities
67
68
 
68
- scope :original, where(:original => true)
69
-
70
- scope :recent, order("#{ quoted_table_name }.created_at DESC")
69
+ scope :recent, order("ties.created_at DESC")
71
70
 
72
71
  scope :sent_by, lambda { |a|
73
72
  where(:sender_id => Actor.normalize_id(a))
@@ -94,17 +93,25 @@ class Tie < ActiveRecord::Base
94
93
  where("ties.sender_id = ties_2.receiver_id AND ties.receiver_id = ties_2.sender_id")
95
94
  }
96
95
 
96
+ scope :replying, lambda { |tie|
97
+ where(:sender_id => tie.receiver_id).
98
+ where(:receiver_id => tie.sender_id)
99
+ }
100
+
97
101
  scope :following, lambda { |a|
98
102
  where(:receiver_id => Actor.normalize_id(a)).
99
103
  joins(:relation => :permissions).merge(Permission.follow)
100
104
  }
101
105
 
106
+ scope :public_relation, lambda {
107
+ joins(:relation).where('relations.type' => 'Relation::Public')
108
+ }
109
+
102
110
  validates_presence_of :sender_id, :receiver_id, :relation
103
111
 
104
112
  before_validation :find_or_build_relation
105
113
 
106
114
  before_create :save_relation
107
- after_create :complete_weak_set
108
115
  after_create :create_activity
109
116
  after_create :send_message
110
117
 
@@ -185,12 +192,6 @@ class Tie < ActiveRecord::Base
185
192
  # We get the set of ties that are allowing certain permission
186
193
  #
187
194
 
188
- scope :with_permissions, lambda { |action, object|
189
- joins(:relation => :permissions).
190
- where('permissions.action' => action).
191
- where('permissions.object' => object)
192
- }
193
-
194
195
  # Given a given permission (action, object), the access_set are the set of ties that grant that permission.
195
196
  scope :access_set, lambda { |tie, action, object|
196
197
  with_permissions(action, object).
@@ -201,13 +202,13 @@ class Tie < ActiveRecord::Base
201
202
  query =
202
203
  select("DISTINCT ties.*").
203
204
  from("ties INNER JOIN relations ON relations.id = ties.relation_id, ties as ties_as INNER JOIN relations AS relations_as ON relations_as.id = ties_as.relation_id INNER JOIN relation_permissions ON relations_as.id = relation_permissions.relation_id INNER JOIN permissions ON permissions.id = relation_permissions.permission_id").
204
- where("permissions.action = ?", action).
205
- where("permissions.object = ?", object)
205
+ where("permissions.action" => action).
206
+ where("permissions.object" => object)
206
207
 
207
208
  conds = Permission.parameter_conditions
208
209
  # FIXME: Patch to support public activities
209
210
  if action == 'read' && object == 'activity'
210
- conds = sanitize_sql([ "( #{ conds } ) OR relations.name = ?", "public" ])
211
+ conds = "( #{ conds } ) OR #{ sanitize_sql('relations.type' => 'Relation::Public') }"
211
212
  end
212
213
 
213
214
  query.where(conds)
@@ -229,13 +230,38 @@ class Tie < ActiveRecord::Base
229
230
  end
230
231
 
231
232
  # Does this tie allows user to perform action on object?
232
- def allows?(user, action, object)
233
- # FIXME: Patch to support public activities
234
- return true if relation.name == 'public' && action == 'read' && object == 'activity'
233
+ #
234
+ # We allow all actions on reflexive ties
235
+ def allow?(user, action, object)
236
+ return true if Actor.normalize_id(user) == sender_id && reflexive?
237
+
238
+ # FIXME: Patch to support public activities.
239
+ if relation.is_a?(Relation::Public)
240
+ return relation.allow?(user, action, object)
241
+ end
235
242
 
236
243
  allowing(user, action, object).any?
237
244
  end
238
245
 
246
+ scope :with_permissions, lambda { |action, object|
247
+ joins(:relation => :permissions).
248
+ where('permissions.action' => action).
249
+ where('permissions.object' => object)
250
+ }
251
+
252
+ # All the ties that are allowed to follow activities from this tie
253
+ def followers
254
+ followers = Tie.received_by(sender).with_permissions('follow', nil)
255
+
256
+ unless relation.is_a?(Relation::Public)
257
+ allowed = access_set('read', 'activity').map(&:receiver_id)
258
+
259
+ followers = followers.sent_by(allowed)
260
+ end
261
+
262
+ followers
263
+ end
264
+
239
265
  private
240
266
 
241
267
  # Before validation callback
@@ -243,8 +269,8 @@ class Tie < ActiveRecord::Base
243
269
  def find_or_build_relation
244
270
  return if find_relation || relation_name.blank?
245
271
 
246
- self.relation = Relation.new :name => relation_name,
247
- :actor => sender
272
+ self.relation = Relation::Custom.new :name => relation_name,
273
+ :sphere => nil
248
274
 
249
275
  relation.permission_ids = relation_permissions
250
276
  end
@@ -265,34 +291,21 @@ class Tie < ActiveRecord::Base
265
291
  end
266
292
 
267
293
 
268
- # After create callback
269
- # Creates ties with weaker relations in the strength hierarchy of this tie
270
- def complete_weak_set
294
+ # After create callback to create related {Activity}
295
+ def create_activity
271
296
  return if reflexive?
272
297
 
273
- relation.weaker.each do |r|
274
- if relation_set(:relations => r).blank?
275
- t = relation_set.build :relation => r,
276
- :original => false
277
- t.save!
278
- end
279
- end
298
+ Activity.create! :_tie => self, :activity_verb => ActivityVerb[contact_verb]
280
299
  end
281
-
282
- def create_activity
283
- return if ! original? || reflexive?
284
300
 
285
- Activity.create! :_tie => self, :activity_verb => ActivityVerb[contact_verb]
301
+ def contact_verb
302
+ replied? ? "make-friend" : "follow"
286
303
  end
287
-
304
+
288
305
  # Send a message to the receiver of the tie
289
306
  def send_message
290
- if original? && message.present?
307
+ if message.present?
291
308
  sender.send_message(receiver, message, I18n.t("activity.verb.#{ contact_verb }.#{ receiver.subject_type }.message", :name => sender.name))
292
309
  end
293
310
  end
294
-
295
- def contact_verb
296
- replied? ? "make-friend" : "follow"
297
- end
298
311
  end
@@ -1,4 +1,42 @@
1
1
  class TieActivity < ActiveRecord::Base
2
2
  belongs_to :activity
3
3
  belongs_to :tie
4
+
5
+ after_create :disseminate
6
+
7
+ private
8
+
9
+ # Make a copy to all the ties that are both interesed and allowed to reach the activity
10
+ def disseminate
11
+ return unless original?
12
+
13
+ followers = tie.followers
14
+
15
+ # FIXME: here we need to check moderation and diffussion of the received activity.
16
+ #
17
+ # Sometimes, diffussion is not required, i.e. when the sender adds the receiver as contact
18
+ # Other times, the receiver must explicitly allow to post to her wall, and the dissemination permissions
19
+ # can control who else related with the receiver should receive the activity
20
+ receiver_ties =
21
+ Tie.
22
+ with_permissions('create', 'activity').
23
+ replying(tie)
24
+
25
+ if receiver_ties.present?
26
+ followers |= receiver_ties
27
+
28
+ # Disseminate to the followers of the receiver
29
+ receiver_ties.each do |t|
30
+ followers |= t.followers
31
+ end
32
+ end
33
+
34
+ # All the ties following the activities attached to this tie, allowed to read
35
+ # this activity
36
+ followers.each do |t|
37
+ self.class.create!(:activity_id => activity_id,
38
+ :tie => t,
39
+ :original => false)
40
+ end
41
+ end
4
42
  end
@@ -1,4 +1,4 @@
1
- <% if receiver.active_ties_for(current_subject).any? %>
1
+ <% if receiver.activity_ties_for?(current_subject) %>
2
2
  <% content_for :javascript do %>
3
3
 
4
4
  securityImage = "<%= escape_javascript(image_tag('btn/btn_security.png', :id => 'security_image', :alt => 'security')) %>";
@@ -11,14 +11,14 @@
11
11
 
12
12
  <div id="activities_header" class="content_size">
13
13
  <%= form_for Post.new(:text => t('activity.input'),
14
- :_activity_tie_id => receiver.active_ties_for(current_subject).first.id),
14
+ :_activity_tie_id => receiver.activity_ties_for(current_subject).first.id),
15
15
  :remote => true do |f| %>
16
16
  <%= f.text_field :text, :id => "input_activities", :size => 85 %>
17
17
  <div id="activities_share_btn">
18
18
 
19
- <% if receiver.active_ties_for(current_subject).count > 1 %>
19
+ <% if receiver.activity_ties_for(current_subject).count > 1 %>
20
20
  <div id="securities">
21
- <%= f.select :_activity_tie_id, receiver.active_ties_for(current_subject).sort{ |t, u| t.relation <=> u.relation }.map{ |t| [ t.relation_name, t.id ] }, {}, :id => 'security' %>
21
+ <%= f.select :_activity_tie_id, receiver.activity_ties_for(current_subject).sort{ |t, u| t.relation <=> u.relation }.map{ |t| [ t.relation_name, t.id ] }, {}, :id => 'security' %>
22
22
  </div>
23
23
  <% else %>
24
24
  <%= f.hidden_field :_activity_tie_id %>
@@ -1,11 +1,11 @@
1
1
  <div class="activity_options">
2
2
  <ul class="activity_options" >
3
3
  <li><div class="post_time_ago"><%= t('time.ago', :time => time_ago_in_words(activity.created_at)) %></div></li>
4
- <% if activity.is_root? && activity.receiver.sent_ties_allowing(current_subject, 'create', 'activity').any? %>
4
+ <% if activity.is_root? && activity.receiver.activity_ties_for?(current_subject) %>
5
5
  <li><div class="verb_comment"> · <%= link_to t('activity.to_comment'), "#", :class => "to_comment" %> </div></li>
6
6
  <% end %>
7
7
  <li><div class="verb_like" id="like_<%= dom_id(activity) %>"> · <%= link_like(activity)%></div></li>
8
- <% if activity.direct_object.present? %>
8
+ <% if activity.direct_object.present? && !activity.direct_object.is_a?(Actor) %>
9
9
  <li><div class="verb_delete"> · <%= link_to t('activity.delete'), activity.direct_object , :confirm => t('confirm_delete', :scope => activity.direct_object.class.to_s.underscore), :method => :delete, :remote => true %> </div></li>
10
10
  <% end %>
11
11
  </ul>
File without changes
@@ -5,6 +5,9 @@
5
5
  <%= javascript_include_tag 'avatars.js' %>
6
6
  <% end %>
7
7
 
8
+ <% content_for :title do%>
9
+ <%= current_subject.name %>
10
+ <% end%>
8
11
  <% content_for :sidebar do %>
9
12
  <%= render :partial => 'home/sidebar' %>
10
13
  <% end %>
@@ -18,7 +21,7 @@
18
21
  <div class="space_center"></div>
19
22
  <div class="space_center"></div>
20
23
  <% unless(@avatars.empty? || (@avatars.first.present? && @avatars.first.id.blank?)) %>
21
- <h2>Use your saved avatars ...</h2>
24
+ <h2><%=t('avatar.text.use') %></h2>
22
25
  <div class="space_center"></div>
23
26
  <div class="space_center"></div>
24
27
  <div class="avatars">
@@ -46,7 +49,7 @@
46
49
  <br class="clearfloat" />
47
50
  <div class="space_center"></div>
48
51
  <div class="space_center"></div>
49
- <h2>... our upload a new one</h2>
52
+ <h2><%=t('avatar.text.new') %></h2>
50
53
  <% else %>
51
54
  <h2><%= t('avatar.new') %></h2>
52
55
  <% end %>
@@ -1,8 +1,8 @@
1
- <% if activity.receiver.sent_ties_allowing(current_subject, 'create', 'activity').any? %>
1
+ <% if activity.receiver.activity_ties_for?(current_subject) %>
2
2
  <div class="activity_new_comment">
3
3
  <%= form_for Comment.new(:text => t('comment.input'),
4
4
  :_activity_tie_id =>
5
- activity.receiver.sent_ties_allowing(current_subject, 'create', 'activity').first.id,
5
+ activity.receiver.activity_ties_for(current_subject).first.id,
6
6
  :_activity_parent_id => activity.id),
7
7
  :remote => true do |f| %>
8
8
  <%= f.hidden_field :_activity_tie_id %>