social_stream 0.0.1 → 0.0.2

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/Gemfile CHANGED
@@ -9,6 +9,7 @@ if RUBY_VERSION < '1.9'
9
9
  end
10
10
 
11
11
  gem 'atd-ancestry', :require => 'ancestry'
12
+ gem 'devise'
12
13
  gem 'cancan'
13
14
 
14
15
  gem "rspec-rails", ">= 2.0.0.beta"
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.3.4)
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.5)
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.4)
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.beta.20)
81
- rspec-core (= 2.0.0.beta.20)
82
- rspec-expectations (= 2.0.0.beta.20)
83
- rspec-mocks (= 2.0.0.beta.20)
84
- rspec-core (2.0.0.beta.20)
85
- rspec-expectations (2.0.0.beta.20)
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.beta.20)
88
- rspec-rails (2.0.0.beta.20)
89
- rspec (= 2.0.0.beta.20)
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.28)
97
- ffi (>= 0.6.1)
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.0)
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
- validates_presence_of :sender_id, :receiver_id, :relation_id
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
- def relation_set(r = :nil)
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
- case r
84
- when :nil
85
- set
86
- when String
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
- # Include default devise modules. Others available are:
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
- # Contents managed by actors
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
- # Example: config.activity_objects = [ :post, :comment, :photo ]
13
- config.activity_objects = []
16
+ # config.activity_objects = []
14
17
  end
@@ -76,6 +76,7 @@ class CreateSocialStream < ActiveRecord::Migration
76
76
  t.string "ancestry"
77
77
  t.integer "inverse_id"
78
78
  t.integer "granted_id"
79
+ t.boolean "default", :default => false
79
80
  end
80
81
 
81
82
  add_index "relations", ["ancestry"]
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
- s = s.to_s.classify.constantize
24
- s.__send__(:include, features) unless s.ancestors.include?(features)
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
@@ -1,4 +1,5 @@
1
1
  # Load Devise constant
2
+ require 'ancestry'
2
3
  require 'devise'
3
4
  require 'social_stream/rails/common'
4
5
  File.expand_path(__FILE__) =~ /#{ File.join('vendor', 'plugins') }/ ?
@@ -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
 
@@ -1,3 +1,3 @@
1
1
  module SocialStream
2
- VERSION = "0.0.1".freeze
2
+ VERSION = "0.0.2".freeze
3
3
  end
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: 29
4
+ hash: 27
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 1
10
- version: 0.0.1
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-18 00:00:00 +02:00
19
+ date: 2010-10-19 00:00:00 +02:00
20
20
  default_executable:
21
21
  dependencies:
22
22
  - !ruby/object:Gem::Dependency