social_stream-base 0.20.0 → 0.20.1

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 (63) hide show
  1. data/README.rdoc +2 -2
  2. data/app/assets/stylesheets/base.css.scss +1 -1
  3. data/app/controllers/activities_controller.rb +1 -2
  4. data/app/controllers/profiles_controller.rb +40 -8
  5. data/app/controllers/search_controller.rb +6 -49
  6. data/app/helpers/search_helper.rb +4 -34
  7. data/app/models/activity_object.rb +37 -4
  8. data/app/models/actor.rb +6 -0
  9. data/app/models/relation.rb +15 -0
  10. data/app/models/tie.rb +6 -0
  11. data/app/views/comments/create.js.erb +12 -7
  12. data/app/views/messages/_form.html.erb +1 -1
  13. data/app/views/posts/create.js.erb +8 -3
  14. data/app/views/search/_extended_search.html.erb +1 -1
  15. data/app/views/search/_extended_tab.html.erb +5 -0
  16. data/app/views/search/_form.html.erb +3 -3
  17. data/app/views/search/index.js.erb +3 -3
  18. data/config/routes.rb +6 -2
  19. data/lib/logos/groups/1.jpg +0 -0
  20. data/lib/logos/groups/10.jpg +0 -0
  21. data/lib/logos/groups/11.jpg +0 -0
  22. data/lib/logos/groups/12.jpg +0 -0
  23. data/lib/logos/groups/2.jpg +0 -0
  24. data/lib/logos/groups/3.jpg +0 -0
  25. data/lib/logos/groups/4.jpg +0 -0
  26. data/lib/logos/groups/5.jpg +0 -0
  27. data/lib/logos/groups/6.jpg +0 -0
  28. data/lib/logos/groups/7.jpg +0 -0
  29. data/lib/logos/groups/8.jpg +0 -0
  30. data/lib/logos/groups/9.jpg +0 -0
  31. data/lib/logos/partners/1.jpg +0 -0
  32. data/lib/logos/partners/1.png +0 -0
  33. data/lib/logos/partners/2.jpg +0 -0
  34. data/lib/logos/partners/2.png +0 -0
  35. data/lib/logos/users/1.jpg +0 -0
  36. data/lib/logos/users/10.jpg +0 -0
  37. data/lib/logos/users/11.jpg +0 -0
  38. data/lib/logos/users/12.jpg +0 -0
  39. data/lib/logos/users/2.jpg +0 -0
  40. data/lib/logos/users/3.jpg +0 -0
  41. data/lib/logos/users/4.jpg +0 -0
  42. data/lib/logos/users/5.jpg +0 -0
  43. data/lib/logos/users/6.jpg +0 -0
  44. data/lib/logos/users/7.jpg +0 -0
  45. data/lib/logos/users/8.jpg +0 -0
  46. data/lib/logos/users/9.jpg +0 -0
  47. data/lib/social_stream-base.rb +8 -0
  48. data/lib/social_stream/base/dependencies.rb +3 -1
  49. data/lib/social_stream/base/thinking-sphinx.rb +3 -1
  50. data/lib/social_stream/base/version.rb +1 -1
  51. data/lib/social_stream/controllers/helpers.rb +36 -30
  52. data/lib/social_stream/controllers/objects.rb +89 -1
  53. data/lib/social_stream/controllers/subjects.rb +3 -1
  54. data/lib/social_stream/models/object.rb +18 -0
  55. data/lib/social_stream/models/subject.rb +2 -0
  56. data/lib/social_stream/population/activity_object.rb +55 -0
  57. data/lib/social_stream/{populate.rb → population/power_law.rb} +3 -4
  58. data/lib/social_stream/population/timestamps.rb +12 -0
  59. data/lib/social_stream/search.rb +107 -0
  60. data/lib/tasks/db/populate.rake +13 -26
  61. data/social_stream-base.gemspec +3 -1
  62. data/spec/models/post_spec.rb +14 -0
  63. metadata +110 -68
data/README.rdoc CHANGED
@@ -7,8 +7,8 @@ network environment see https://github.com/ging/social_stream
7
7
 
8
8
  == Features
9
9
 
10
- * Social network infraestructure
11
- * Activity streams infraestructure
10
+ * Social network infrastructure
11
+ * Activity streams infrastructure
12
12
  * Subjects: {User} and {Group}
13
13
  * Objects: {Post} and {Comment}
