social_stream 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +1 -0
- data/Gemfile.lock +27 -15
- data/app/models/actor.rb +31 -0
- data/app/models/tie.rb +55 -21
- data/app/models/user.rb +1 -4
- data/lib/generators/social_stream/templates/initializer.rb +9 -6
- data/lib/generators/social_stream/templates/migration.rb +1 -0
- data/lib/social_stream.rb +5 -1
- data/lib/social_stream/models/actor.rb +24 -0
- data/lib/social_stream/models/supertype.rb +6 -2
- data/lib/social_stream/rails.rb +1 -0
- data/lib/social_stream/seed.rb +2 -0
- data/lib/social_stream/version.rb +1 -1
- metadata +4 -4
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -31,8 +31,9 @@ GEM
|
|
31
31
|
arel (1.0.1)
|
32
32
|
activesupport (~> 3.0.0)
|
33
33
|
atd-ancestry (1.3.0)
|
34
|
+
bcrypt-ruby (2.1.2)
|
34
35
|
builder (2.1.2)
|
35
|
-
cancan (1.
|
36
|
+
cancan (1.4.0)
|
36
37
|
capybara (0.3.9)
|
37
38
|
culerity (>= 0.2.4)
|
38
39
|
mime-types (>= 1.16)
|
@@ -40,8 +41,13 @@ GEM
|
|
40
41
|
rack (>= 1.0.0)
|
41
42
|
rack-test (>= 0.5.4)
|
42
43
|
selenium-webdriver (>= 0.0.3)
|
44
|
+
childprocess (0.1.3)
|
45
|
+
ffi (~> 0.6.3)
|
43
46
|
columnize (0.3.1)
|
44
47
|
culerity (0.2.12)
|
48
|
+
devise (1.1.3)
|
49
|
+
bcrypt-ruby (~> 2.1.2)
|
50
|
+
warden (~> 0.10.7)
|
45
51
|
diff-lcs (1.1.2)
|
46
52
|
erubis (2.6.6)
|
47
53
|
abstract (>= 1.0.0)
|
@@ -51,7 +57,7 @@ GEM
|
|
51
57
|
i18n (0.4.1)
|
52
58
|
json_pure (1.4.6)
|
53
59
|
linecache (0.43)
|
54
|
-
mail (2.2.
|
60
|
+
mail (2.2.7)
|
55
61
|
activesupport (>= 2.3.6)
|
56
62
|
mime-types
|
57
63
|
treetop (>= 1.4.5)
|
@@ -61,7 +67,7 @@ GEM
|
|
61
67
|
rack (1.2.1)
|
62
68
|
rack-mount (0.6.13)
|
63
69
|
rack (>= 1.0.0)
|
64
|
-
rack-test (0.5.
|
70
|
+
rack-test (0.5.6)
|
65
71
|
rack (>= 1.0)
|
66
72
|
rails (3.0.0)
|
67
73
|
actionmailer (= 3.0.0)
|
@@ -77,31 +83,36 @@ GEM
|
|
77
83
|
rake (>= 0.8.4)
|
78
84
|
thor (~> 0.14.0)
|
79
85
|
rake (0.8.7)
|
80
|
-
rspec (2.0.0
|
81
|
-
rspec-core (= 2.0.0
|
82
|
-
rspec-expectations (= 2.0.0
|
83
|
-
rspec-mocks (= 2.0.0
|
84
|
-
rspec-core (2.0.0
|
85
|
-
rspec-expectations (2.0.0
|
86
|
+
rspec (2.0.0)
|
87
|
+
rspec-core (= 2.0.0)
|
88
|
+
rspec-expectations (= 2.0.0)
|
89
|
+
rspec-mocks (= 2.0.0)
|
90
|
+
rspec-core (2.0.0)
|
91
|
+
rspec-expectations (2.0.0)
|
86
92
|
diff-lcs (>= 1.1.2)
|
87
|
-
rspec-mocks (2.0.0
|
88
|
-
|
89
|
-
rspec (= 2.0.0
|
93
|
+
rspec-mocks (2.0.0)
|
94
|
+
rspec-core (= 2.0.0)
|
95
|
+
rspec-expectations (= 2.0.0)
|
96
|
+
rspec-rails (2.0.1)
|
97
|
+
rspec (~> 2.0.0)
|
90
98
|
ruby-debug (0.10.3)
|
91
99
|
columnize (>= 0.1)
|
92
100
|
ruby-debug-base (~> 0.10.3.0)
|
93
101
|
ruby-debug-base (0.10.3)
|
94
102
|
linecache (>= 0.3)
|
95
103
|
rubyzip (0.9.4)
|
96
|
-
selenium-webdriver (0.0.
|
97
|
-
|
104
|
+
selenium-webdriver (0.0.29)
|
105
|
+
childprocess (>= 0.0.7)
|
106
|
+
ffi (~> 0.6.3)
|
98
107
|
json_pure
|
99
108
|
rubyzip
|
100
109
|
sqlite3-ruby (1.3.1)
|
101
|
-
thor (0.14.
|
110
|
+
thor (0.14.3)
|
102
111
|
treetop (1.4.8)
|
103
112
|
polyglot (>= 0.3.1)
|
104
113
|
tzinfo (0.3.23)
|
114
|
+
warden (0.10.7)
|
115
|
+
rack (>= 1.0.0)
|
105
116
|
|
106
117
|
PLATFORMS
|
107
118
|
ruby
|
@@ -110,6 +121,7 @@ DEPENDENCIES
|
|
110
121
|
atd-ancestry
|
111
122
|
cancan
|
112
123
|
capybara (>= 0.3.9)
|
124
|
+
devise
|
113
125
|
factory_girl
|
114
126
|
rails (= 3.0.0)
|
115
127
|
rspec-rails (>= 2.0.0.beta)
|
data/app/models/actor.rb
CHANGED
@@ -23,9 +23,40 @@ class Actor < ActiveRecord::Base
|
|
23
23
|
Tie.sent_or_received_by(self)
|
24
24
|
end
|
25
25
|
|
26
|
+
# All the subject actors of class type that have at least one tie
|
27
|
+
# with this actor
|
28
|
+
#
|
29
|
+
# Options::
|
30
|
+
# * relations: Restrict the relations of considered ties
|
31
|
+
def contacts(type, options = {})
|
32
|
+
type_class = type.to_s.classify.constantize
|
33
|
+
|
34
|
+
cs = type_class.
|
35
|
+
select("DISTINCT #{ type_class.quoted_table_name }.*").
|
36
|
+
with_received_ties &
|
37
|
+
Tie.sent_by(self)
|
38
|
+
|
39
|
+
if options[:relations].present?
|
40
|
+
cs &=
|
41
|
+
Tie.related_by(Tie.Relation(options[:relations], :mode => [ subject.class, type_class ]))
|
42
|
+
end
|
43
|
+
|
44
|
+
cs
|
45
|
+
end
|
46
|
+
|
47
|
+
# This is an scaffold for a recomendations engine
|
48
|
+
#
|
49
|
+
# By now, it returns another actor without any current relation
|
50
|
+
def suggestion(type = subject.class)
|
51
|
+
candidates = type.to_s.classify.constantize.all - contacts(type)
|
52
|
+
|
53
|
+
candidates[rand(candidates.size)]
|
54
|
+
end
|
55
|
+
|
26
56
|
# The set of activities in the wall of this actor
|
27
57
|
# TODO: authorization
|
28
58
|
def wall
|
29
59
|
Activity.wall ties
|
30
60
|
end
|
31
61
|
end
|
62
|
+
|
data/app/models/tie.rb
CHANGED
@@ -20,17 +20,17 @@
|
|
20
20
|
# * sent_by(actor), ties whose sender is actor
|
21
21
|
# * received_by(actor), ties whose receiver is actor
|
22
22
|
# * sent_or_received_by(actor), the union of the former
|
23
|
+
# * related_by(relation), ties with this relation. Accepts relation, relation_name, integer, array
|
24
|
+
# * pending, ties whose relation grant other relations, like friendship requests.
|
23
25
|
# * inverse(tie), the inverse of tie
|
24
26
|
#
|
25
27
|
class Tie < ActiveRecord::Base
|
26
|
-
# Avoids loops at create_inverse after save callback
|
27
|
-
attr_accessor :_without_inverse
|
28
|
-
attr_protected :_without_inverse
|
29
|
-
|
30
28
|
# Facilitates relation assigment along with find_relation callback
|
31
29
|
attr_accessor :relation_name
|
32
30
|
|
33
|
-
|
31
|
+
# Avoids loops at create_inverse after save callback
|
32
|
+
attr_accessor :_without_inverse
|
33
|
+
attr_protected :_without_inverse
|
34
34
|
|
35
35
|
belongs_to :sender,
|
36
36
|
:class_name => "Actor",
|
@@ -38,6 +38,7 @@ class Tie < ActiveRecord::Base
|
|
38
38
|
belongs_to :receiver,
|
39
39
|
:class_name => "Actor",
|
40
40
|
:include => SocialStream.actors
|
41
|
+
|
41
42
|
belongs_to :relation
|
42
43
|
|
43
44
|
has_many :activities
|
@@ -56,12 +57,24 @@ class Tie < ActiveRecord::Base
|
|
56
57
|
|
57
58
|
}
|
58
59
|
|
60
|
+
scope :related_by, lambda { |r|
|
61
|
+
where(:relation_id => Relation(r))
|
62
|
+
}
|
63
|
+
|
64
|
+
scope :pending, includes(:relation) & Relation.request
|
65
|
+
|
59
66
|
scope :inverse, lambda { |t|
|
60
67
|
sent_by(t.receiver).
|
61
68
|
received_by(t.sender).
|
62
69
|
where(:relation_id => t.relation.inverse_id)
|
63
70
|
}
|
64
71
|
|
72
|
+
validates_presence_of :sender_id, :receiver_id, :relation_id
|
73
|
+
|
74
|
+
before_validation :find_relation
|
75
|
+
|
76
|
+
after_create :complete_weak_set, :create_inverse
|
77
|
+
|
65
78
|
def sender_subject
|
66
79
|
sender.try(:subject)
|
67
80
|
end
|
@@ -70,33 +83,28 @@ class Tie < ActiveRecord::Base
|
|
70
83
|
receiver.try(:subject)
|
71
84
|
end
|
72
85
|
|
73
|
-
before_validation :find_relation
|
74
|
-
|
75
|
-
scope :pending, includes(:relation) & Relation.request
|
76
|
-
|
77
86
|
# The set of ties between sender and receiver
|
78
87
|
#
|
79
|
-
|
88
|
+
# Options::
|
89
|
+
# * relations: Only ties with relations
|
90
|
+
def relation_set(options = {})
|
80
91
|
set = self.class.where(:sender_id => sender_id,
|
81
92
|
:receiver_id => receiver_id)
|
82
93
|
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
set.where(:relation_id => relation.mode.find_by_name(r))
|
88
|
-
else
|
89
|
-
set.where(:relation_id => r)
|
94
|
+
if options.key?(:relations)
|
95
|
+
set =
|
96
|
+
set.related_by self.class.Relation(options[:relations],
|
97
|
+
:mode => relation.mode)
|
90
98
|
end
|
99
|
+
|
100
|
+
set
|
91
101
|
end
|
92
102
|
|
93
103
|
# The tie with relation r inside this relation_set
|
94
104
|
def related(r)
|
95
|
-
relation_set(r).first
|
105
|
+
relation_set(:relations => r).first
|
96
106
|
end
|
97
107
|
|
98
|
-
after_create :complete_weak_set, :create_inverse
|
99
|
-
|
100
108
|
# Access Control
|
101
109
|
|
102
110
|
scope :with_permissions, lambda { |action, object|
|
@@ -172,7 +180,7 @@ class Tie < ActiveRecord::Base
|
|
172
180
|
# Creates ties with a weaker relations in the strength hierarchy of this tie
|
173
181
|
def complete_weak_set
|
174
182
|
relation.weaker.each do |r|
|
175
|
-
if relation_set(r).blank?
|
183
|
+
if relation_set(:relations => r).blank?
|
176
184
|
t = relation_set.build :relation => r
|
177
185
|
t._without_inverse = true
|
178
186
|
t.save!
|
@@ -203,5 +211,31 @@ class Tie < ActiveRecord::Base
|
|
203
211
|
a.actor.id
|
204
212
|
end
|
205
213
|
end
|
214
|
+
|
215
|
+
# Normalize a relation for ActiveRecord query from relation_name, id or Array
|
216
|
+
#
|
217
|
+
# Options::
|
218
|
+
# mode:: Relation mode
|
219
|
+
def Relation(r, options = {})
|
220
|
+
case r
|
221
|
+
when Relation
|
222
|
+
r
|
223
|
+
when String
|
224
|
+
case options[:mode]
|
225
|
+
when Array
|
226
|
+
Relation.mode(*options[:mode]).find_by_name(r)
|
227
|
+
when ActiveRecord::Relation
|
228
|
+
options[:mode].find_by_name(r)
|
229
|
+
else
|
230
|
+
raise "Must provide a mode when looking up relations from name: #{ options[:mode] }"
|
231
|
+
end
|
232
|
+
when Integer
|
233
|
+
r
|
234
|
+
when Array
|
235
|
+
r.map{ |e| Relation(e, options) }
|
236
|
+
else
|
237
|
+
raise "Unable to normalize relation #{ r.inspect }"
|
238
|
+
end
|
239
|
+
end
|
206
240
|
end
|
207
241
|
end
|
data/app/models/user.rb
CHANGED
@@ -1,8 +1,5 @@
|
|
1
1
|
class User < ActiveRecord::Base
|
2
|
-
|
3
|
-
# :token_authenticatable, :confirmable, :lockable, :timeoutable, :validatable
|
4
|
-
devise :database_authenticatable, :registerable,
|
5
|
-
:recoverable, :rememberable, :trackable
|
2
|
+
devise *SocialStream.devise_modules
|
6
3
|
|
7
4
|
# Setup accessible (or protected) attributes for your model
|
8
5
|
attr_accessible :name, :email, :password, :password_confirmation, :remember_me
|
@@ -1,14 +1,17 @@
|
|
1
1
|
SocialStream.setup do |config|
|
2
2
|
# List the models that are social entities. These will have ties between them.
|
3
|
-
#
|
4
3
|
# Remember you must add an "actor_id" foreign key column to your migration!
|
5
4
|
#
|
6
|
-
config.actors = [:user ]
|
5
|
+
# config.actors = [:user ]
|
7
6
|
|
8
|
-
#
|
9
|
-
#
|
7
|
+
# Include devise modules in User. See devise documentation for details.
|
8
|
+
# Others available are:
|
9
|
+
# :token_authenticatable, :confirmable, :lockable, :timeoutable, :validatable
|
10
|
+
# config.devise_modules :database_authenticatable, :registerable,
|
11
|
+
:recoverable, :rememberable, :trackable
|
12
|
+
|
13
|
+
# Type of activities managed by actors
|
10
14
|
# Remember you must add an "activity_object_id" foreign key column to your migration!
|
11
15
|
#
|
12
|
-
#
|
13
|
-
config.activity_objects = []
|
16
|
+
# config.activity_objects = []
|
14
17
|
end
|
data/lib/social_stream.rb
CHANGED
@@ -9,7 +9,11 @@ module SocialStream
|
|
9
9
|
end
|
10
10
|
|
11
11
|
mattr_accessor :actors
|
12
|
-
@@actors = []
|
12
|
+
@@actors = [ :user ]
|
13
|
+
|
14
|
+
mattr_accessor :devise_modules
|
15
|
+
@@devise_modules = [ :database_authenticatable, :registerable, :recoverable,
|
16
|
+
:rememberable, :trackable ]
|
13
17
|
|
14
18
|
mattr_accessor :activity_objects
|
15
19
|
@@activity_objects = []
|
@@ -16,14 +16,38 @@ module SocialStream
|
|
16
16
|
:permalink, :permalink=,
|
17
17
|
:disabled, :disabled=,
|
18
18
|
:ties, :sent_ties, :received_ties,
|
19
|
+
:contacts, :suggestion,
|
19
20
|
:wall,
|
20
21
|
:to => :actor!
|
22
|
+
|
23
|
+
after_create :initialize_default_ties
|
21
24
|
end
|
22
25
|
|
23
26
|
module InstanceMethods
|
24
27
|
def actor!
|
25
28
|
actor || build_actor
|
26
29
|
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def initialize_default_ties
|
34
|
+
self.class.relations.where(:default => true).each do |r|
|
35
|
+
Tie.create! :sender => self.actor,
|
36
|
+
:receiver => self.actor,
|
37
|
+
:relation => r
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
module ClassMethods
|
43
|
+
# Relations defined for this actor model.
|
44
|
+
def relations(to = to_s)
|
45
|
+
Relation.mode(to_s, to)
|
46
|
+
end
|
47
|
+
|
48
|
+
def with_received_ties
|
49
|
+
joins(:actor => :received_ties)
|
50
|
+
end
|
27
51
|
end
|
28
52
|
end
|
29
53
|
end
|
@@ -20,8 +20,12 @@ module SocialStream #:nodoc:
|
|
20
20
|
features = "SocialStream::Models::#{ to_s }".constantize
|
21
21
|
|
22
22
|
subtypes.each do |s|
|
23
|
-
|
24
|
-
|
23
|
+
begin
|
24
|
+
s = s.to_s.classify.constantize
|
25
|
+
s.__send__(:include, features) unless s.ancestors.include?(features)
|
26
|
+
rescue
|
27
|
+
puts "Warning: could not load #{ s }"
|
28
|
+
end
|
25
29
|
end
|
26
30
|
end
|
27
31
|
end
|
data/lib/social_stream/rails.rb
CHANGED
data/lib/social_stream/seed.rb
CHANGED
@@ -24,6 +24,8 @@ module SocialStream
|
|
24
24
|
find_or_create_by_sender_type_and_receiver_type_and_name(r['sender_type'],
|
25
25
|
r['receiver_type'],
|
26
26
|
r['name'])
|
27
|
+
relations[name].update_attribute(:default, r['default'])
|
28
|
+
|
27
29
|
# FIXME: optimize
|
28
30
|
relations[name].relation_permissions.destroy_all
|
29
31
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: social_stream
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Antonio Tapiador
|
@@ -16,7 +16,7 @@ autorequire:
|
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
18
|
|
19
|
-
date: 2010-10-
|
19
|
+
date: 2010-10-19 00:00:00 +02:00
|
20
20
|
default_executable:
|
21
21
|
dependencies:
|
22
22
|
- !ruby/object:Gem::Dependency
|