social_stream-base 0.6.3 → 0.6.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (93) hide show
  1. data/app/assets/stylesheets/base.css +1 -0
  2. data/app/assets/stylesheets/contacts.css +2 -1
  3. data/app/assets/stylesheets/fcbkComplete.css +1 -1
  4. data/app/assets/stylesheets/header.css +2 -2
  5. data/app/assets/stylesheets/messages.css +3 -3
  6. data/app/assets/stylesheets/{spheres.css → relation_customs.css} +0 -0
  7. data/app/controllers/contacts_controller.rb +9 -4
  8. data/app/controllers/messages_controller.rb +69 -68
  9. data/app/controllers/relation/customs_controller.rb +1 -11
  10. data/app/helpers/activities_helper.rb +1 -2
  11. data/app/helpers/notifications_helper.rb +3 -2
  12. data/app/helpers/permissions_helper.rb +5 -5
  13. data/app/helpers/subjects_helper.rb +9 -0
  14. data/app/helpers/toolbar_helper.rb +10 -89
  15. data/app/models/activity.rb +39 -15
  16. data/app/models/actor.rb +30 -71
  17. data/app/models/contact.rb +15 -0
  18. data/app/models/group.rb +1 -3
  19. data/app/models/permission.rb +9 -72
  20. data/app/models/profile.rb +7 -2
  21. data/app/models/relation/custom.rb +6 -33
  22. data/app/models/relation.rb +15 -39
  23. data/app/models/user.rb +5 -1
  24. data/app/views/activities/_new.html.erb +5 -2
  25. data/app/views/activities/_options.html.erb +2 -2
  26. data/app/views/activities/_walls.html.erb +1 -1
  27. data/app/views/contacts/_contact.html.erb +3 -3
  28. data/app/views/contacts/_form.html.erb +14 -20
  29. data/app/views/contacts/_index.html.erb +1 -1
  30. data/app/views/contacts/_suggestions.html.erb +1 -13
  31. data/app/views/contacts/destroy.js.erb +6 -0
  32. data/app/views/contacts/edit.html.erb +1 -1
  33. data/app/views/conversations/_conversation.html.erb +1 -1
  34. data/app/views/groups/_group.html.erb +1 -1
  35. data/app/views/groups/_index.html.erb +1 -1
  36. data/app/views/groups/show.html.erb +1 -1
  37. data/app/views/invitation_mailer/send_invitation.html.erb +17 -6
  38. data/app/views/invitation_mailer/send_invitation.text.erb +7 -2
  39. data/app/views/layouts/_representation.html.erb +10 -6
  40. data/app/views/layouts/_settings.html.erb +1 -1
  41. data/app/views/messages/_message.html.erb +1 -1
  42. data/app/views/messages/new.html.erb +1 -1
  43. data/app/views/notifications/_notification.html.erb +7 -3
  44. data/app/views/objects/_new.html.erb +0 -6
  45. data/app/views/profiles/edit.html.erb +5 -9
  46. data/app/views/relation/customs/_form.html.erb +2 -2
  47. data/app/views/{spheres → relation/customs}/_jquery.erb +0 -58
  48. data/app/views/relation/customs/_list.html.erb +9 -26
  49. data/app/views/relation/customs/create.js.erb +2 -3
  50. data/app/views/relation/customs/index.html.erb +67 -0
  51. data/app/views/users/_index.html.erb +1 -1
  52. data/app/views/users/show.html.erb +1 -1
  53. data/config/locales/en.yml +16 -41
  54. data/config/routes.rb +1 -6
  55. data/db/migrate/20110705103202_empty_ties_count.rb +4 -0
  56. data/db/migrate/20110712090343_remove_spheres.rb +30 -0
  57. data/db/migrate/20110712142140_remove_permission_function.rb +26 -0
  58. data/lib/generators/social_stream/base/install_generator.rb +4 -0
  59. data/lib/generators/social_stream/base/templates/mailboxer_custom.rb +13 -0
  60. data/lib/generators/social_stream/base/templates/navigation.rb +4 -0
  61. data/lib/generators/social_stream/base/templates/relations.yml +14 -20
  62. data/lib/social_stream/ability.rb +1 -2
  63. data/lib/social_stream/base/version.rb +1 -1
  64. data/lib/social_stream/migration_finder.rb +19 -0
  65. data/lib/social_stream/toolbar_config.rb +113 -0
  66. data/lib/social_stream-base.rb +1 -0
  67. data/lib/tasks/db/populate.rake +1 -1
  68. data/social_stream-base.gemspec +4 -2
  69. data/spec/controllers/contacts_controller_spec.rb +1 -1
  70. data/spec/controllers/permissions_controller_spec.rb +1 -2
  71. data/spec/controllers/posts_controller_spec.rb +2 -2
  72. data/spec/controllers/relation_customs_controller_spec.rb +69 -62
  73. data/spec/dummy/config/database.yml +7 -0
  74. data/spec/dummy/config/relations.yml +14 -20
  75. data/spec/factories/relation_custom.rb +1 -1
  76. data/spec/factories/tie.rb +4 -0
  77. data/spec/models/activity_spec.rb +11 -2
  78. data/spec/models/user_spec.rb +68 -9
  79. data/spec/spec_helper.rb +0 -3
  80. data/spec/support/db.rb +9 -0
  81. data/spec/support/migrations.rb +3 -12
  82. metadata +19 -25
  83. data/app/controllers/spheres_controller.rb +0 -12
  84. data/app/models/sphere.rb +0 -9
  85. data/app/views/relation/customs/_index.html.erb +0 -28
  86. data/app/views/relation/customs/index.js.erb +0 -2
  87. data/app/views/spheres/_form.html.erb +0 -28
  88. data/app/views/spheres/_list.html.erb +0 -19
  89. data/app/views/spheres/create.js.erb +0 -20
  90. data/app/views/spheres/index.html.erb +0 -74
  91. data/spec/controllers/spheres_controller_spec.rb +0 -116
  92. data/spec/factories/sphere.rb +0 -5
  93. data/spec/models/relation_custom_spec.rb +0 -14
