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 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