Class: Actor
- Inherits:
-
ActiveRecord::Base
- Object
- ActiveRecord::Base
- Actor
- Includes:
- SocialStream::Models::Object
- Defined in:
- app/models/actor.rb
Overview
An Actor represents a social entity. This means individuals, but also groups, departments, organizations even nations or states.
Actors are the nodes of a social network. Two actors are linked by Ties. The type of a Tie is a Relation. Each actor can define and customize their relations own Relations.
Every Actor has an Avatar, a Profile with personal or group information, contact data, etc.
Actors perform actions (like, suscribe, etc.) on activity objects (posts, commments, pictures, events..)
Actor subtypes
An actor subtype is called a Subject. SocialStream::Base provides two actor subtypes, User and Group, but the application developer can define as many actor subtypes as required. Besides including the SocialStream::Models::Subject module, Actor subtypes must added to config/initializers/social_stream.rb
Instance Method Summary collapse
-
#action_to(activity_object) ⇒ Object
Return the ActivityAction model to an ActivityObject.
-
#action_to!(activity_object) ⇒ Object
Return the ActivityAction model to an ActivityObject.
- #activity_relation_ids ⇒ Object
- #activity_relations ⇒ Object
-
#activity_relations_for(subject, options = {}) ⇒ Object
This method returns all the Relation that subject can choose to broadcast an Activity in this Actor‘s wall.
-
#activity_relations_for?(subject, options = {}) ⇒ Boolean
Are #activity_relations available for subject?.
-
#allow?(subject, action, object) ⇒ Boolean
Does this Actor allow subject to perform action on object?.
-
#as_object_type ⇒ Object
FIXME SocialStream::ActivityStreams::Supertype should take precedence over SocialStream::ActivityStreams::Subtype.
- #avatar! ⇒ Object
-
#can_comment?(activity) ⇒ Boolean
Is this Actor allowed to create a comment on activity?.
-
#cheesecake_json ⇒ Object
JSON compatible with SocialCheesecake.
-
#comment_relations(activity) ⇒ Object
Are there any relations that allow this actor to create a comment on activity?.
-
#common_contacts_count(subject) ⇒ Object
Count the contacts in common between this Actor and subject.
-
#contact_actors(options = {}) ⇒ Object
All the Actors this one has ties with:.
- #contact_subjects(options = {}) ⇒ Object
-
#contact_to(subject) ⇒ Object
Return a contact to subject.
-
#contact_to!(subject) ⇒ Object
Return a contact to subject.
-
#egocentric_ties ⇒ Object
The ties sent by this actor, plus the second grade ties.
- #following_actor_and_self_ids ⇒ Object
- #following_actor_ids ⇒ Object
-
#following_actor_objects ⇒ Object
The ActivityObjects followed by this Actor that are Actors.
-
#liked_by(subject) ⇒ Object
:nodoc:.
-
#liked_by?(subject) ⇒ Boolean
Does subject like this Actor?.
-
#likes ⇒ Object
The ‘like’ qualifications emmited to this actor.
- #logo ⇒ Object
-
#mailboxer_email(object) ⇒ Object
Returning the email address of the model if an email should be sent for this object (Message or Notification).
-
#new_like(subject, user) ⇒ Object
Build a new activity where subject like this.
-
#pending_contacts ⇒ Object
Build a new Contact from each that has not inverse.
- #pending_contacts? ⇒ Boolean
- #pending_contacts_count ⇒ Object
-
#relation_custom(name) ⇒ Object
A given relation defined and managed by this actor.
- #relation_customs ⇒ Object
-
#relation_notifys ⇒ Object
All relations with the ‘notify’ permission.
-
#represented_by?(subject) ⇒ Boolean
Can this actor be represented by subject.
- #self_contact ⇒ Object (also: #ego_contact)
- #sent_active_contact_ids ⇒ Object
-
#subject ⇒ Object
The subject instance for this actor.
- #suggestions(size = 1) ⇒ Contact
-
#ties_to(subject) ⇒ Object
Set of ties sent by this actor received by subject.
-
#ties_to?(subject) ⇒ Boolean
Is there any Tie sent by this actor and received by subject.
-
#to_param ⇒ Object
Use slug as parameter.
-
#wall(type, options = {}) ⇒ Object
The set of activities in the wall of this Actor.
Instance Method Details
#action_to(activity_object) ⇒ Object
Return the ActivityAction model to an ActivityObject
335 336 337 |
# File 'app/models/actor.rb', line 335 def action_to(activity_object) sent_actions.received_by(activity_object).first end |
#action_to!(activity_object) ⇒ Object
Return the ActivityAction model to an ActivityObject. Create it if it does not exist
340 341 342 343 |
# File 'app/models/actor.rb', line 340 def action_to!(activity_object) action_to(activity_object) || sent_actions.create!(:activity_object => ActivityObject.normalize(activity_object)) end |
#activity_relation_ids ⇒ Object
403 404 405 |
# File 'app/models/actor.rb', line 403 def activity_relation_ids activity_relations.map(&:id) end |
#activity_relations ⇒ Object
394 395 396 397 398 399 |
# File 'app/models/actor.rb', line 394 def activity_relations SocialStream.relation_model == :custom ? relations. allowing('read', 'activity') : [ Relation::Public.instance ] end |
#activity_relations_for(subject, options = {}) ⇒ Object
411 412 413 414 415 416 417 |
# File 'app/models/actor.rb', line 411 def activity_relations_for(subject, = {}) if Actor.normalize(subject) == self return relation_customs + Array.wrap(Relation::Public.instance) else Array.new end end |
#activity_relations_for?(subject, options = {}) ⇒ Boolean
Are #activity_relations available for subject?
420 421 422 |
# File 'app/models/actor.rb', line 420 def activity_relations_for?(subject, = {}) activity_relations(subject, ).any? end |
#allow?(subject, action, object) ⇒ Boolean
Does this Actor allow subject to perform action on object?
330 331 332 |
# File 'app/models/actor.rb', line 330 def allow?(subject, action, object) ties_to(subject).(action, object).any? end |
#as_object_type ⇒ Object
FIXME SocialStream::ActivityStreams::Supertype should take precedence over SocialStream::ActivityStreams::Subtype
144 145 146 |
# File 'app/models/actor.rb', line 144 def as_object_type subtype_instance.as_object_type end |
#avatar! ⇒ Object
504 505 506 |
# File 'app/models/actor.rb', line 504 def avatar! avatar || avatars.build end |
#can_comment?(activity) ⇒ Boolean
Is this Actor allowed to create a comment on activity?
We are allowing comments from everyone signed in by now
427 428 429 430 431 |
# File 'app/models/actor.rb', line 427 def can_comment?(activity) return true comment_relations(activity).any? end |
#cheesecake_json ⇒ Object
JSON compatible with SocialCheesecake
542 543 544 545 546 547 548 549 |
# File 'app/models/actor.rb', line 542 def cheesecake_json { :sectors => relation_customs.includes(:ties => :contact).map { |r| r.to_cheesecake_hash } }.to_json end |
#comment_relations(activity) ⇒ Object
Are there any relations that allow this actor to create a comment on activity?
434 435 436 437 |
# File 'app/models/actor.rb', line 434 def comment_relations(activity) activity.relations.select{ |r| r.is_a?(Relation::Public) } | Relation.allow(self, 'create', 'activity', :in => activity.relations) end |
#common_contacts_count(subject) ⇒ Object
Count the contacts in common between this Actor and subject
456 457 458 |
# File 'app/models/actor.rb', line 456 def common_contacts_count(subject) (sent_active_contact_ids & subject.sent_active_contact_ids).size end |
#contact_actors(options = {}) ⇒ Object
All the Actors this one has ties with:
actor.contact_actors #=> array of actors that sent and receive ties from actor
There are several options available to refine the query:
- type
-
Filter by the class of the contacts (User, Group, etc.)
actor.contact_actors(:type => :user) #=> array of user actors. Exclude groups, etc.
- direction
-
:sent
leaves only the actors this one has ties to.:received
gets the actors sending ties to this actor, whether this actor added them or notactor.contact_actors(:direction => :sent) #=> all the receivers of ties from actor
- relations
-
Restrict to ties made up with
relations
. In the case of both directions, only relations belonging to Actor are considered. It defaults to actor’s custom relationsactor.contact_actors(:relations => [2]) #=> actors tied with relation #2
- include_self
-
False by default, do not include this actor even they have ties with themselves.
- load_subjects
-
True by default, make the queries for eager loading of Subject
221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 |
# File 'app/models/actor.rb', line 221 def contact_actors( = {}) subject_types = Array([:type] || self.class.subtypes) subject_classes = subject_types.map{ |s| s.to_s.classify } as = Actor.select('actors.*'). # PostgreSQL requires that all the columns must be included in the GROUP BY group((Actor.columns.map(&:name).map{ |c| "actors.#{ c }" } + [ "contacts.created_at" ]).join(", ")). where('actors.subject_type' => subject_classes) if [:load_subjects].nil? || [:load_subjects] as = as.includes(subject_types) end # A blank :direction means reciprocate contacts, there must be ties in both directions # # This is achieved by getting the id of all the contacts that are sending ties # Then, we filter the sent contacts query to only those contacts if [:direction].blank? rcv_opts = .dup rcv_opts[:direction] = :received rcv_opts[:load_subjects] = false # Get the id of actors that are sending to this one sender_ids = contact_actors(rcv_opts).map(&:id) # Filter the sent query with these ids as = as.where(:id => sender_ids) [:direction] = :sent end case [:direction] when :sent as = as.joins(:received_ties => :relation).merge(Contact.sent_by(self)) when :received as = as.joins(:sent_ties => :relation).merge(Contact.received_by(self)) else raise "How do you get here?!" end if [:include_self].blank? as = as.where("actors.id != ?", self.id) end if [:relations].present? as = as.merge(Tie.([:relations])) else as = as.merge(Relation.where(:type => ['Relation::Custom', 'Relation::Public'])) end as end |
#contact_subjects(options = {}) ⇒ Object
280 281 282 283 284 285 286 287 288 |
# File 'app/models/actor.rb', line 280 def contact_subjects( = {}) as = contact_actors() if block_given? as = yield(as) end as.map(&:subject) end |
#contact_to(subject) ⇒ Object
Return a contact to subject.
291 292 293 |
# File 'app/models/actor.rb', line 291 def contact_to(subject) sent_contacts.received_by(subject).first end |
#contact_to!(subject) ⇒ Object
Return a contact to subject. Create it if it does not exist
296 297 298 299 |
# File 'app/models/actor.rb', line 296 def contact_to!(subject) contact_to(subject) || sent_contacts.create!(:receiver => Actor.normalize(subject)) end |
#egocentric_ties ⇒ Object
The ties sent by this actor, plus the second grade ties
374 375 376 377 |
# File 'app/models/actor.rb', line 374 def egocentric_ties @egocentric_ties ||= load_egocentric_ties end |
#following_actor_and_self_ids ⇒ Object
325 326 327 |
# File 'app/models/actor.rb', line 325 def following_actor_and_self_ids following_actor_ids + [ id ] end |
#following_actor_ids ⇒ Object
316 317 318 319 320 321 |
# File 'app/models/actor.rb', line 316 def following_actor_ids following_actor_objects. includes(:actor). map(&:actor). map(&:id) end |
#following_actor_objects ⇒ Object
The ActivityObjects followed by this Actor that are Actors
310 311 312 313 |
# File 'app/models/actor.rb', line 310 def following_actor_objects followings. where('activity_objects.object_type' => "Actor") end |
#liked_by(subject) ⇒ Object
:nodoc:
514 515 516 |
# File 'app/models/actor.rb', line 514 def liked_by(subject) #:nodoc: likes.(subject) end |
#liked_by?(subject) ⇒ Boolean
Does subject like this Actor?
519 520 521 |
# File 'app/models/actor.rb', line 519 def liked_by?(subject) liked_by(subject).present? end |
#likes ⇒ Object
The ‘like’ qualifications emmited to this actor
509 510 511 512 |
# File 'app/models/actor.rb', line 509 def likes Activity.joins(:activity_verb).where('activity_verbs.name' => "like"). joins(:activity_objects).where('activity_objects.id' => activity_object_id) end |
#logo ⇒ Object
500 501 502 |
# File 'app/models/actor.rb', line 500 def logo avatar!.logo end |
#mailboxer_email(object) ⇒ Object
Returning the email address of the model if an email should be sent for this object (Message or Notification). If the actor is a Group and has no email address, an array with the email of the highest rank members will be returned isntead.
If no mail has to be sent, return nil.
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# File 'app/models/actor.rb', line 153 def mailboxer_email(object) #If actor has disabled the emails, return nil. return nil if !notify_by_email #If actor has enabled the emails and has email return "#{name} <#{email}>" if email.present? #If actor is a Group, has enabled emails but no mail we return the highest_rank ones. if (group = self.subject).is_a? Group emails = Array.new group.relation_notifys.each do |relation| receivers = group.contact_actors(:direction => :sent, :relations => relation) receivers.each do |receiver| next unless Actor.normalize(receiver).subject_type.eql?("User") receiver_emails = receiver.mailboxer_email(object) case receiver_emails when String emails << receiver_emails when Array receiver_emails.each do |receiver_email| emails << receiver_email end end end end return emails end end |
#new_like(subject, user) ⇒ Object
Build a new activity where subject like this
524 525 526 527 528 529 530 531 532 533 534 |
# File 'app/models/actor.rb', line 524 def new_like(subject, user) a = Activity.new :verb => "like", :author_id => Actor.normalize_id(subject), :user_author_id => Actor.normalize_id(user), :owner_id => id, :relation_ids => Array(Relation::Public.instance.id) a.activity_objects << activity_object a end |
#pending_contacts ⇒ Object
Build a new Contact from each that has not inverse
448 449 450 451 452 453 |
# File 'app/models/actor.rb', line 448 def pending_contacts received_contacts.pending.includes(:inverse).all.map do |c| c.inverse || c.receiver.contact_to!(c.sender) end end |
#pending_contacts? ⇒ Boolean
443 444 445 |
# File 'app/models/actor.rb', line 443 def pending_contacts? pending_contacts_count > 0 end |
#pending_contacts_count ⇒ Object
439 440 441 |
# File 'app/models/actor.rb', line 439 def pending_contacts_count received_contacts.not_reflexive.pending.count end |
#relation_custom(name) ⇒ Object
A given relation defined and managed by this actor
192 193 194 |
# File 'app/models/actor.rb', line 192 def relation_custom(name) relation_customs.find_by_name(name) end |
#relation_customs ⇒ Object
187 188 189 |
# File 'app/models/actor.rb', line 187 def relation_customs relations.where(:type => 'Relation::Custom') end |
#relation_notifys ⇒ Object
All relations with the ‘notify’ permission
197 198 199 |
# File 'app/models/actor.rb', line 197 def relation_notifys relations.joins(:relation_permissions => :permission).where('permissions.action' => 'notify') end |
#represented_by?(subject) ⇒ Boolean
Can this actor be represented by subject. Does she has permissions for it?
381 382 383 384 385 386 387 388 389 390 |
# File 'app/models/actor.rb', line 381 def represented_by?(subject) return false if subject.blank? self.class.normalize(subject) == self || sent_ties. merge(Contact.received_by(subject)). joins(:relation => :permissions). merge(Permission.represent). any? end |
#self_contact ⇒ Object Also known as: ego_contact
302 303 304 |
# File 'app/models/actor.rb', line 302 def self_contact contact_to!(self) end |
#sent_active_contact_ids ⇒ Object
345 346 347 348 |
# File 'app/models/actor.rb', line 345 def sent_active_contact_ids @sent_active_contact_ids ||= load_sent_active_contact_ids end |
#subject ⇒ Object
The subject instance for this actor
182 183 184 |
# File 'app/models/actor.rb', line 182 def subject subtype_instance end |
#suggestions(size = 1) ⇒ Contact
353 354 355 356 357 358 359 360 361 |
# File 'app/models/actor.rb', line 353 def suggestions(size = 1) candidates = Actor.where(Actor.arel_table[:id].not_in(sent_active_contact_ids + [id])) size.times.map { candidates.delete_at rand(candidates.size) }.compact.map { |a| contact_to! a } end |
#ties_to(subject) ⇒ Object
Set of ties sent by this actor received by subject
364 365 366 |
# File 'app/models/actor.rb', line 364 def ties_to(subject) sent_ties.merge(Contact.received_by(subject)) end |
#ties_to?(subject) ⇒ Boolean
Is there any Tie sent by this actor and received by subject
369 370 371 |
# File 'app/models/actor.rb', line 369 def ties_to?(subject) ties_to(subject).present? end |
#to_param ⇒ Object
Use slug as parameter
537 538 539 |
# File 'app/models/actor.rb', line 537 def to_param slug end |
#wall(type, options = {}) ⇒ Object
The set of activities in the wall of this Actor.
There are two types of walls:
- home
-
includes all the activities from this Actor and their followed actors
See {Permission permissions} for more information on the following support
- profile
-
The set of activities in the wall profile of this Actor, it includes only the activities from the ties of this actor that can be read by the subject
Options:
- :for
-
the subject that is accessing the wall
- :relation
-
show only activities that are attached at this relation level. For example, the wall for members of the group.
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 |
# File 'app/models/actor.rb', line 473 def wall(type, = {}) [:for] = self if type == :home wall = Activity. select("DISTINCT activities.*"). roots. includes(:author, :user_author, :owner, :activity_objects, :activity_verb, :relations) actor_ids = case type when :home following_actor_and_self_ids when :profile id else raise "Unknown type of wall: #{ type }" end wall = wall.(actor_ids) # Authentication wall = wall.shared_with([:for]) wall = wall.order("created_at desc") end |