data/app/models/actor.rb CHANGED
@@ -56,11 +56,6 @@ class Actor < ActiveRecord::Base
56
56
  :uniq => true
57
57
 
58
58
  has_many :relations
59
- has_many :spheres
60
-
61
- has_many :relation_customs,
62
- :through => :spheres,
63
- :source => :customs
64
59
 
65
60
  scope :alphabetic, order('actors.name')
66
61
 
@@ -140,12 +135,31 @@ class Actor < ActiveRecord::Base
140
135
  end
141
136
  end
142
137
 
138
+ # Returns the email used for Mailboxer
139
+ def mailboxer_email
140
+ return email if email.present?
141
+ if (group = self.subject).is_a? Group
142
+ relation = group.relation_customs.sort.first
143
+ receivers = group.contact_actors(:direction => :sent, :relations => relation)
144
+ emails = Array.new
145
+ receivers.each do |receiver|
146
+ emails << receiver.mailboxer_email
147
+ end
148
+ return emails
149
+ end
150
+ end
151
+
143
152
  # The subject instance for this actor
144
153
  def subject
145
154
  subtype_instance ||
146
155
  activity_object.try(:object)
147
156
  end
148
157
 
158
+ # All the {Relation relations} defined by this {Actor}
159
+ def relation_customs
160
+ relations.where(:type => 'Relation::Custom')
161
+ end
162
+
149
163
  # A given relation defined and managed by this actor
150
164
  def relation_custom(name)
151
165
  relation_customs.find_by_name(name)
@@ -161,7 +175,7 @@ class Actor < ActiveRecord::Base
161
175
  # Options:
162
176
  # * type: Filter by the class of the contacts.
163
177
  # * direction: sent or received
164
- # * relations: Restrict the relations of considered ties
178
+ # * relations: Restrict the relations of considered ties. Defaults to {Relation::Custom relations of custom type}
165
179
  # * include_self: False by default, don't include this actor as subject even they have ties with themselves.
166
180
  #
167
181
  def contact_actors(options = {})
@@ -169,15 +183,15 @@ class Actor < ActiveRecord::Base
169
183
  subject_classes = subject_types.map{ |s| s.to_s.classify }
170
184
 
171
185
  as = Actor.select("DISTINCT actors.*").
172
- where('actors.subject_type' => subject_classes).
173
- includes(subject_types)
186
+ where('actors.subject_type' => subject_classes).
187
+ includes(subject_types)
174
188
 
175
189
 
176
190
  case options[:direction]
177
191
  when :sent
178
- as = as.contacted_from(self)
192
+ as = as.joins(:received_ties => :relation).merge(Contact.sent_by(self))
179
193
  when :received
180
- as = as.contacted_to(self)
194
+ as = as.joins(:sent_ties => :relation).merge(Contact.received_by(self))
181
195
  else
