social_stream 0.0.4 → 0.0.5

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.
Files changed (113) hide show
  1. data/.gitignore +1 -0
  2. data/.yardopts +2 -0
  3. data/Gemfile +2 -3
  4. data/Gemfile.lock +20 -3
  5. data/README.rdoc +2 -3
  6. data/Rakefile +15 -18
  7. data/app/controllers/groups_controller.rb +9 -0
  8. data/app/controllers/likes_controller.rb +47 -0
  9. data/app/controllers/ties_controller.rb +2 -72
  10. data/app/helpers/activities_helper.rb +5 -1
  11. data/app/helpers/ties_helper.rb +21 -10
  12. data/app/models/actor.rb +53 -14
  13. data/app/models/group.rb +13 -0
  14. data/app/models/tie.rb +11 -2
  15. data/app/models/user.rb +6 -0
  16. data/app/views/activities/_activity.html.erb +2 -2
  17. data/app/views/activities/_child.html.erb +23 -0
  18. data/app/views/activities/_jquery.html.erb +0 -2
  19. data/app/views/activities/{_activity_options.html.erb → _options.html.erb} +1 -1
  20. data/app/views/activities/_root.html.erb +32 -0
  21. data/app/views/activity_objects/_activity_object.html.erb +1 -0
  22. data/app/views/groups/_group.html.erb +3 -0
  23. data/app/views/groups/show.html.erb +28 -0
  24. data/app/views/home/_groups.html.erb +14 -0
  25. data/app/views/home/index.html.erb +1 -0
  26. data/app/views/likes/create.js.erb +2 -0
  27. data/app/views/likes/destroy.js.erb +1 -0
  28. data/app/views/ties/_form.html.erb +6 -0
  29. data/app/views/ties/_new.html.erb +26 -0
  30. data/app/views/ties/_pending.html.erb +2 -14
  31. data/app/views/ties/_pendings.html.erb +16 -0
  32. data/app/views/ties/_suggestions.html.erb +7 -3
  33. data/app/views/ties/_tie.html.erb +21 -0
  34. data/app/views/ties/create.js.erb +21 -0
  35. data/app/views/ties/new.html.erb +1 -0
  36. data/app/views/ties/new.js.erb +2 -0
  37. data/config/locales/en.yml +32 -11
  38. data/config/routes.rb +14 -0
  39. data/init.rb +3 -0
  40. data/lib/generators/social_stream/install_generator.rb +8 -4
  41. data/lib/generators/social_stream/templates/initializer.rb +1 -1
  42. data/lib/generators/social_stream/templates/migration.rb +14 -1
  43. data/lib/generators/social_stream/templates/seeds.yml +30 -0
  44. data/lib/paperclip/ext.rb +6 -0
  45. data/lib/social_stream.rb +1 -1
  46. data/lib/social_stream/models/actor.rb +19 -4
  47. data/lib/social_stream/models/supertype.rb +2 -6
  48. data/lib/social_stream/rails.rb +9 -3
  49. data/lib/social_stream/version.rb +1 -1
  50. data/social_stream.gemspec +15 -0
  51. data/spec/dummy/Rakefile +7 -0
  52. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  53. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  54. data/spec/dummy/app/models/ability.rb +23 -0
  55. data/spec/dummy/app/models/post.rb +2 -0
  56. data/spec/dummy/app/models/user.rb +2 -0
  57. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  58. data/spec/dummy/config.ru +4 -0
  59. data/spec/dummy/config/application.rb +46 -0
  60. data/spec/dummy/config/boot.rb +10 -0
  61. data/spec/dummy/config/database.yml +22 -0
  62. data/spec/dummy/config/environment.rb +5 -0
  63. data/spec/dummy/config/environments/development.rb +26 -0
  64. data/spec/dummy/config/environments/production.rb +49 -0
  65. data/spec/dummy/config/environments/test.rb +35 -0
  66. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  67. data/spec/dummy/config/initializers/devise.rb +142 -0
  68. data/spec/dummy/config/initializers/inflections.rb +10 -0
  69. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  70. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  71. data/spec/dummy/config/initializers/session_store.rb +8 -0
  72. data/spec/dummy/config/initializers/social_stream.rb +5 -0
  73. data/spec/dummy/config/locales/en.yml +5 -0
  74. data/spec/dummy/config/routes.rb +58 -0
  75. data/spec/dummy/db/.gitignore +1 -0
  76. data/spec/dummy/db/migrate/.gitkeep +0 -0
  77. data/spec/dummy/db/schema.rb +116 -0
  78. data/spec/dummy/db/seeds.rb +9 -0
  79. data/spec/dummy/db/seeds/social_stream.yml +54 -0
  80. data/spec/dummy/log/.gitignore +1 -0
  81. data/spec/dummy/public/404.html +26 -0
  82. data/spec/dummy/public/422.html +26 -0
  83. data/spec/dummy/public/500.html +26 -0
  84. data/spec/dummy/public/favicon.ico +0 -0
  85. data/spec/dummy/public/javascripts/application.js +2 -0
  86. data/spec/dummy/public/javascripts/controls.js +965 -0
  87. data/spec/dummy/public/javascripts/dragdrop.js +974 -0
  88. data/spec/dummy/public/javascripts/effects.js +1123 -0
  89. data/spec/dummy/public/javascripts/prototype.js +6001 -0
  90. data/spec/dummy/public/javascripts/rails.js +175 -0
  91. data/spec/dummy/public/stylesheets/.gitkeep +0 -0
  92. data/spec/dummy/script/rails +6 -0
  93. data/spec/factories/activity.rb +10 -0
  94. data/spec/factories/actor.rb +4 -0
  95. data/spec/factories/group.rb +3 -0
  96. data/spec/factories/post.rb +3 -0
  97. data/spec/factories/tie.rb +38 -0
  98. data/spec/factories/user.rb +4 -0
  99. data/spec/integration/navigation_spec.rb +9 -0
  100. data/spec/models/activity_spec.rb +420 -0
  101. data/spec/models/actor_spec.rb +16 -0
  102. data/spec/models/post_spec.rb +33 -0
  103. data/spec/models/tie_spec.rb +30 -0
  104. data/spec/models/user_space.rb +10 -0
  105. data/spec/social_stream_spec.rb +7 -0
  106. data/spec/spec_helper.rb +45 -0
  107. data/spec/support/cancan.rb +1 -0
  108. data/spec/support/db.rb +4 -0
  109. metadata +155 -45
  110. data/app/views/activities/_root_activity.html.erb +0 -32
  111. data/app/views/activities/_subactivity.html.erb +0 -23
  112. data/app/views/ties/_suggestion.html.erb +0 -20
  113. data/lib/social_stream/rails/routes.rb +0 -19