14
14
  * Private messages and notifications, by {Mailboxer}[https://github.com/ging/mailboxer]
@@ -240,7 +240,7 @@ div.chzn-container ul.chzn-choices li.search-field input{ cursor:pointer;}
240
240
  padding: 5px 7px;
241
241
  background-color: $secondary-color;
242
242
  }
243
- .menu_plain_list li span.selected {
243
+ .menu_plain_list li span.selected, .menu_plain_list li span.active {
244
244
  border: solid 1px $main-color;
245
245
  }
246
246
  .menu_plain_list li span.disabled {
@@ -1,5 +1,4 @@
1
1
  class ActivitiesController < InheritedResources::Base
2
- belongs_to_subjects
3
2
  actions :index
4
3
 
5
4
  respond_to :js
@@ -10,7 +9,7 @@ class ActivitiesController < InheritedResources::Base
10
9
  rel = params[:section].to_i if params[:section].present?
11
10
 
12
11
  # should be activities.page(params[:page], :count => { :select => 'activity.id', :distinct => true }) but it is not working in Rails 3.0.3
13
- @activities ||= association_chain[-1].
12
+ @activities ||= profile_subject.
14
13
  wall(:profile,
15
14
  :for => current_subject,
16
15
  :relation => rel).
@@ -1,9 +1,41 @@
1
- class ProfilesController < InheritedResources::Base
2
- belongs_to_subjects(:singleton => true)
3
-
4
- load_and_authorize_resource :profile,
5
- :through => SocialStream.subjects,
6
- :singleton => true
7
-
8
- respond_to :html, :xml, :js
1
+ class ProfilesController < ApplicationController
2
+ before_filter :authenticate_user!, :except => [ :show ]
3
+
4
+ respond_to :html, :js
5
+
6
+ def show
7
+ subject_profile
8
+ end
9
+
10
+ def edit
11
+ current_profile
12
+ end
13
+
14
+ def update
15
+ current_profile.update_attributes params[:profile]
16
+
17
+ respond_to do |format|
18
+ format.html{ redirect_to [profile_subject, :profile] }
19
+ format.js
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ def subject_profile
26
+ @profile ||=
27
+ profile_subject!.profile
28
+ end
29
+
30
+ def current_profile
31
+ @profile ||= find_current_profile
32
+ end
33
+
34
+ def find_current_profile
35
+ unless profile_subject!.represented_by?(current_subject)
36
+ raise CanCan::AccessDenied
37
+ end
38
+
39
+ current_subject.profile
40
+ end
9
41
  end
@@ -1,18 +1,14 @@
1
1
  class SearchController < ApplicationController
2
2
  include ActionView::Helpers::SanitizeHelper
3
3
 
4
- helper_method :get_search_query
5
-
6
4
  RESULTS_SEARCH_PER_PAGE=12
7
5
  MIN_QUERY=2
8
6
  def index
9
7
  @search_result =
10
- if params[:q].blank? || too_short_query
8
+ if params[:q].blank? || params[:q].strip.size < MIN_QUERY
11
9
  []
12
10
  elsif params[:mode].eql? "header_search"
13
11
  search :quick
14
- elsif params[:type].present?
15
- focus_search
16
12
  else
17
13
  search :extended
18
14
  end
@@ -41,56 +37,17 @@ class SearchController < ApplicationController
41
37
  private
42
38
 
43
39
  def search mode
44
- models = ( mode.to_s.eql?("quick") ?
45
- SocialStream.extended_search_models :
46
- SocialStream.quick_search_models
47
- ).dup
40
+ result = SocialStream::Search.search(params[:q],
41
+ current_subject,
42
+ :mode => mode,
43
+ :key => params[:type])
48
44
 
49
- models.map! {|model_sym| model_sym.to_s.classify.constantize}
50
- result = ThinkingSphinx.search(get_search_query, :classes => models)
51
- result = authorization_filter result
52
45
  if mode.to_s.eql? "quick"
53
46
  result = Kaminari.paginate_array(result).page(1).per(7)
54
47
  else
55
48
  result = Kaminari.paginate_array(result).page(params[:page]).per(RESULTS_SEARCH_PER_PAGE)
56
49
  end
57
- return result
58
- end
59
-
60
- def focus_search
61
- @search_class_sym = params[:type].singularize.to_sym unless params[:type].blank?
62
- search_class = @search_class_sym.to_s.classify.constantize
63
- result = ThinkingSphinx.search(get_search_query, :classes => [search_class])
64
- result = authorization_filter result
65
- return Kaminari.paginate_array(result).page(params[:page]).per(RESULTS_SEARCH_PER_PAGE)
66
- end
67
-
68
- def too_short_query
69
- bare_query = strip_tags(params[:q]) unless bare_query.html_safe?
70
- return bare_query.strip.size < MIN_QUERY
71
- end
72
-
73
- def get_search_query
74
- search_query = ""
75
- param = strip_tags(params[:q]) || ""
76
- bare_query = param unless bare_query.html_safe?
77
- search_query_words = bare_query.strip.split
78
- search_query_words.each_index do |i|
79
- search_query+= search_query_words[i] + " " if i < (search_query_words.size - 1)
80
- search_query+= "*" + search_query_words[i] + "* " if i == (search_query_words.size - 1)
81
- end
82
- return search_query.strip
83
- end
84
50
 
85
- def authorization_filter results
86
- filtered_results = Array.new
87
- results.each do |result|
88
- if result.is_a? SocialStream::Models::Object
89
- filtered_results << result if can? :read, result
90
- else
91
- filtered_results << result
92
- end
93
- end
94
- return filtered_results
51
+ result
95
52
  end
96
53
  end
@@ -30,39 +30,9 @@ module SearchHelper
30
30
  return bare_query.strip.split
31
31
  end
32
32
 
33
- def search_class(type, model_sym)
34
- case type
35
- when :selected
36
- params[:type].present? &&
37
- params[:type].eql?(model_sym.to_s) &&
38
- 'selected' || ''
39
- when :disabled
40
- search_results?(model_sym) &&
41
- '' || 'disabled'
42
- else
43
- raise "Unknown select search class type"
44
- end
45
- end
46
-
47
- def search_results?(model_sym)
48
- ThinkingSphinx.count(get_search_query,
49
- :classes => [model_sym.to_s.classify.constantize]) > 0
50
- end
51
-
52
- def search_tab(model_sym)
53
- span_options = {}
54
- span_options[:class] = "#{ search_class(:selected, model_sym) } #{ search_class(:disabled, model_sym) } #{ model_sym.to_s.pluralize.downcase }"
55
-
56
- results = search_results?(model_sym)
57
-
58
- unless results
59
- span_options[:title] = t('search.no_subject_found', :subject => model_sym.to_s)
60
- end
61
-
62
- link_to_if results,
63
- content_tag(:span, t("#{ model_sym }.title.other"), span_options),
64
- search_path(:type => model_sym,
65
- :q => params[:q]),
66
- :remote => true
33
+ def search_results?(key)
34
+ SocialStream::Search.count(params[:q],
35
+ current_subject,
36
+ :key => key) > 0
67
37
  end
68
38
  end
@@ -32,9 +32,12 @@ class ActivityObject < ActiveRecord::Base
32
32
  :conditions => { 'activity_actions.follow' => true }
33
33
 
34
34
  # Associations for indexing
35
- has_many :author_action,
35
+ has_many :author_actions,
36
36
  :class_name => "ActivityAction",
37
- :conditions => { 'activity_actions.author' => true }
37
+ :conditions => { :author => true }
38
+ has_many :owner_actions,
39
+ :class_name => "ActivityAction",
40
+ :conditions => { :owner => true }
38
41
 
39
42
  has_many :activity_object_properties,
40
43
  :dependent => :destroy
@@ -49,7 +52,8 @@ class ActivityObject < ActiveRecord::Base
49
52
  :through => :activity_object_holders,
50
53
  :source => :activity_object
51
54
 
52
- before_validation :fill_relation_ids, :if => lambda { |obj| obj.object_type != "Actor" }
55
+
56
+ before_validation :fill_owner_id, :fill_user_author_id, :fill_relation_ids, :if => lambda { |obj| obj.object_type != "Actor" }
53
57
 
54
58
  validates_presence_of :object_type
55
59
  validate :allowed_relations, :if => lambda { |obj| obj.object_type != "Actor" }
@@ -71,8 +75,23 @@ class ActivityObject < ActiveRecord::Base
71
75
  merge(ActivityAction.not_sent_by(subject).where(:author => true))
72
76
  }
73
77
 
78
+ scope :owned_by, lambda { |subject|
79
+ joins(:received_actions).
80
+ merge(ActivityAction.sent_by(subject).where(:owner => true))
81
+ }
82
+
74
83
  scope :followed, order("activity_objects.follower_count DESC")
75
84
 
85
+ scope :followed_by, lambda { |subject|
86
+ joins(:received_actions).
87
+ merge(ActivityAction.sent_by(subject).where(:follow => true))
88
+ }
89
+
90
+ scope :shared_with, lambda { |subject|
91
+ joins(:activity_object_audiences).
92
+ merge(ActivityObjectAudience.where(:relation_id => Relation.ids_shared_with(subject)))
93
+ }
94
+
76
95
  def received_role_action(role)
77
96
  received_actions.
78
97
  find{ |a| a.__send__ "#{ role }?" }
@@ -179,6 +198,20 @@ class ActivityObject < ActiveRecord::Base
179
198
 
180
199
  private
181
200
 
201
+ def fill_owner_id
202
+ return if owner_id.present? || author_id.blank?
203
+
204
+ self.owner_id = author_id
205
+ end
206
+
207
+ def fill_user_author_id
208
+ return if user_author_id.present? ||
209
+ author_id.blank? ||
210
+ author.subject_type != "User"
211
+
212
+ self.user_author_id = author_id
213
+ end
214
+
182
215
  def fill_relation_ids
183
216
  return if relation_ids.present? || author.blank? || owner.blank?
184
217
 
@@ -206,7 +239,7 @@ class ActivityObject < ActiveRecord::Base
206
239
  Relation::Single.allowing('read', 'activity')
207
240
 
208
241
  if (relation_ids - allowed_rels.map(&:id)).any?
209
- errors.add(:relation_ids, "not allowed")
242
+ errors.add(:relation_ids, "not allowed: #{ relation_ids }, author_id: #{ author_id }, owner_id: #{ owner_id }")
210
243
  end
211
244
  end
212
245
 
data/app/models/actor.rb CHANGED
@@ -317,6 +317,12 @@ class Actor < ActiveRecord::Base
317
317
  map(&:id)
318
318
  end
319
319
 
320
+ # An array with the ids of {Actor Actors} followed by this {Actor}
321
+ # plus the id from this {Actor}
322
+ def following_actor_and_self_ids
323
+ following_actor_ids + [ id ]
324
+ end
325
+
320
326
  # Does this {Actor} allow subject to perform action on object?
321
327
  def allow?(subject, action, object)
322
328
  ties_to(subject).with_permissions(action, object).any?
@@ -152,6 +152,21 @@ class Relation < ActiveRecord::Base
152
152
  def allow?(*args)
153
153
  allow(*args).to_a.any?
154
154
  end
155
+
156
+ # All the {Relation} ids in {Tie Ties} this subject has received
157
+ # plus the one from {Relation::Public}
158
+ def ids_shared_with(subject)
159
+ ids = [Relation::Public.instance.id]
160
+
161
+ if SocialStream.relation_model == :custom && subject.present?
162
+ # Subject own defined custom relations
163
+ ids += subject.relation_ids
164
+ # From Ties sent by other subject
165
+ ids += subject.received_relation_ids
166
+ end
167
+
168
+ ids
169
+ end
155
170
  end
156
171
 
157
172
  # Relation class scoped in the same mode that this relation
data/app/models/tie.rb CHANGED
@@ -28,6 +28,12 @@ class Tie < ActiveRecord::Base
28
28
  has_one :receiver, :through => :contact
29
29
 
30
30
  belongs_to :relation
31
+ has_many :permissions, :through => :relation
32
+
33
+ scope :allowing, lambda { |action, object|
34
+ joins(:relation).
35
+ merge(Relation.allowing(action, object))
36
+ }
31
37
 
32
38
  scope :recent, order("ties.created_at DESC")
33
39
 
@@ -1,8 +1,13 @@
1
- //Display the new comment
2
- $("#comments_activity_<%= @comment.post_activity.parent.id %>").append("<%= escape_javascript(render @comment.post_activity) %>");
3
- $(".activities_comment_btn").hide();
4
- $(".input_new_comments").each(function() {
5
- $(this).focus().val("").blur();
6
- });
1
+ <% if @comment.valid? %>
2
+ //Display the new comment
3
+ $("#comments_activity_<%= @comment.post_activity.parent.id %>").append("<%= escape_javascript(render @comment.post_activity) %>");
4
+ $(".activities_comment_btn").hide();
5
+ $(".input_new_comments").each(function() {
6
+ $(this).focus().val("").blur();
7
+ });
7
8
 
8
- SocialStream.Timeline.create("<%= escape_javascript dom_id(@comment.post_activity) %>");
9
+ SocialStream.Timeline.create("<%= escape_javascript dom_id(@comment.post_activity) %>");
10
+ <% else %>
11
+ SocialStream.Timeline.create();
12
+ alert('<%= j @comment.errors.full_messages.to_sentence %>');
13
+ <% end %>
@@ -1,4 +1,4 @@
1
- <h2>New Message</h2>
1
+ <h2><%= t('mailbox.message.new') %></h2>
2
2
  <%= form_tag messages_path, :method => :post , :class => "new_message" do %>
3
3
  <% if @receipt and @receipt.errors.any? %>
4
4
  <div class="error">
@@ -1,4 +1,9 @@
1
- //Display the new post
2
- $("#wall").prepend("<%= escape_javascript(render @post.post_activity) %>");
1
+ <% if @post.valid? %>
2
+ //Display the new post
3
+ $("#wall").prepend("<%= escape_javascript(render @post.post_activity) %>");
3
4
 
4
- SocialStream.Timeline.create("<%= escape_javascript dom_id(@post.post_activity) %>");
5
+ SocialStream.Timeline.create("<%= escape_javascript dom_id(@post.post_activity) %>");
6
+ <% else %>
7
+ SocialStream.Timeline.create();
8
+ alert('<%= j @post.errors.full_messages.to_sentence %>');
9
+ <% end %>
@@ -4,7 +4,7 @@
4
4
  </div>
5
5
  <% else %>
6
6
  <% @search_result.each do |model|%>
7
- <% if @search_class_sym.nil? %>
7
+ <% if params[:type].blank? %>
8
8
  <div class="subject_search_results block left">
9
9
  <%= render_global_search_for model %>
10
10
  </div>
@@ -0,0 +1,5 @@
1
+ <%= link_to (search_results?(key) ? search_path(:type => key, :q => params[:q]) : '#') do %>
2
+ <span class="<%= key %><%= " active" if params[:type] == key.to_s %><%= " disabled" unless search_results?(key) %>" <%= "title=\"#{ t 'search.no_subject_found', :subject => key.to_s }\"" %>>
3
+ <%= t("#{ key }.title.other") %>
4
+ </span>
5
+ <% end %>
@@ -13,12 +13,12 @@
13
13
  <ul class="menu_plain_list">
14
14
  <li><%= link_to content_tag(:span,
15
15
  t('search.show_all'),
16
- :class => "global #{ params[:type].blank? && 'selected' }"),
16
+ :class => "global #{ params[:type].blank? && 'active' }"),
17
17
  search_path(:q => params[:q]),