182
196
  raise "contact actors in both directions are not supported yet"
183
197
  end
@@ -187,7 +201,9 @@ class Actor < ActiveRecord::Base
187
201
  end
188
202
 
189
203
  if options[:relations].present?
190
- as = as.joins(:ties).merge(Tie.related_by(options[:relations]))
204
+ as = as.merge(Tie.related_by(options[:relations]))
205
+ else
206
+ as = as.merge(Relation.where(:type => 'Relation::Custom'))
191
207
  end
192
208
 
193
209
  as
@@ -241,7 +257,7 @@ class Actor < ActiveRecord::Base
241
257
  # Candidates are all the instance of "type" minus all the subjects
242
258
  # that are receiving any tie from this actor
243
259
  candidates = candidates_classes.inject([]) do |cs, klass|
244
- cs += klass.all - contact_subjects(:type => klass.to_s.underscore, :direction => :sent)
260
+ cs += klass.all - contact_subjects(:type => klass.to_s.underscore, :direction => :sent, :relations => relations.to_a)
245
261
  cs -= Array(subject) if subject.is_a?(klass)
246
262
  cs
247
263
  end
@@ -250,7 +266,7 @@ class Actor < ActiveRecord::Base
250
266
 
251
267
  return nil unless candidate.present?
252
268
 
253
- Contact.new :sender => self, :receiver => candidate.actor
269
+ contact_to!(candidate)
254
270
  end
255
271
 
256
272
  # Set of ties sent by this actor received by subject
@@ -279,30 +295,15 @@ class Actor < ActiveRecord::Base
279
295
  any?
280
296
  end
281
297
 
282
- # The relations that allow attaching an activity to them. This method is used for caching
283
- def active_relations
284
- @active_relations ||= { :sender => {}, :receiver => {} }
285
- end
286
-
287
298
  # An {Activity} can be shared with multiple {audicences Audience}, which corresponds to a {Relation}.
288
299
  #
289
300
  # This method returns all the {relations Relation} that this actor can use to broadcast an Activity
290
301
  #
291
- # Options:
292
- # from:: limit the relations to one side, from the :sender or the :receiver of the activity
293
302
  #
294
303
  def activity_relations(subject, options = {})
295
304
  return relations if Actor.normalize(subject) == self
296
305
 
297
- case options[:from]
298
- when :sender
299
- sender_activity_relations(subject)
300
- when :receiver
301
- receiver_activity_relations(subject)
302
- else
303
- sender_activity_relations(subject) +
304
- receiver_activity_relations(subject)
305
- end
306
+ Array.new
306
307
  end
307
308
 
308
309
  # Are there any activity_relations present?
@@ -310,48 +311,6 @@ class Actor < ActiveRecord::Base
310
311
  activity_relations(*args).any?
311
312
  end
312
313
 
313
- # Relations from this actor that can be read by subject
314
- def sender_activity_relations(subject)
315
- active_relations[:sender][subject] ||=
316
- Relation.allow(subject, 'read', 'activity', :owner => self)
317
- end
318
-
319
- def receiver_activity_relations(subject)
320
- active_relations[:receiver][subject] ||=
321
- Relation.allow(self, 'create', 'activity', :owner => subject)
322
- end
323
-
324
- # Builds a hash of options their spheres as keys
325
- def grouped_activity_relations(subject)
326
- rels = activity_relations(subject)
327
-
328
- spheres =
329
- rels.map{ |r| r.respond_to?(:sphere) ? r.sphere : I18n.t('relation_public.name') }.uniq
330
-
331
- spheres.sort!{ |x, y|
332
- case x
333
- when Sphere
334
- case y
335
- when Sphere
336
- x.id <=> y.id
337
- else
338
- -1
339
- end
340
- else
341
- 1
342
- end
343
- }
344
-
345
- spheres.map{ |s|
346
- case s
347
- when Sphere
348
- [ s.name, rels.select{ |r| r.respond_to?(:sphere) && r.sphere == s }.sort.map{ |u| [ u.name, u.id ] } ]
349
- else
350
- [ s, rels.select{ |r| r.is_a?(Relation::Public) }.map{ |u| [ u.name, u.id ] } ]
351
- end
352
- }
353
- end
354
-
355
314
  # Is this {Actor} allowed to create a comment on activity?
356
315
  #
357
316
  # We are allowing comments from everyone signed in by now