data/.gitignore ADDED
@@ -0,0 +1 @@
1
+ pkg/*gem
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ lib/**/*.rb
2
+ app/**/*.rb
data/Gemfile CHANGED
@@ -8,9 +8,8 @@ if RUBY_VERSION < '1.9'
8
8
  gem "ruby-debug", ">= 0.10.3"
9
9
  end
10
10
 
11
- gem 'atd-ancestry', :require => 'ancestry'
12
- gem 'devise'
13
- gem 'inherited_resources'
11
+ gemspec
12
+
14
13
  gem 'cancan'
15
14
 
16
15
  gem "rspec-rails", ">= 2.0.0.beta"
data/Gemfile.lock CHANGED
@@ -1,3 +1,13 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ social_stream (0.0.4)
5
+ atd-ancestry (~> 1.3.0)
6
+ devise (~> 1.1.3)
7
+ inherited_resources (~> 1.1.2)
8
+ paperclip (~> 2.3.4)
9
+ stringex (~> 1.2.0)
10
+
1
11
  GEM
2
12
  remote: http://rubygems.org/
3
13
  specs:
@@ -67,6 +77,9 @@ GEM
67
77
  treetop (>= 1.4.5)
68
78
  mime-types (1.16)
69
79
  nokogiri (1.4.3.1)
80
+ paperclip (2.3.5)
81
+ activerecord
82
+ activesupport
70
83
  polyglot (0.3.1)
71
84
  rack (1.2.1)
72
85
  rack-mount (0.6.13)
@@ -112,6 +125,7 @@ GEM
112
125
  json_pure
113
126
  rubyzip
114
127
  sqlite3-ruby (1.3.1)
128
+ stringex (1.2.0)
115
129
  thor (0.14.3)
116
130
  treetop (1.4.8)
117
131
  polyglot (>= 0.3.1)
@@ -123,13 +137,16 @@ PLATFORMS
123
137
  ruby
124
138
 
125
139
  DEPENDENCIES
126
- atd-ancestry
140
+ atd-ancestry (~> 1.3.0)
127
141
  cancan
128
142
  capybara (>= 0.3.9)
129
- devise
143
+ devise (~> 1.1.3)
130
144
  factory_girl
