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 = nil) ⇒ Boolean
Does this Actor allow subject to perform action on object?.
- #as_json(options) ⇒ Object
-
#as_object_type ⇒ Object
FIXME SocialStream::ActivityStreams::Supertype should take precedence over SocialStream::ActivityStreams::Subtype.
-
#can_comment?(activity) ⇒ Boolean
Is this Actor allowed to create a comment on activity?.
-
#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.
-
#mailboxer_email(object) ⇒ Object
Returning the email address of the model if an email should be sent for this object (Message or Notification).
- #notification_settings ⇒ Object
-
#options_for_contact_select ⇒ Object
Return an object of choices suitable for the contact add button or modal.
-
#options_for_contact_select_simple? ⇒ Boolean
Options for contact select are simple.
-
#options_for_contact_select_type ⇒ Object
Returns the type for contact select, :simple or :multiple.
-
#pending_contacts ⇒ Object
Build a new Contact from each that has not inverse.
- #pending_contacts? ⇒ Boolean
- #pending_contacts_count ⇒ Object
-
#positive_sent_contact_actors ⇒ Object
The actors this one has established positive ties with.
-
#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.
-
#relations_for_select ⇒ Object
The relations offered in the “Add contact” button when subjects add new contacts.
-
#relations_list ⇒ Object
The relations that will appear in privacy forms.
-
#represented_by?(subject) ⇒ Boolean
Can this actor be represented by subject.
- #self_contact ⇒ Object (also: #ego_contact)
- #sent_active_contact_count ⇒ Object
- #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.
Instance Method Details
#action_to(activity_object) ⇒ Object
Return the ActivityAction model to an ActivityObject
391 392 393 |
# File 'app/models/actor.rb', line 391 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
396 397 398 399 |
# File 'app/models/actor.rb', line 396 def action_to!(activity_object) action_to(activity_object) || sent_actions.create!(:activity_object => ActivityObject.normalize(activity_object)) end |
#activity_relation_ids ⇒ Object
479 480 481 |
# File 'app/models/actor.rb', line 479 def activity_relation_ids activity_relations.map(&:id) end |
#activity_relations ⇒ Object
The default Relations for sharing an Activity owned by this Actor
Activities are shared with all the contacts by default.
You can change this behaviour with a decorator, overwriting this method. For example, if you want the activities shared publicly by default, create a decorator in app/decorators/actor_decorator.rb with
Actor.class_eval do
def activity_relations
[ Relation::Public.instance ]
end
end
472 473 474 475 |
# File 'app/models/actor.rb', line 472 def activity_relations relations. allowing('read', 'activity') end |
#activity_relations_for(subject, options = {}) ⇒ Object
487 488 489 490 491 492 493 |
# File 'app/models/actor.rb', line 487 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?
496 497 498 |
# File 'app/models/actor.rb', line 496 def activity_relations_for?(subject, = {}) activity_relations(subject, ).any? end |
#allow?(subject, action, object = nil) ⇒ Boolean
Does this Actor allow subject to perform action on object?
386 387 388 |
# File 'app/models/actor.rb', line 386 def allow?(subject, action, object = nil) ties_to(subject).(action, object).any? end |
#as_json(options) ⇒ Object
541 542 543 544 545 546 547 548 549 550 551 |
# File 'app/models/actor.rb', line 541 def as_json() { id: id, slug: slug, name: name, url: [:helper].polymorphic_url(subject), image: { url: [:helper].root_url + logo.url(:small) } } end |
#as_object_type ⇒ Object
FIXME SocialStream::ActivityStreams::Supertype should take precedence over SocialStream::ActivityStreams::Subtype
166 167 168 |
# File 'app/models/actor.rb', line 166 def as_object_type subtype_instance.as_object_type 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
503 504 505 506 507 |
# File 'app/models/actor.rb', line 503 def can_comment?(activity) return true comment_relations(activity).any? end |
#comment_relations(activity) ⇒ Object
Are there any relations that allow this actor to create a comment on activity?
510 511 512 513 |
# File 'app/models/actor.rb', line 510 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
532 533 534 |
# File 'app/models/actor.rb', line 532 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
272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 |
# File 'app/models/actor.rb', line 272 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.positive) end as end |
#contact_subjects(options = {}) ⇒ Object
331 332 333 334 335 336 337 338 339 |
# File 'app/models/actor.rb', line 331 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.
347 348 349 |
# File 'app/models/actor.rb', line 347 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
352 353 354 355 |
# File 'app/models/actor.rb', line 352 def contact_to!(subject) contact_to(subject) || sent_contacts.create!(receiver_id: Actor.normalize_id(subject)) end |
#egocentric_ties ⇒ Object
The ties sent by this actor, plus the second grade ties
440 441 442 443 |
# File 'app/models/actor.rb', line 440 def egocentric_ties @egocentric_ties ||= load_egocentric_ties end |
#following_actor_and_self_ids ⇒ Object
381 382 383 |
# File 'app/models/actor.rb', line 381 def following_actor_and_self_ids following_actor_ids + [ id ] end |
#following_actor_ids ⇒ Object
372 373 374 375 376 377 |
# File 'app/models/actor.rb', line 372 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
366 367 368 369 |
# File 'app/models/actor.rb', line 366 def following_actor_objects followings. where('activity_objects.object_type' => "Actor") 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.
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 |
# File 'app/models/actor.rb', line 175 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 |
#notification_settings ⇒ Object
553 554 555 556 |
# File 'app/models/actor.rb', line 553 def notification_settings self.update_attribute(:notification_settings, SocialStream.default_notification_settings) unless super super end |
#options_for_contact_select ⇒ Object
Return an object of choices suitable for the contact add button or modal
238 239 240 |
# File 'app/models/actor.rb', line 238 def relations_for_select.map{ |r| [ r.name, r.id ] } end |
#options_for_contact_select_simple? ⇒ Boolean
Options for contact select are simple
243 244 245 |
# File 'app/models/actor.rb', line 243 def relations_list.count == 1 end |
#options_for_contact_select_type ⇒ Object
Returns the type for contact select, :simple or :multiple
248 249 250 |
# File 'app/models/actor.rb', line 248 def ? :simple : :multiple end |
#pending_contacts ⇒ Object
Build a new Contact from each that has not inverse
524 525 526 527 528 529 |
# File 'app/models/actor.rb', line 524 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
519 520 521 |
# File 'app/models/actor.rb', line 519 def pending_contacts? pending_contacts_count > 0 end |
#pending_contacts_count ⇒ Object
515 516 517 |
# File 'app/models/actor.rb', line 515 def pending_contacts_count received_contacts.not_reflexive.pending.count end |
#positive_sent_contact_actors ⇒ Object
The actors this one has established positive ties with
342 343 344 |
# File 'app/models/actor.rb', line 342 def positive_sent_contact_actors sent_contacts.joins(ties: :relation).merge(Relation.positive) end |
#relation_custom(name) ⇒ Object
A given relation defined and managed by this actor
214 215 216 |
# File 'app/models/actor.rb', line 214 def relation_custom(name) relation_customs.find_by_name(name) end |
#relation_customs ⇒ Object
209 210 211 |
# File 'app/models/actor.rb', line 209 def relation_customs relations.where(:type => 'Relation::Custom') end |
#relation_notifys ⇒ Object
All relations with the ‘notify’ permission
219 220 221 |
# File 'app/models/actor.rb', line 219 def relation_notifys relations.joins(:relation_permissions => :permission).where('permissions.action' => 'notify') end |
#relations_for_select ⇒ Object
The relations offered in the “Add contact” button when subjects add new contacts
233 234 235 |
# File 'app/models/actor.rb', line 233 def relations_for_select relations_list end |
#relations_list ⇒ Object
The relations that will appear in privacy forms
They usually include Relation::Custom but may also include other system-defined relations that are not editable but appear in add contact buttons
227 228 229 |
# File 'app/models/actor.rb', line 227 def relations_list Relation.system_list(subject) + relation_customs end |
#represented_by?(subject) ⇒ Boolean
Can this actor be represented by subject. Does she has permissions for it?
447 448 449 450 451 452 453 454 455 456 |
# File 'app/models/actor.rb', line 447 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
358 359 360 |
# File 'app/models/actor.rb', line 358 def self_contact contact_to!(self) end |
#sent_active_contact_count ⇒ Object
401 402 403 |
# File 'app/models/actor.rb', line 401 def sent_active_contact_count sent_contacts.active.count end |
#sent_active_contact_ids ⇒ Object
405 406 407 408 |
# File 'app/models/actor.rb', line 405 def sent_active_contact_ids @sent_active_contact_ids ||= load_sent_active_contact_ids end |
#subject ⇒ Object
The subject instance for this actor
204 205 206 |
# File 'app/models/actor.rb', line 204 def subject subtype_instance end |
#suggestions(size = 1) ⇒ Contact
416 417 418 419 420 421 422 423 424 425 426 427 |
# File 'app/models/actor.rb', line 416 def suggestions(size = 1) candidates = Actor. where(subject_type: SocialStream.suggested_models.map{ |m| m.to_s.classify }). 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
430 431 432 |
# File 'app/models/actor.rb', line 430 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
435 436 437 |
# File 'app/models/actor.rb', line 435 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 |