@@ -100,6 +100,21 @@ class Contact < ActiveRecord::Base
100
100
  association(:relations).ids_writer(ids)
101
101
  end
102
102
 
103
+ # Is this {Contact} +new+ or +edit+ for {SocialStream::Models::Subject subject} ?
104
+ #
105
+ # action is +new+ when, despite of being created, it has not {Tie ties} or it has a {Tie} with a
106
+ # {Relation::Public public relation}.
107
+ #
108
+ # The contact's action is +edit+ when it has any {Tie} with a {Relation::Custom custom relation}
109
+ #
110
+ def action
111
+ if ties_count > 0 && relations.where(:type => 'Relation::Custom').any?
112
+ 'edit'
113
+ else
114
+ 'new'
115
+ end
116
+ end
117
+
103
118
  private
104
119
 
105
120
  def remove_follower(ids)
data/app/models/group.rb CHANGED
@@ -23,9 +23,7 @@ class Group < ActiveRecord::Base
23
23
  merge(Contact.recent)
24
24
  end
25
25
  end
26
-
27
- private
28
-
26
+
29
27
  # Creates the ties between the group and the founder
30
28
  def create_founder
31
29
  founder =
@@ -1,5 +1,5 @@
1
- # SocialStream provides a sophisticated and powerful system of permissions based on the {Relation relations}
2
- # of the social network.
1
+ # SocialStream provides a system of permissions based on the {Relation relations}
2
+ # of the social network as roles.
3
3
  #
4
4
  # = Permissions and Relations
5
5
  #
@@ -13,9 +13,9 @@
13
13
  #
14
14
  # = Permissions description
15
15
  #
16
- # Permissions are composed by *action*, *objective* and *function*. Action and objective
16
+ # Permissions are composed by *action* and *object*. Action and object
17
17
  # are typical in content management systems, e.g. <tt>create activity</tt>,
18
- # <tt>update tie</tt>, <tt>read post</tt>. *function* is a new parameter for social networks
18
+ # <tt>update tie</tt>, <tt>read post</tt>.
19
19
  #
20
20
  # == Actions
21
21
  #
@@ -32,33 +32,8 @@
32
32
  #
33
33
  # +activity+:: all the objects in a wall: posts, comments
34
34
  #
35
- # Other objectives currently not implemented could be +tie+, +post+, +comment+ or +message+
35
+ # Other objects currently not implemented could be +tie+, +post+, +comment+ or +message+
36
36
  #
37
- # == Functions
38
- #
39
- # Function is a novel feature. It supports applying the permission to other related relations and ties.
40
- # It is required because the set of ties changes while {SocialStream::Models::Subject subjects } build their network.
41
- # Besides {SocialStream::Models::Subject subjects} can describe and
42
- # customize their own relations and permissions.
43
- #
44
- # Available functions are:
45
- #
46
- # +same_level+:: the permission applies to all the objects in same relation
47
- #
48
- # Example: the _friend_ relation has the permission
49
- # <tt>read tie same_level</tt>. If _Alice_ has a _friend_ tie with
50
- # _Bob_, she is granting him access to read all the contacts of type _friend_
51
- ##
52
- # +same_and_lower_levels+:: apply the permission to all the related objects attached to a relation weaker
53
- # or equal than this.#
54
- #
55
- # Example: if the _member_ relation of a group has the permission
56
- # <tt>create activity same_and_lower_levels</tt>, its members
57
- # can also create activities attached to the weaker relations of
58
- # _acquaintance_ and _public_.
59
- # This means than a group _member_ can create activities at different
60
- # levels of the sphere, and therefore, with different levels of
61
- # access.
62
37
  #
63
38
  class Permission < ActiveRecord::Base
64
39
  has_many :relation_permissions, :dependent => :destroy
@@ -68,51 +43,13 @@ class Permission < ActiveRecord::Base
68
43
  scope p, where(:action => p) # scope :represent, where(:action => 'represent')
69
44
  end
70
45
 
71
- RelationConditions = {
72
- 'same_level' =>
73
- "relations.id = relations_as.id",
74
- 'same_and_lower_levels' =>
75
- "(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 || '/%')) OR (relations.actor_id = relations_as.actor_id AND relations.type = 'Relation::Public')"
76
- }
77
-
78
- class << self
79
- # Builds SQL conditions based on {RelationConditions}
80
- def relation_conditions
81
- RelationConditions.inject([]){ |result, pc|
82
- result <<
83
- "(#{ pc.last }) AND #{ sanitize_sql('permissions_as.function' => pc.first) }"
84
- }.join(" OR ")
85
- end
86
- end
87
-
88
46
  # An explanation of the permissions. Type can be brief or detailed.