131
- inherited_resources
145
+ inherited_resources (~> 1.1.2)
146
+ paperclip (~> 2.3.4)
132
147
  rails (= 3.0.0)
133
148
  rspec-rails (>= 2.0.0.beta)
134
149
  ruby-debug (>= 0.10.3)
150
+ social_stream!
135
151
  sqlite3-ruby
152
+ stringex (~> 1.2.0)
data/README.rdoc CHANGED
@@ -37,9 +37,8 @@ Then, execute:
37
37
  This will generate the following:
38
38
  * A migration providing the database schema
39
39
  * An initializer configuration file for Social Stream.
40
- * A database seeds file for defining Social Stream relations. You must add:
41
- SocialStream.seed!
42
- to your db/seeds.rb
40
+ * A database seeds file for defining Social Stream relations, along with an entry
41
+ in db/seeds.rb to load it.
43
42
  * A devise:install generation for authentication support
44
43
 
45
44
  == Actors and Activity Objects
data/Rakefile CHANGED
@@ -1,11 +1,14 @@
1
1
  # encoding: UTF-8
2
2
  require 'rake'
3
3
  require 'rake/rdoctask'
4
- require 'rake/gempackagetask'
4
+
5
+ require 'rubygems'
5
6
 
6
7
  require 'rspec/core'
7
8
  require 'rspec/core/rake_task'
8
9
 
10
+ require 'bundler'
11
+
9
12
  require File.join(File.dirname(__FILE__), 'lib', 'social_stream', 'version')
10
13
 
11
14
 
@@ -23,22 +26,16 @@ Rake::RDocTask.new(:rdoc) do |rdoc|
23
26
  rdoc.rdoc_files.include('lib/**/*.rb', 'app/**/*.rb')
24
27
  end
25
28
 
26
- spec = Gem::Specification.new do |s|
27
- s.name = "social_stream"
28
- s.version = SocialStream::VERSION.dup
29
- s.summary = "Social networking features and activity streams."
30
- s.description = "Ruby on Rails plug-in supporting social networking features and activity streams."
31
- s.authors = ['Antonio Tapiador', 'Diego Carrera']
32
- s.files = FileList["[A-Z]*", "{app,config,lib}/**/*"]
33
- s.add_dependency('atd-ancestry', '~> 1.3.0')
34
- s.add_dependency('devise', '~> 1.1.3')
35
- s.add_dependency('inherited_resources', '~> 1.1.2')
29
+ class Bundler::GemHelper
30
+ def install_gem
31
+ built_gem_path = build_gem
32
+ out, err, code = sh_with_code("sudo gem install #{built_gem_path} --no-rdoc --no-ri")
33
+ if err[/ERROR/]
34
+ Bundler.ui.error err
35
+ else
36
+ Bundler.ui.confirm "#{name} (#{version}) installed"
37
+ end
38
+ end
36
39
  end
37
40
 