18
18
  :remote => true %></li>
19
- <% SocialStream.extended_search_models.each do |model_sym| %>
19
+ <% SocialStream::Search.keys(:extended).each do |model_sym| %>
20
20
  <li>
21
- <%= search_tab(model_sym) %>
21
+ <%= render :partial => 'extended_tab', :locals => { :key => model_sym } %>
22
22
  </li>
23
23
  <% end %>
24
24
  </ul>
@@ -1,12 +1,12 @@
1
1
  $('#search_results').html("<%= escape_javascript render :partial => 'extended_search' %>");
2
2
  $('#search_form_div').html("<%= escape_javascript render :partial => 'form' %>");
3
3
 
4
- $('#focus_options ul li a span').removeClass('selected');
4
+ $('#focus_options ul li a span').removeClass('active');
5
5
 
6
6
  <% if params[:type].present? %>
7
- $('#focus_options ul li a span.<%= params[:type].pluralize.downcase %>').addClass('selected');
7
+ $('#focus_options ul li a span.<%= params[:type].pluralize.downcase %>').addClass('active');
8
8
  <% else %>
9
- $('#focus_options ul li a span.global').addClass('selected');
9
+ $('#focus_options ul li a span.global').addClass('active');
10
10
  <% end %>
11
11
 
12
12
  $('title').text('<%= t('search.name')%> <%= escape_javascript(params[:q].present? ? ": #{params[:q]}" : "")%>');
data/config/routes.rb CHANGED
@@ -17,7 +17,9 @@ Rails.application.routes.draw do
17
17
  #
18
18
  # /users/demo/posts
19
19
  (SocialStream.objects - [ :actor ]).each do |object|
20
- resources object.to_s.pluralize
20
+ resources object.to_s.pluralize do
21
+ get 'search', :on => :collection
22
+ end
21
23
  end
22
24
  end
23
25
  end
@@ -26,7 +28,9 @@ Rails.application.routes.draw do
26
28
  #
27
29
  # /posts
28
30
  (SocialStream.objects - [ :actor ]).each do |object|
29
- resources object.to_s.pluralize
31
+ resources object.to_s.pluralize do
32
+ get 'search', :on => :collection
33
+ end
30
34
  end
31
35
 
32
36
  resources :comments