social_stream-base 0.20.0 → 0.20.1

Sign up to get free protection for your applications and to get access to all the features.
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