38
- Rake::GemPackageTask.new(spec) do |pkg|
39
- end
40
-
41
- desc "Install the gem #{spec.name}-#{spec.version}.gem"
42
- task :install => :gem do
43
- system("sudo gem install pkg/#{spec.name}-#{spec.version}.gem --no-ri --no-rdoc")
44
- end
41
+ Bundler::GemHelper.install_tasks
@@ -0,0 +1,9 @@
1
+ class GroupsController < InheritedResources::Base
2
+ protected
3
+
4
+ # Overwrite resource method to support permalink
5
+ # See InheritedResources::BaseHelpers#resource
6
+ def resource
7
+ @group ||= end_of_association_chain.find_by_permalink!(params[:id])
8
+ end
9
+ end
@@ -0,0 +1,47 @@
1
+ class LikesController < ApplicationController
2
+ # Ensure the suitable tie exists
3
+ before_filter :tie!, :only => :create
4
+
5
+ # POST /activities/1/like.js
6
+ def create
7
+ @like = activity!.children.new :verb => "like"
8
+
9
+ respond_to do |format|
10
+ if @like.save
11
+ tie!.activities << @like
12
+ format.js
13
+ else
14
+ format.js
15
+ end
16
+ end
17
+ end
18
+
19
+ def destroy
20
+ if (@like = activity!.liked_by(current_user).first)
21
+ @like.destroy
22
+ end
23
+
24
+ respond_to do |format|
25
+ format.js
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def activity
32
+ @activity ||= Activity.find(params[:activity_id])
33
+ end
34
+
35
+ def activity!
36
+ activity || raise(ActiveRecord::RecordNotFound)
37
+ end
38
+
39
+ def tie
40
+ @tie ||= current_user.sent_ties(:receiver => activity!.receiver,
41
+ :relation => activity!.relation).first
42
+ end
43
+
44
+ def tie!
45
+ tie || raise(ActiveRecord::RecordNotFound)
46
+ end
47
+ end
@@ -1,73 +1,3 @@
1
- class TiesController < ApplicationController
2
- before_filter :actor!
3
-
4
- # GET /ties
5
- # GET /ties.xml
6
- def index
7
- @ties = actor.sent_ties.all
8
-
9
- respond_to do |format|
10
- format.html # index.html.erb
11
- format.xml { render :xml => @ties }
12
- end
13
- end
14
-
15
- # GET /ties/1
16
- # GET /ties/1.xml
17
- def show
18
- @tie = actor.sent_ties.find(params[:id])
19
-
20
- respond_to do |format|
21
- format.html # show.html.erb
22
- format.xml { render :xml => @tie }
23
- end
24
- end
25
-
26
- # GET /ties/new
27
- # GET /ties/new.xml
28
- def new
29
- @tie = actor!.sent_ties.build(params[:tie])
30
-
31
- respond_to do |format|
32
- format.html {render :layout => false }
33
- #format.xml { render :xml => @tie }
34
- format.js {render :partial => "ties/new"}
35
- end
36
- end
37
-
38
- # POST /ties
39
- # POST /ties.xml
40
- def create
41
- @tie = Tie.new(params[:tie])
42
-
43
- respond_to do |format|
44
- if @tie.save
45
- format.html { redirect_to(@tie, :notice => 'Tie was successfully created.') }
46
- format.xml { render :xml => @tie, :status => :created, :location => @tie }
47
- format.js
48
- else
49
- format.html { render :partial => "new" }
50
- format.xml { render :xml => @tie.errors, :status => :unprocessable_entity }
51
- format.js
52
- end
53
- end
54
- end
55
-
56
- # DELETE /ties/1
57
- # DELETE /ties/1.xml
58
- def destroy
59
- @tie = Tie.find(params[:id])
60
- @tie.destroy
61
-
62
- respond_to do |format|
63
- format.html { redirect_to(ties_url) }
64
- format.xml { head :ok }
65
- end
66
- end
67
-
68
- private
69
-
70
- def actor!
71
- current_user
72
- end
1
+ class TiesController < InheritedResources::Base
2
+ respond_to :html, :xml, :js
73
3
  end
@@ -1,6 +1,10 @@
1
1
  module ActivitiesHelper
2
2
 
3
- def like_activity(activity)
3
+ # Link to 'like' or 'unlike' depending on the like status of the activity to current_user
4
+ #
5
+ # @param [Activity]
6
+ # @return [String]
7
+ def link_like(activity)
4
8
  if (activity.liked_by?(current_user))
5
9
  link_to t('activity.unlike'), activity_like_path(activity), :method => :delete, :remote => true
6
10
  else
@@ -1,18 +1,29 @@
1
1
  module TiesHelper
2
- def suggestion_brief(subject)
2
+ def tie_brief(tie)
3
3
  "18 contacts in common"
4
4
  end
5
5
 
6
- def suggestion_link(subject, relations)
7
- relation = relations[subject.class.to_s.underscore.to_sym] # relation = relations[:user]
6
+ def tie_link(tie)
7
+ # FIXME: tie name
8
+ if tie.relation.granted
9
+ # There is granted relation, so another user must confirmate it
10
+ # We need to render ties#new with a message
11
+ link_to t("#{ tie.relation.name }.new"),
12
+ new_tie_path("tie[sender_id]" => tie.sender.id,
13
+ "tie[receiver_id]" => tie.receiver.id,
14
+ "tie[relation_name]" => tie.relation.name),
15
+ :title => t("#{ tie.relation.name }.confirm_new",
16
+ :name => tie.receiver_subject.name),
17
+ :remote => true
8
18
 
9
- raise "Relation not provided for #{ subject.class.to_s.underscore }" if relation.blank?
19
+ else
20
+ # Tie can be established at once.
21
+ render :partial => 'ties/form',
22
+ :locals => { :tie => tie }
23
+ end
24
+ end
10
25
 
11
- link_to t("tie.suggestion.#{ relation }.new"),
12
- new_tie_path("tie[sender_id]" => current_user.actor.id,
13
- "tie[receiver_id]" => subject.actor.id,
14
- "tie[relation_name]" => relation),
15
- :class => 'boxy',
16
- :title => t("tie.suggestion.#{ relation }.confirm_new", :name => subject.name)
26
+ def link_follow_state
27
+ link_to("unfollow", home_path)
17
28
  end
