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
333 334 335 |
# File 'app/models/actor.rb', line 333 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
338 339 340 341 |
# File 'app/models/actor.rb', line 338 def action_to!(activity_object) action_to(activity_object) || sent_actions.create!(:activity_object => ActivityObject.normalize(activity_object)) end |
#activity_relation_ids ⇒ Object
401 402 403 |
# File 'app/models/actor.rb', line 401 def activity_relation_ids activity_relations.map(&:id) end |
#activity_relations ⇒ Object
392 393 394 395 396 397 |
# File 'app/models/actor.rb', line 392 def activity_relations SocialStream.relation_model == :custom ? relations. allowing('read', 'activity') : [ Relation::Public.instance ] end |
#activity_relations_for(subject, options = {}) ⇒ Object
409 410 411 412 413 414 415 |
# File 'app/models/actor.rb', line 409 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?
418 419 420 |
# File 'app/models/actor.rb', line 418 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?
328 329 330 |
# File 'app/models/actor.rb', line 328 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
142 143 144 |
# File 'app/models/actor.rb', line 142 def as_object_type subtype_instance.as_object_type end |
#avatar! ⇒ Object
502 503 504 |
# File 'app/models/actor.rb', line 502 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
425 426 427 428 429 |
# File 'app/models/actor.rb', line 425 def can_comment?(activity) return true comment_relations(activity).any? end |
#cheesecake_json ⇒ Object
JSON compatible with SocialCheesecake
540 541 542 543 544 545 546 547 |
# File 'app/models/actor.rb', line 540 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?
432 433 434 435 |
# File 'app/models/actor.rb', line 432 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
454 455 456 |
# File 'app/models/actor.rb', line 454 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
219 220 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 |
# File 'app/models/actor.rb', line 219 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
278 279 280 281 282 283 284 285 286 |
# File 'app/models/actor.rb', line 278 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.
289 290 291 |
# File 'app/models/actor.rb', line 289 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
294 295 296 297 |
# File 'app/models/actor.rb', line 294 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
372 373 374 375 |
# File 'app/models/actor.rb', line 372 def egocentric_ties @egocentric_ties ||= load_egocentric_ties end |
#following_actor_and_self_ids ⇒ Object
323 324 325 |
# File 'app/models/actor.rb', line 323 def following_actor_and_self_ids following_actor_ids + [ id ] end |
#following_actor_ids ⇒ Object
314 315 316 317 318 319 |
# File 'app/models/actor.rb', line 314 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
308 309 310 311 |
# File 'app/models/actor.rb', line 308 def following_actor_objects followings. where('activity_objects.object_type' => "Actor") end |
#liked_by(subject) ⇒ Object
:nodoc:
512 513 514 |
# File 'app/models/actor.rb', line 512 def liked_by(subject) #:nodoc: likes.(subject) end |
#liked_by?(subject) ⇒ Boolean
Does subject like this Actor?
517 518 519 |
# File 'app/models/actor.rb', line 517 def liked_by?(subject) liked_by(subject).present? end |
#likes ⇒ Object
The ‘like’ qualifications emmited to this actor
507 508 509 510 |
# File 'app/models/actor.rb', line 507 def likes Activity.joins(:activity_verb).where('activity_verbs.name' => "like"). joins(:activity_objects).where('activity_objects.id' => activity_object_id) end |
#logo ⇒ Object
498 499 500 |
# File 'app/models/actor.rb', line 498 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.
151 152 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 |
# File 'app/models/actor.rb', line 151 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
522 523 524 525 526 527 528 529 530 531 532 |
# File 'app/models/actor.rb', line 522 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
446 447 448 449 450 451 |
# File 'app/models/actor.rb', line 446 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
441 442 443 |
# File 'app/models/actor.rb', line 441 def pending_contacts? pending_contacts_count > 0 end |
#pending_contacts_count ⇒ Object
437 438 439 |
# File 'app/models/actor.rb', line 437 def pending_contacts_count received_contacts.not_reflexive.pending.count end |
#relation_custom(name) ⇒ Object
A given relation defined and managed by this actor
190 191 192 |
# File 'app/models/actor.rb', line 190 def relation_custom(name) relation_customs.find_by_name(name) end |
#relation_customs ⇒ Object
185 186 187 |
# File 'app/models/actor.rb', line 185 def relation_customs relations.where(:type => 'Relation::Custom') end |
#relation_notifys ⇒ Object
All relations with the ‘notify’ permission
195 196 197 |
# File 'app/models/actor.rb', line 195 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?
379 380 381 382 383 384 385 386 387 388 |
# File 'app/models/actor.rb', line 379 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
300 301 302 |
# File 'app/models/actor.rb', line 300 def self_contact contact_to!(self) end |
#sent_active_contact_ids ⇒ Object
343 344 345 346 |
# File 'app/models/actor.rb', line 343 def sent_active_contact_ids @sent_active_contact_ids ||= load_sent_active_contact_ids end |
#subject ⇒ Object
The subject instance for this actor
180 181 182 |
# File 'app/models/actor.rb', line 180 def subject subtype_instance end |
#suggestions(size = 1) ⇒ Contact
351 352 353 354 355 356 357 358 359 |
# File 'app/models/actor.rb', line 351 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
362 363 364 |
# File 'app/models/actor.rb', line 362 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
367 368 369 |
# File 'app/models/actor.rb', line 367 def ties_to?(subject) ties_to(subject).present? end |
#to_param ⇒ Object
Use slug as parameter
535 536 537 |
# File 'app/models/actor.rb', line 535 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.
471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 |
# File 'app/models/actor.rb', line 471 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 |