social_stream-base 0.7.11 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore CHANGED
@@ -11,3 +11,4 @@ nbproject
11
11
  lib/generators/social_stream/base/templates/public/images/tmp/
12
12
  **.*swp
13
13
  .code_swarm
14
+ .rvmrc
@@ -0,0 +1,67 @@
1
+ //= require d3
2
+ //= require d3.layout
3
+ //= require d3.geom
4
+
5
+ (function( $ ){
6
+ $.fn.tiesGraph = function( data ) {
7
+ //TODO: better handling of width and height
8
+ var w = 860,
9
+ h = 500,
10
+ fill = d3.scale.category20();
11
+
12
+ var vis = d3.select(this.selector)
13
+ .append("svg:svg")
14
+ .attr("width", w)
15
+ .attr("height", h);
16
+
17
+ var force = d3.layout.force()
18
+ .charge(-120)
19
+ .linkDistance(40)
20
+ .nodes(data.nodes)
21
+ .links(data.links)
22
+ .size([w, h])
23
+ .start();
24
+
25
+ var link = vis.selectAll("line.link")
26
+ .data(data.links)
27
+ .enter().append("svg:line")
28
+ .attr("class", "link")
29
+ .style("stroke-width", function(d) { return Math.sqrt(d.value); })
30
+ .attr("x1", function(d) { return d.source.x; })
31
+ .attr("y1", function(d) { return d.source.y; })
32
+ .attr("x2", function(d) { return d.target.x; })
33
+ .attr("y2", function(d) { return d.target.y; });
34
+
35
+ var node = vis.selectAll("g.node")
36
+ .data(data.nodes)
37
+ .enter().append("svg:g")
38
+ .attr("class", "node")
39
+ .call(force.drag);
40
+
41
+ node.append("svg:image")
42
+ .attr("class", "circle")
43
+ .attr("xlink:href", function(d) { return d.logo; })
44
+ .attr("x", "-10px")
45
+ .attr("y", "-10px")
46
+ .attr("width", "20px")
47
+ .attr("height", "20px");
48
+
49
+ node.append("svg:title")
50
+ .text(function(d) { return d.name; });
51
+
52
+ vis.style("opacity", 1e-6)
53
+ .transition()
54
+ .duration(1000)
55
+ .style("opacity", 1);
56
+
57
+ force.on("tick", function() {
58
+ link.attr("x1", function(d) { return d.source.x; })
59
+ .attr("y1", function(d) { return d.source.y; })
60
+ .attr("x2", function(d) { return d.target.x; })
61
+ .attr("y2", function(d) { return d.target.y; });
62
+
63
+ node.attr("transform", function(d) { return "translate(" + d.x + "," + d.y + ")"; });
64
+ });
65
+ };
66
+ })( jQuery );
67
+
@@ -23,7 +23,7 @@
23
23
  .activity { text-align:left; display: block; vertical-align: top; padding: 10px 0px 5px 0px;
24
24
  display: inline-block; color: #000; font-size: 13px; color: #2A3890;border-bottom:1px solid #E9E9E9;}
25
25
  .actor_logo { width: 38px; padding: 8px 0px 5px 5px; display: inline-block; vertical-align: top;}
26
- .activity_content { padding: 8px 0px 0px 0px; display: inline-block; color: #000; width: 90%;}
26
+ .activity_content { padding: 8px 0px 0px 0px; display: inline-block; color: #000; width: 89%;}
27
27
  .actor_name {font-size: 13px;}
28
28
  .actor_name a{font-weight: bold;}
29
29
  .post a { color: #2A3890;}
@@ -1,6 +1,6 @@
1
1
  /*************Basic SECTION ********************/
2
2
  * { margin: 0; padding: 0; font-family: Arial; }
3
- html, body {height: 100%;}
3
+ html, body {height: auto;}
4
4
  .p { margin: 0px; padding: 0px; font-size: inherit; font-family: inherit; font-weight: inherit;
5
5
  text-align: inherit; color: inherit; line-height: inherit; vertical-align: top;}
6
6
  p { padding-top: 0px; margin-top: 0px;}
@@ -15,7 +15,7 @@ h2{padding-left:10px;}
15
15
 
16
16
 
17
17
  /******* Main Structure SECTION***************************/
18
- body{font-size:1.0em; color:#2A3890; background-color:#ffffff; }
18
+ body{font-size:1.0em; color:#2A3890; background-color:#ffffff; overflow-y: scroll;}
19
19
  #wrapper { background-color: #f5f5f5; width: 100%; margin: 0px auto; }
20
20
  #wrapper_body{min-height: 552px; width: 960px; margin:0px auto; margin-left: auto; margin-right: auto;
21
21
  margin-top: auto; margin-bottom:auto;}
@@ -102,6 +102,7 @@ textarea.new_contact_text_area{ height: 100px; color: #2A3890;}
102
102
  .block .header_icon{ margin-top: 2px; width:14px; height:14px; }
103
103
  .block .header_icon_right { float: right; padding-right: 5px; padding-top: 3px;}
104
104
  .block .header_text { margin-top: 3px; display: inline-block;}
105
+ .block .header_title { margin-top: 3px; display: inline-block; font-weight: bold}
105
106
  .block .logo{ display: inline-block; vertical-align:top;}
106
107
  .block .right{padding-right:20px; float:right;}
107
108
  .block .row { display: block;}
@@ -0,0 +1,10 @@
1
+ circle.node {
2
+ stroke: #fff;
3
+ stroke-width: 1.5px;
4
+ }
5
+
6
+ line.link {
7
+ stroke: #999;
8
+ stroke-opacity: .6;
9
+ }
10
+
@@ -0,0 +1,8 @@
1
+ class TiesController < ApplicationController
2
+ respond_to :html
3
+
4
+ before_filter :authenticate_user!
5
+
6
+ def index
7
+ end
8
+ end
@@ -1,15 +1,15 @@
1
1
  module SubjectsHelper
2
-
3
- NAME_MAX_LENGHT = 30
4
-
2
+
3
+ NAME_MAX_LENGTH = 30
4
+
5
5
  # Return a link to this subject with the name
6
6
  def link_name(subject, options = {})
7
7
  link_to subject.name, subject, options
8
8
  end
9
-
9
+
10
10
  # Return the truncated name
11
11
  def truncate_name(name, options={})
12
- options = {:length => NAME_MAX_LENGHT, :separator => ' '}.merge options
12
+ options = {:length => NAME_MAX_LENGTH, :separator => ' '}.merge options
13
13
  truncate(name,options)
14
14
  end
15
15
  end
data/app/models/actor.rb CHANGED
@@ -280,6 +280,13 @@ class Actor < ActiveRecord::Base
280
280
  ties_to(subject).present?
281
281
  end
282
282
 
283
+ # The {Tie ties} sent by this actor, plus the second grade ties
284
+ def egocentric_ties
285
+ @egocentric_ties ||=
286
+ load_egocentric_ties
287
+ end
288
+
289
+
283
290
  # Can this actor be represented by subject. Does she has permissions for it?
284
291
  def represented_by?(subject)
285
292
  return false if subject.blank?
@@ -444,4 +451,18 @@ class Actor < ActiveRecord::Base
444
451
  create_profile
445
452
  end
446
453
  end
454
+
455
+ # Calculate {#egocentric_ties}
456
+ def load_egocentric_ties
457
+ ties = sent_ties.includes(:contact).to_a
458
+
459
+ contact_ids = ties.map{ |t| t.contact.receiver_id }
460
+
461
+ second_grade_ties =
462
+ contact_ids.
463
+ map{ |i| Tie.sent_by(i) }.
464
+ flatten
465
+
466
+ ties + second_grade_ties
467
+ end
447
468
  end
@@ -0,0 +1,8 @@
1
+ <% toolbar :option => :contacts %>
2
+
3
+ <div id="ties"></div>
4
+
5
+ <%= javascript_tag do %>
6
+ var tiesData = <%= raw SocialStream::D3::Force.new(current_subject.egocentric_ties, self).to_json %>;
7
+ $('#ties').tiesGraph(tiesData);
8
+ <% end %>
@@ -307,7 +307,7 @@ en:
307
307
  title: "Privacy & context"
308
308
  relation_public:
309
309
  name: "Public"
310
- required: "* These fields are required"
310
+ required: "(*) These fields are required"
311
311
  settings:
312
312
  error: "Some errors raised when saving your changes"
313
313
  for: "Settings for"
data/config/routes.rb CHANGED
@@ -65,6 +65,7 @@ Rails.application.routes.draw do
65
65
  resource :like
66
66
  end
67
67
 
68
+ match 'ties' => 'ties#index', :as => :ties
68
69
 
69
70
  # Social Stream objects configured in config/initializers/social_stream.rb
70
71
  (SocialStream.objects - [ :actor ]).each do |object|
@@ -4,11 +4,11 @@ module Mailboxer
4
4
  def decode_notification notification_text, activity
5
5
  return if activity.nil?
6
6
  notification_text = notification_text.gsub(/\%\{sender\}/, link_to(truncate_name(activity.sender.name),
7
- url_for(:controller=> activity.sender.subject.class.to_s.downcase.pluralize,
7
+ url_for(:controller=> activity.sender.subject.class.to_s.underscore.pluralize,
8
8
  :action=> :show, :id=> activity.sender.subject.slug, :only_path => false)))
9
9
  notification_text = notification_text.gsub(/\%\{confirm\}/,link_to(t('notification.confirm'),edit_contact_url(activity.receiver.contact_to!(activity.sender), :s => activity.sender.slug)))
10
10
  notification_text = notification_text.gsub(/\%\{look\}/,link_to(t('notification.look'),
11
- url_for(:controller=> activity.sender.subject.class.to_s.downcase.pluralize,
11
+ url_for(:controller=> activity.sender.subject.class.to_s.underscore.pluralize,
12
12
  :action=> :show, :id=> activity.sender.subject.slug, :only_path => false)))
13
13
  notification_text = notification_text.gsub(/\%\{sender.name\}/,truncate_name(activity.sender.name))
14
14
 
@@ -23,12 +23,12 @@ module Mailboxer
23
23
  if activity.direct_object.present?
24
24
  object = activity.direct_object
25
25
  object = object.subject if object.is_a? Actor
26
- notification_text=notification_text.gsub(/\%\{object\}/,link_to(object.class.to_s.downcase,
27
- url_for(:controller=> object.class.to_s.downcase.pluralize, :action=> :show,
26
+ notification_text=notification_text.gsub(/\%\{object\}/,link_to(object.class.to_s.underscore,
27
+ url_for(:controller=> object.class.to_s.underscore.pluralize, :action=> :show,
28
28
  :id=> object.id, :only_path => false)))
29
- notification_text=notification_text.gsub(/\%\{object.name\}/,object.class.to_s.downcase)
29
+ notification_text=notification_text.gsub(/\%\{object.name\}/,object.class.to_s.underscore)
30
30
  notification_text=notification_text.gsub(/\%\{object.text\}/,link_to(object.text.truncate(100, :separator =>' '),
31
- url_for(:controller=> object.class.to_s.downcase.pluralize, :action=> :show,
31
+ url_for(:controller=> object.class.to_s.underscore.pluralize, :action=> :show,
32
32
  :id=> object.id, :only_path => false))) if object.respond_to? :text
33
33
 
34
34
  #notification_text=notification_text.gsub(/\%\{object.image\}/,thumb_for(object)) if SocialStream.activity_forms.include? :document and object.is_a? Document
@@ -59,8 +59,8 @@ module Mailboxer
59
59
  if activity.direct_object.present?
60
60
  object = activity.direct_object
61
61
  object = object.subject if object.is_a? Actor
62
- notification_text=notification_text.gsub(/\%\{object\}/,object.class.to_s.downcase)
63
- notification_text=notification_text.gsub(/\%\{object.name\}/,object.class.to_s.downcase)
62
+ notification_text=notification_text.gsub(/\%\{object\}/,object.class.to_s.underscore)
63
+ notification_text=notification_text.gsub(/\%\{object.name\}/,object.class.to_s.underscore)
64
64
  notification_text=notification_text.gsub(/\%\{object.text\}/,object.text.truncate(100, :separator =>' ')) if object.respond_to? :text
65
65
 
66
66
  #notification_text=notification_text.gsub(/\%\{object.image\}/,thumb_for(object)) if SocialStream.activity_forms.include? :document and object.is_a? Document
@@ -1,5 +1,5 @@
1
1
  module SocialStream
2
2
  module Base
3
- VERSION = "0.7.11".freeze
3
+ VERSION = "0.8.0".freeze
4
4
  end
5
5
  end
@@ -57,9 +57,8 @@ module SocialStream
57
57
  # Requirements: the controller must inherit from +InheritedResources::Base+ and the method
58
58
  # {ClassMethods#belongs_to_subjects} must be called
59
59
  #
60
- #
61
60
  # class PostsController < InheritedResources::Base
62
- # belongs_to_subjects
61
+ # belongs_to_subjects :optional => true
63
62
  # end
64
63
  #
65
64
  # # /users/demo/posts
@@ -100,10 +99,9 @@ module SocialStream
100
99
 
101
100
  subject = Actor.find_by_slug!(params[:s]).subject
102
101
 
103
- # remove security to control allow "slug" until tapiador fix it
104
- #unless subject.represented_by?(current_user)
105
- # raise CanCan::AccessDenied.new("Not authorized!", :represent, subject.name)
106
- #end
102
+ unless subject.represented_by?(current_user)
103
+ raise CanCan::AccessDenied.new("Not authorized!", :represent, subject.name)
104
+ end
107
105
 
108
106
  self.current_subject = subject
109
107
  end
@@ -0,0 +1,53 @@
1
+ module SocialStream
2
+ # Methods for d3.js library
3
+ # http://mbostock.github.com/d3/
4
+ module D3
5
+ class Force
6
+ def initialize(ties, view)
7
+ @view = view
8
+
9
+ @force =
10
+ ties.inject({ :nodes => [], :links => [] }) { |result, t|
11
+ add_node(result[:nodes], t.sender)
12
+ add_node(result[:nodes], t.receiver)
13
+
14
+ add_link(result[:links], t, result[:nodes])
15
+
16
+ result
17
+ }
18
+ end
19
+
20
+ def to_json
21
+ @force.to_json
22
+ end
23
+
24
+ private
25
+
26
+ def node(actor)
27
+ {
28
+ :name => actor.name,
29
+ :logo => @view.image_path(actor.logo.url(:representation)),
30
+ :group => SocialStream.subjects.index(actor.subject_type.underscore.to_sym) + 1
31
+ }
32
+ end
33
+
34
+ def add_node(nodes, actor)
35
+ return if nodes_actor_index(nodes, actor)
36
+
37
+ nodes << node(actor)
38
+ end
39
+
40
+ def add_link(links, tie, nodes)
41
+ links << {
42
+ :source => nodes_actor_index(nodes, tie.sender),
43
+ :target => nodes_actor_index(nodes, tie.receiver),
44
+ :value => 1
45
+ }
46
+ end
47
+
48
+ def nodes_actor_index(nodes, actor)
49
+ nodes.index(nodes.find{ |n| n[:name] == actor.name })
50
+ end
51
+ end
52
+ end
53
+ end
@@ -43,6 +43,7 @@ module SocialStream
43
43
  :options => {:link => {:id => "contacts_menu"}},
44
44
  :items => [
45
45
  {:key => :invitations, :name => image_tag("btn/btn_friend.png")+t('contact.current'), :url => contacts_path},
46
+ {:key => :contacts_graph, :name => image_tag("btn/btn_friend.png")+t('contact.graph'), :url => ties_path},
46
47
  {:key => :invitations, :name => image_tag("btn/btn_friend.png")+t('contact.pending.other'), :url => contacts_path(:pending=>true)},
47
48
  {:key => :invitations, :name => image_tag("btn/btn_invitation.png")+t('invitation.toolbar'), :url => new_invitation_path}
48
49
  ]}
@@ -39,6 +39,7 @@ require 'modernizr-rails'
39
39
  # Provides your Rails application with social network and activity stream support
40
40
  module SocialStream
41
41
  autoload :Ability, 'social_stream/ability'
42
+ autoload :D3, 'social_stream/d3'
42
43
  autoload :Populate, 'social_stream/populate'
43
44
  autoload :Relations, 'social_stream/relations'
44
45
  autoload :TestHelpers, 'social_stream/test_helpers'
@@ -95,11 +96,16 @@ module SocialStream
95
96
  #
96
97
  # Maybe Rails provides some method to do this, in this case, please tell!!
97
98
  def require_model(m)
98
- path = $:.find{ |f| f =~ Regexp.new(File.join('social_stream.*', 'app', 'models')) }
99
+ paths = $:.find_all{ |f| f =~ Regexp.new(File.join('social_stream.*', 'app', 'models')) }
99
100
 
100
- raise "Can't find social_stream path" if path.blank?
101
+ raise "Can't find social_stream path" if paths.blank?
102
+
103
+ paths.each do |path|
104
+ if File.exists?(File.join(path, "#{m}.rb"))
105
+ require_dependency File.join(path, m)
106
+ end
107
+ end
101
108
 
102
- require_dependency File.join(path, m)
103
109
  end
104
110
  end
105
111
  end
@@ -1,26 +1,26 @@
1
1
  namespace :db do
2
2
  desc 'Populate database with fake data for development'
3
3
  task :populate => [ 'db:seed', 'db:populate:create' ]
4
-
4
+
5
5
  namespace :populate do
6
-
6
+
7
7
  desc "Reload populate data"
8
8
  task :reload => [ 'db:reset', :create ]
9
-
9
+
10
10
  desc "Create populate data"
11
11
  task :create => :environment do
12
-
12
+
13
13
  LOGOS_PATH = File.join(Rails.root, 'lib', 'logos')
14
-
14
+
15
15
  Mailboxer.setup do |config|
16
16
  config.uses_emails = false
17
17
  end
18
-
18
+
19
19
  def set_logos(klass)
20
20
  klass.all.each do |i|
21
21
  logo = Dir[File.join(LOGOS_PATH, klass.to_s.tableize, "#{ i.id }.*")].first
22
22
  avatar = Dir[File.join(LOGOS_PATH, klass.to_s.tableize, "#{ i.id }.*")].first
23
-
23
+
24
24
  if avatar.present? && File.exists?(avatar)
25
25
  Avatar.copy_to_temp_file(avatar)
26
26
  dimensions = Avatar.get_image_dimensions(avatar)
@@ -30,7 +30,7 @@ namespace :db do
30
30
  end
31
31
  end
32
32
  end
33
-
33
+
34
34
  def set_tags(klass)
35
35
  klass.all.each do |el|
36
36
  el.tag_list = Forgery::LoremIpsum.words(1,:random => true)+", "+
@@ -39,12 +39,12 @@ namespace :db do
39
39
  el.save!
40
40
  end
41
41
  end
42
-
42
+
43
43
  puts 'User population'
44
44
  users_start = Time.now
45
-
45
+
46
46
  # = Users
47
-
47
+
48
48
  # Create demo user if not present
49
49
  if User.find_by_name('demo').blank?
50
50
  User.create! :name => 'Demo',
@@ -52,100 +52,98 @@ namespace :db do
52
52
  :password => 'demonstration',
53
53
  :password_confirmation => 'demonstration'
54
54
  end
55
-
55
+
56
56
  require 'forgery'
57
-
57
+
58
58
  9.times do
59
59
  User.create! :name => Forgery::Name.full_name,
60
60
  :email => Forgery::Internet.email_address,
61
61
  :password => 'demonstration',
62
62
  :password_confirmation => 'demonstration'
63
63
  end
64
-
65
- set_logos(User)
66
-
67
- users_end = Time.now
64
+
65
+
66
+ users_end = Time.now
68
67
  puts ' -> ' + (users_end - users_start).round(4).to_s + 's'
69
-
68
+
70
69
  puts 'Groups population'
71
70
  groups_start = Time.now
72
-
71
+
73
72
  # = Groups
74
73
  available_actors = Actor.all
75
74
 
76
75
  10.times do
77
76
  founder = available_actors[rand(available_actors.size)]
78
-
77
+
79
78
  Group.create! :name => Forgery::Name.company_name,
80
79
  :email => Forgery::Internet.email_address,
81
80
  :_founder => founder.slug
82
81
  end
83
-
84
- set_logos(Group)
82
+
85
83
  set_tags(Group)
86
-
87
- groups_end = Time.now
84
+
85
+ groups_end = Time.now
88
86
  puts ' -> ' + (groups_end - groups_start).round(4).to_s + 's'
89
-
90
-
87
+
88
+
91
89
  puts 'Ties population'
92
90
  ties_start = Time.now
93
-
91
+
94
92
  # Reload actors to include groups
95
- available_actors = Actor.all
96
-
93
+ available_actors = Actor.all
94
+
97
95
  # = Ties
98
96
  available_actors.each do |a|
99
97
  actors = available_actors.dup - Array(a)
100
98
  relations = a.relations
101
-
99
+
102
100
  Forgery::Basic.number(:at_most => actors.size).times do
103
101
  actor = actors.delete_at((rand * actors.size).to_i)
104
- a.contact_to!(actor).relation_ids = Array(relations.random.id)
102
+ a.contact_to!(actor).relation_ids = Array(Forgery::Extensions::Array.new(relations).random.id)
105
103
  end
106
104
  end
107
-
105
+
108
106
  ties_end = Time.now
109
107
  puts ' -> ' + (ties_end - ties_start).round(4).to_s + 's'
110
-
108
+
111
109
  # = Posts
112
-
110
+
113
111
  puts 'Post population'
114
112
  posts_start = Time.now
115
-
113
+
116
114
  SocialStream::Populate.power_law(Tie.all) do |t|
117
115
  updated = Time.at(rand(Time.now.to_i))
118
-
116
+
119
117
  p = Post.create :text =>
120
118
  "This post should be for #{ t.relation.name } of #{ t.sender.name }.\n#{ Forgery::LoremIpsum.paragraph(:random => true) }",
121
119
  :created_at => Time.at(rand(updated.to_i)),
122
120
  :updated_at => updated,
123
121
  :_contact_id => t.contact_id,
124
122
  :_relation_ids => Array(t.relation_id)
125
-
123
+
126
124
  p.post_activity.update_attributes(:created_at => p.created_at,
127
125
  :updated_at => p.updated_at)
128
126
  end
129
-
130
- posts_end = Time.now
127
+
128
+ posts_end = Time.now
131
129
  puts ' -> ' + (posts_end - posts_start).round(4).to_s + 's'
132
-
130
+
133
131
  puts 'Mailboxer population'
134
132
  mailboxer_start = Time.now
135
-
133
+
136
134
  # = Mailboxer
137
135
  available_actors = Actor.all
138
-
136
+
139
137
  available_actors.each do |a|
140
138
  actors = available_actors.dup - Array(a)
141
-
139
+
142
140
  mult_recp = actors.uniq
143
141
  if (demo = User.find_by_name('demo')) and !mult_recp.include? Actor.normalize(demo)
144
142
  mult_recp << Actor.normalize(demo)
145
143
  end
146
144
  actor = mult_recp[(rand * mult_recp.size).to_i]
147
145
  mult_recp.delete(actor)
148
- mail = actor.send_message(mult_recp, "Hello all, I am #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}", Forgery::LoremIpsum.words(10,:random => true))
146
+ mail = actor.send_message(mult_recp, "Hello all, I am #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}", Forgery::LoremIpsum.words(10,:random => true))
149
147
  actor = mult_recp[(rand * mult_recp.size).to_i]
150
148
  mail = actor.reply_to_all(mail, "Well, I am #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}")
151
149
  actor = mult_recp[(rand * mult_recp.size).to_i]
@@ -153,11 +151,11 @@ namespace :db do
153
151
  actor = mult_recp[(rand * mult_recp.size).to_i]
154
152
  mail = actor.reply_to_all(mail, "Pretty well, I am #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}")
155
153
  actor = mult_recp[(rand * mult_recp.size).to_i]
156
- actor.reply_to_all(mail, "Finally, I am #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}")
157
-
158
-
154
+ actor.reply_to_all(mail, "Finally, I am #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}")
155
+
156
+
159
157
  if (demo = User.find_by_name('demo'))
160
- next if Actor.normalize(demo)==Actor.normalize(a)
158
+ next if Actor.normalize(demo)==Actor.normalize(a)
161
159
  mail = a.send_message(demo, "Hello, #{demo.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}", Forgery::LoremIpsum.words(10,:random => true))
162
160
  if rand > 0.5
163
161
  mail = demo.reply_to_sender(mail, "Pretty well #{a.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}")
@@ -168,11 +166,11 @@ namespace :db do
168
166
  if rand > 0.75
169
167
  mail.conversation.move_to_trash(demo)
170
168
  end
171
- end
172
-
169
+ end
170
+
173
171
  Forgery::Basic.number(:at_most => actors.size).times do
174
172
  actor = actors.delete_at((rand * actors.size).to_i)
175
- next if Actor.normalize(actor)==Actor.normalize(a)
173
+ next if Actor.normalize(actor)==Actor.normalize(a)
176
174
  mail = a.send_message(actor, "Hello, #{actor.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}", Forgery::LoremIpsum.words(10,:random => true))
177
175
  if rand > 0.5
178
176
  mail = actor.reply_to_sender(mail, "Pretty well #{a.name}. #{Forgery::LoremIpsum.sentences(2,:random => true)}")
@@ -182,13 +180,21 @@ namespace :db do
182
180
  end
183
181
  if rand > 0.75
184
182
  mail.conversation.move_to_trash(actor)
185
- end
183
+ end
186
184
  end
187
185
  end
188
-
186
+
189
187
  mailboxer_end = Time.now
190
188
  puts ' -> ' + (mailboxer_end - mailboxer_start).round(4).to_s + 's'
191
-
189
+
190
+
191
+
192
+ puts 'Avatar population'
193
+ avatar_start = Time.now
194
+ SocialStream.subjects.each {|a| set_logos(Kernel.const_get(a.to_s.classify)) }
195
+ avatar_end = Time.now
196
+ puts ' -> ' + (avatar_end - avatar_start).round(4).to_s + 's'
197
+
192
198
  end
193
199
  end
194
200
  end