18
29
  end
data/app/models/actor.rb CHANGED
@@ -2,16 +2,32 @@
2
2
  class Actor < ActiveRecord::Base
3
3
  include SocialStream::Models::Supertype
4
4
 
5
+ validates_presence_of :name, :subject_type
6
+
7
+ acts_as_url :name, :url_attribute => :permalink
8
+
9
+ has_attached_file :logo,
10
+ :styles => { :small => "30x30" },
11
+ :default_url => "/:attachment/:style/:subtype_class.png"
12
+
5
13
  has_many :sent_ties,
6
14
  :class_name => "Tie",
7
15
  :foreign_key => 'sender_id',
8
16
  :dependent => :destroy
9
17
 
18
+ has_many :senders,
19
+ :through => :received_ties,
20
+ :uniq => true
21
+
10
22
  has_many :received_ties,
11
23
  :class_name => "Tie",
12
24
  :foreign_key => 'receiver_id',
13
25
  :dependent => :destroy
14
26
 
27
+ has_many :receivers,
28
+ :through => :sent_ties,
29
+ :uniq => true
30
+
15
31
  # The subject instance for this actor
16
32
  def subject
17
33
  subtype_instance ||
@@ -81,20 +97,39 @@ class Actor < ActiveRecord::Base
81
97
 
82
98
  # This is an scaffold for a recomendations engine
83
99
  #
84
- # By now, it returns another subject without any current relation
100
+ SuggestedRelations = {
101
+ 'User' => 'friend_request',
102
+ 'Group' => 'follower'
103
+ }
104
+
105
+ # Make n suggestions
106
+ # TODO: make more
107
+ def suggestions(n)
108
+ n.times.map{ |m| suggestion }
109
+ end
110
+
111
+ # By now, it returns a tie suggesting a relation from SuggestedRelations
112
+ # to another subject without any current relation
85
113
  #
86
114
  # Options::
87
115
  # * type: the class of the recommended subject
116
+ #
117
+ # @return [Tie]
88
118
  def suggestion(options = {})
89
- type = options[:type]
119
+ type = options[:type].present? ?
120
+ options[:type].to_s.classify :
121
+ SuggestedRelations.keys[rand(SuggestedRelations.size)]
90
122
 
91
- type = type.present? ?
92
- type.to_s.classify.constantize :
93
- random_receiving_subject_type
123
+ type_class = type.constantize
94
124
 
95
- candidates = type.all - receiver_subjects(type)
125
+ # Candidates are all the instance of "type" minus all the subjects
126
+ # that are receiving any tie from this actor
127
+ candidates = type_class.all - receiver_subjects(type)
128
+
129
+ candidate = candidates[rand(candidates.size)]
96
130
 
97
- candidates[rand(candidates.size)]
131
+ sent_ties.build :receiver_id => candidate.actor_id,
132
+ :relation => Relation.mode(subject_type, type).find_by_name(SuggestedRelations[type])
98
133
  end
99
134
 
100
135
  # All the ties this actor has with subject that support activities
@@ -102,17 +137,21 @@ class Actor < ActiveRecord::Base
102
137
  sent_ties.received_by(subject).active
103
138
  end
104
139
 
140
+ def pending_ties
141
+ #TODO: optimize by SQL
142
+ @pending_ties ||=
143
+ received_ties.pending.
144
+ select{ |t| ! receivers.include?(t.sender) }.
145
+ map{ |u| Tie.new :sender_id => u.receiver_id,
146
+ :receiver_id => u.sender_id,
147
+ :relation_id => u.relation.granted_id
148
+ }
149
+ end
150
+
105
151
  # The set of activities in the wall of this actor
106
152
  # TODO: authorization
107
153
  def wall
108
154
  Activity.wall ties
109
155
  end
110
-
111
- private
112
-
113
- def random_receiving_subject_type
114
- type_candidates = subject.class.receiving_subject_classes
115
- type_candidates[rand(type_candidates.size)]
116
- end
117
156
  end
118
157
 
@@ -0,0 +1,13 @@
1
+ class Group < ActiveRecord::Base
2
+ validates_presence_of :name
3
+
4
+ scope :alphabetic, includes(:actor).order('actors.name')
5
+
6
+ def logo
7
+ "group.png"
8
+ end
9
+
10
+ def followers
11
+ sender_subjects(:user, :relations => 'follower')
12
+ end
13
+ end