89
- # If detailed, description includes details about the relation
47
+ # If detailed, description includes more information about the relation
90
48
  def description(type, relation = nil)
91
- options = ( relation.present? ? description_options(relation) : {} )
49
+ options = {}
50
+ options[:relation] = relation.name if relation.present?
92
51
 
93
- I18n.t "permission.description.#{ type }.#{ action }.#{ object || "nil" }.#{ function || "nil" }",
52
+ I18n.t "permission.description.#{ type }.#{ action }.#{ object || "nil" }",
94
53
  options
95
54
  end
96
-
97
- private
98
-
99
- def description_options(relation)
100
- {
101
- :sphere => relation.sphere.name,
102
- :public => I18n.t('relation_public.name')
103
- }.tap do |h|
104
- case function
105
- when NilClass, "same_level"
106
- h[:relation] = relation.name
107
- when "same_and_lower_levels"
108
- h[:relations] = relation.
109
- weaker_or_equal.
110
- sort.
111
- map(&:name).
112
- join(", ")
113
-
114
- end
115
- end
116
-
117
- end
118
55
  end
@@ -17,18 +17,23 @@ class Profile < ActiveRecord::Base
17
17
 
18
18
  validate :validate_birthday
19
19
 
20
- def birthday=(value)
20
+ def birthday=(value)
21
+
22
+ puts "He entrado en el metodo birthday con un :" + value.class.to_s
23
+
21
24
  if value.blank?
22
25
  @birthday_formatted_invalid = false
23
26
  super value
24
27
  else
25
28
  begin
26
- super Date.parse(value)
29
+ #super Date.parse(value)
30
+ super value
27
31
  @birthday_formatted_invalid = false
28
32
  rescue
29
33
  @birthday_formatted_invalid = true
30
34
  end
31
35
  end
36
+
32
37
  end
33
38
 
34
39
  def age
@@ -13,16 +13,10 @@ class Relation::Custom < Relation
13
13
  inspect
14
14
  has_ancestry
15
15
 
16
- attr_protected :actor_id
17
-
18
- belongs_to :sphere
19
16
  belongs_to :actor
20
17
 
21
- validates_presence_of :name, :sphere_id, :actor_id
22
- validates_uniqueness_of :name, :scope => :sphere_id
23
-
24
- before_validation :assign_parent, :on => :create
25
- before_validation :assign_actor, :on => :create
18
+ validates_presence_of :name, :actor_id
19
+ validates_uniqueness_of :name, :scope => :actor_id
26
20
 
27
21
  class << self
28
22
  # Relations configuration
@@ -40,18 +34,15 @@ class Relation::Custom < Relation
40
34
  rels = {}
41
35
 
42
36
  cfg_rels.each_pair do |name, cfg_rel|
43
- raise("Must associatiate relation #{ cfg_rel['name'] } to a sphere") if cfg_rel['sphere'].blank?
44
- sphere = actor.spheres.find_or_create_by_name(cfg_rel['sphere'])
45
-
46
37
  rels[name] =
47
- create! :sphere => sphere,
48
- :receiver_type => cfg_rel['receiver_type'],
49
- :name => cfg_rel['name']
38
+ create! :actor => actor,
39
+ :name => cfg_rel['name'],
40
+ :receiver_type => cfg_rel['receiver_type']
50
41
 
51
42
  if (ps = cfg_rel['permissions']).present?
52
43
  ps.each do |p|
53
44
  rels[name].permissions <<
54
- Permission.find_or_create_by_action_and_object_and_function(*p)
45
+ Permission.find_or_create_by_action_and_object(*p)
55
46
  end
56
47
  end
57
48
  end
@@ -103,22 +94,4 @@ class Relation::Custom < Relation
103
94
  def stronger_or_equal
104
95
  path
105
96
  end
106
-
107
- private
108
-
109
- # Before create callback
110
- #
111
- # Assign the last relation as parent if there are other custom relations in the sphere
112
- def assign_parent
113
- return if parent.present? || sphere.customs.blank?
114
-
115
- self.parent = sphere.customs.sort.last
116
- end
117
-
118
- # Before create callback
119
- #
120
- # Assign the sphere's actor
121
- def assign_actor
122
- self.actor = sphere.actor
123
- end
124
97
  end
