Class: Relation

Inherits:
ActiveRecord::Base
  • Object
show all
Defined in:
app/models/relation.rb

Overview

A relation defines a type of Tie between two Actors. From social literature, Relations can be affective (friendship, liking, respect), formal or biological (authority, kinship), transfer of material resources (transactions, lending and borrowing), messages or conversations, physical connection and affiliation to same organizations.

Relation types defined in Social Stream

All the above cases could be supported in Social Stream. Nevertheless, the following Relations are defined. All of them inherit from the Relation class:

Custom

user-defined Relation. Every Subject is able to define their own Custom relation, giving them a custom name (for instance: friend, colleague, partner, buddy) and Permissions.

Public

default Relation for ocassional Ties.

Reject

the Subject does not want to add the other as a contact. A new Tie is created using this Relation

You can define new Relations in your application. Just create a new class and inherit from Relation. This class already supports Single Table Inheritance (STI).

Relations and link building

When a Subject creates a new link to other Subject, she must specify one or serveral Relations for that link. (friend, colleague, Public or Reject. A new Tie will be created for each Relation

Permissions

Subjects assign permissions to Relations. This way, when establishing ties, they are granting permissions to their contacts.

See the documentation of Permission for more details on permission definition.

Activities and Relations

Each Activity can be attached to one or more relations. It sets the Audience that has access to it, and the Permissions that rule that access.

Direct Known Subclasses

Custom, Single

Defined Under Namespace

Classes: Custom, CustomsController, Follow, Owner, Public, Reject, Single

Constant Summary collapse

Positive =
%w{ custom public follow owner }
Negative =
%w{ reject }

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.allow(subject, action, object, options = {}) ⇒ Object

All the relations that allow subject to perform action

Options:

in:: Limit possible relations to a set
public_relations:: include also {Relation::Public} whose activities can always be read


121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# File 'app/models/relation.rb', line 121

def allow(subject, action, object, options = {})
  q = 
    select("DISTINCT relations.*").
    joins(:contacts).
    joins(:permissions)

  conds =
    Permission.arel_table[:action].eq(action).and(Permission.arel_table[:object].eq(object))
  # Relation::Public permissions cannot be customized and should not depend on the subject
  if action == 'read' && object == 'activity' && (options[:public].nil? || options[:public])
    conds = conds.or(Relation.arel_table[:type].eq('Relation::Public'))
  end


  # Add in condition
  if ! options[:in].nil?
    conds = conds.and(Relation.arel_table[:id].in(Relation.normalize_id(Array(options[:in]))))
  end

  # subject conditions
  conds = conds.and(Contact.arel_table[:receiver_id].eq(Actor.normalize_id(subject)))

  q.where(conds)
end

.allow?(*args) ⇒ Boolean

Returns:

  • (Boolean)


146
147
148
# File 'app/models/relation.rb', line 146

def allow?(*args)
  allow(*args).to_a.any?
end

.create_activity?Boolean

Returns:

  • (Boolean)


165
166
167
# File 'app/models/relation.rb', line 165

def create_activity?
  true
end

.ids_shared_with(subject) ⇒ Object

All the Relation ids in Ties this subject has received plus the one from Public



152
153
154
155
156
157
158
159
160
161
162
163
# File 'app/models/relation.rb', line 152

def ids_shared_with(subject)
  ids = [Relation::Public.instance.id]

  if subject.present?
    # Subject own defined custom relations
    ids += subject.relation_ids
    # From Ties sent by other subject
    ids += subject.received_relation_ids
  end

  ids
end

.negative_namesObject

Negative relations: [ ‘Relation::Reject’ ]



112
113
114
# File 'app/models/relation.rb', line 112

def negative_names
  Negative.map{ |r| "Relation::#{ r.classify }" }
end

.normalize(r, options = {}) ⇒ Object

Get relation from object, if possible

Options
sender

The sender of the tie



76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'app/models/relation.rb', line 76

def normalize(r, options = {})
  case r
  when Relation
    r
  when String
    if options[:sender]
      options[:sender].relation_custom(r)
    else
      raise "Must provide a sender when looking up relations from name: #{ options[:sender] }"
    end
  when Integer
    Relation.find r
  when Array
    r.map{ |e| Relation.normalize(e, options) }
  else
    raise "Unable to normalize relation #{ r.class }: #{ r.inspect }"
  end
end

.normalize_id(r, options = {}) ⇒ Object



95
96
97
98
99
100
101
102
103
104
# File 'app/models/relation.rb', line 95

def normalize_id(r, options = {})
  case r
  when Integer
    r
  when Array
    r.map{ |e| Relation.normalize_id(e, options) }
  else
    normalize(r, options).id
  end
end

.positive_namesObject

Positive relation names: [ ‘Relation::Custom’, ‘Relation::Public’ ]



107
108
109
# File 'app/models/relation.rb', line 107

def positive_names
  Positive.map{ |r| "Relation::#{ r.classify }" }
end

.system_list(subject) ⇒ Object

Default extra relations that are displayed in Actor‘s relation list, typically in /relation/customs



171
172
173
174
175
176
177
178
179
# File 'app/models/relation.rb', line 171

def system_list subject
  name = subject.class.to_s.underscore
  list = SocialStream.system_relations[name] ||
    SocialStream.system_relations[name.to_sym]
  
  return [] if list.blank?

  list.map{ |r| "Relation::#{ r.to_s.classify }".constantize.instance }
end

Instance Method Details

#<=>(rel) ⇒ Object

Compare two relations



188
189
190
191
192
# File 'app/models/relation.rb', line 188

def <=> rel
  return -1 if rel.is_a?(Public)

  permissions.count <=> rel.permissions.count
end

#available_permissionsObject

The permissions that can be assigned to this relation.

They are principally used in the privacy form in /relation/customs form



207
208
209
# File 'app/models/relation.rb', line 207

def available_permissions
  []
end

#follow?Boolean

Does this relation include the follow permission?

Returns:

  • (Boolean)


200
201
202
# File 'app/models/relation.rb', line 200

def follow?
  permissions.follow.any?
end

#modeObject

Relation class scoped in the same mode that this relation



183
184
185
# File 'app/models/relation.rb', line 183

def mode
  Relation.mode(sender_type, receiver_type)
end

#positive?Boolean

Is this Relation a Positive one?

Returns:

  • (Boolean)


195
196
197
# File 'app/models/relation.rb', line 195

def positive?
  self.class.positive_names.include?(self.class.to_s)
end