@@ -30,6 +30,7 @@ class Relation < ActiveRecord::Base
30
30
  has_many :permissions, :through => :relation_permissions
31
31
 
32
32
  has_many :ties, :dependent => :destroy
33
+ has_many :contacts, :through => :ties
33
34
 
34
35
  scope :mode, lambda { |st, rt|
35
36
  where(:sender_type => st, :receiver_type => rt)
@@ -57,7 +58,7 @@ class Relation < ActiveRecord::Base
57
58
  when Array
58
59
  r.map{ |e| Relation.normalize(e, options) }
59
60
  else
60
- raise "Unable to normalize relation #{ r.inspect }"
61
+ raise "Unable to normalize relation #{ r.class }: #{ r.inspect }"
61
62
  end
62
63
  end
63
64
 
@@ -76,59 +77,34 @@ class Relation < ActiveRecord::Base
76
77
  #
77
78
  # Options:
78
79
  # in:: Limit possible relations to a set
79
- # owner:: The owner of the relations
80
80
  # public_relations:: include also {Relation::Public} whose activities can always be read
81
81
  def allow(subject, action, object, options = {})
82
- # The case when the owner == subject is special,
83
- # all the permissions are granted to the owner of the relations
84
- if options[:owner].present? && Actor.normalize(options[:owner]) == Actor.normalize(subject)
85
- rels = subject.relations
82
+ q =
83
+ select("DISTINCT relations.*").
84
+ joins(:contacts).
85
+ joins(:permissions)
86
86
 
87
- if options[:in].present?
88
- rels = rels & options[:in]
89
- end
90
-
91
- rels
92
- end
93
-
94
- # Relation conditions
95
- # Some relations can have permissions that grant permissions to other relations
96
- # through Relation#function
97
- conds = Permission.relation_conditions
98
-
99
- # Permission conditions
100
- # Set the permission conditions
101
- conds = "( #{ conds } ) AND #{ sanitize_sql('permissions_as.action' => action) } AND #{ sanitize_sql('permissions_as.object' => object) }"
87
+ conds =
88
+ Permission.arel_table[:action].eq(action).and(Permission.arel_table[:object].eq(object))
102
89
 
103
90
  # Relation::Public permissions cannot be customized yet
104
91
  if action == 'read' && object == 'activity' && (options[:public].nil? || options[:public])
105
- conds =
106
- "( #{ conds } ) OR #{ sanitize_sql('relations.type' => 'Relation::Public') }"
107
- end
108
-
109
- # subject conditions
110
- #
111
- # Relation permissions are granted to the contact receiver.
112
- # However, relation owners have all the permissions
113
- conds = "( ( #{ conds } ) AND #{ sanitize_sql('contacts_as.receiver_id' => Actor.normalize_id(subject)) } ) OR #{ sanitize_sql('relations.actor_id' => Actor.normalize_id(subject)) }"
114
-
115
- # Add owner condition
116
- if options[:owner].present?
117
- conds = "( #{ conds } ) AND #{ sanitize_sql('relations.actor_id' => Actor.normalize_id(options[:owner])) }"
92
+ conds = conds.or(Relation.arel_table[:type].eq('Relation::Public'))
118
93
  end
119
94
 
120
95
  # Add in condition
121
96
  if options[:in].present?
122
- conds = "( #{ conds } ) AND #{ sanitize_sql('relations.id' => Relation.normalize_id(Array(options[:in]))) }"
97
+ conds = conds.and(Relation.arel_table[:id].in(Relation.normalize_id(Array(options[:in]))))
123
98
  end
124
99
 
125
- select("DISTINCT relations.*").
126
- from("relations, contacts AS contacts_as INNER JOIN ties AS ties_as ON contacts_as.id = ties_as.contact_id INNER JOIN relations AS relations_as ON relations_as.id = ties_as.relation_id INNER JOIN relation_permissions AS relation_permissions_as ON relations_as.id = relation_permissions_as.relation_id INNER JOIN permissions AS permissions_as ON permissions_as.id = relation_permissions_as.permission_id").
127
- where(conds)
100
+ # subject conditions
101
+ conds = conds.and(Contact.arel_table[:receiver_id].eq(Actor.normalize_id(subject)))
102
+
103
+ q.where(conds)
128
104
  end
129
105
 
130
106
  def allow?(*args)
131
- allow(*args).any?
107
+ allow(*args).to_a.any?
132
108
  end
133
109
  end
134
110