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.
- data/README.rdoc +2 -2
- data/app/assets/stylesheets/base.css.scss +1 -1
- data/app/controllers/activities_controller.rb +1 -2
- data/app/controllers/profiles_controller.rb +40 -8
- data/app/controllers/search_controller.rb +6 -49
- data/app/helpers/search_helper.rb +4 -34
- data/app/models/activity_object.rb +37 -4
- data/app/models/actor.rb +6 -0
- data/app/models/relation.rb +15 -0
- data/app/models/tie.rb +6 -0
- data/app/views/comments/create.js.erb +12 -7
- data/app/views/messages/_form.html.erb +1 -1
- data/app/views/posts/create.js.erb +8 -3
- data/app/views/search/_extended_search.html.erb +1 -1
- data/app/views/search/_extended_tab.html.erb +5 -0
- data/app/views/search/_form.html.erb +3 -3
- data/app/views/search/index.js.erb +3 -3
- data/config/routes.rb +6 -2
- data/lib/logos/groups/1.jpg +0 -0
- data/lib/logos/groups/10.jpg +0 -0
- data/lib/logos/groups/11.jpg +0 -0
- data/lib/logos/groups/12.jpg +0 -0
- data/lib/logos/groups/2.jpg +0 -0
- data/lib/logos/groups/3.jpg +0 -0
- data/lib/logos/groups/4.jpg +0 -0
- data/lib/logos/groups/5.jpg +0 -0
- data/lib/logos/groups/6.jpg +0 -0
- data/lib/logos/groups/7.jpg +0 -0
- data/lib/logos/groups/8.jpg +0 -0
- data/lib/logos/groups/9.jpg +0 -0
- data/lib/logos/partners/1.jpg +0 -0
- data/lib/logos/partners/1.png +0 -0
- data/lib/logos/partners/2.jpg +0 -0
- data/lib/logos/partners/2.png +0 -0
- data/lib/logos/users/1.jpg +0 -0
- data/lib/logos/users/10.jpg +0 -0
- data/lib/logos/users/11.jpg +0 -0
- data/lib/logos/users/12.jpg +0 -0
- data/lib/logos/users/2.jpg +0 -0
- data/lib/logos/users/3.jpg +0 -0
- data/lib/logos/users/4.jpg +0 -0
- data/lib/logos/users/5.jpg +0 -0
- data/lib/logos/users/6.jpg +0 -0
- data/lib/logos/users/7.jpg +0 -0
- data/lib/logos/users/8.jpg +0 -0
- data/lib/logos/users/9.jpg +0 -0
- data/lib/social_stream-base.rb +8 -0
- data/lib/social_stream/base/dependencies.rb +3 -1
- data/lib/social_stream/base/thinking-sphinx.rb +3 -1
- data/lib/social_stream/base/version.rb +1 -1
- data/lib/social_stream/controllers/helpers.rb +36 -30
- data/lib/social_stream/controllers/objects.rb +89 -1
- data/lib/social_stream/controllers/subjects.rb +3 -1
- data/lib/social_stream/models/object.rb +18 -0
- data/lib/social_stream/models/subject.rb +2 -0
- data/lib/social_stream/population/activity_object.rb +55 -0
- data/lib/social_stream/{populate.rb → population/power_law.rb} +3 -4
- data/lib/social_stream/population/timestamps.rb +12 -0
- data/lib/social_stream/search.rb +107 -0
- data/lib/tasks/db/populate.rake +13 -26
- data/social_stream-base.gemspec +3 -1
- data/spec/models/post_spec.rb +14 -0
- 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
|
11
|
-
* Activity streams
|
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 ||=
|
12
|
+
@activities ||= profile_subject.
|
14
13
|
wall(:profile,
|
15
14
|
:for => current_subject,
|
16
15
|
:relation => rel).
|
@@ -1,9 +1,41 @@
|
|
1
|
-
class ProfilesController <
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
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? ||
|
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
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
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
|
-
|
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
|
34
|
-
|
35
|
-
|
36
|
-
|
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 :
|
35
|
+
has_many :author_actions,
|
36
36
|
:class_name => "ActivityAction",
|
37
|
-
:conditions => {
|
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
|
-
|
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?
|
data/app/models/relation.rb
CHANGED
@@ -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
|
-
|
2
|
-
|
3
|
-
$(".
|
4
|
-
$(".
|
5
|
-
$(
|
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,9 @@
|
|
1
|
-
|
2
|
-
|
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 %>
|
@@ -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? && '
|
16
|
+
:class => "global #{ params[:type].blank? && 'active' }"),
|
17
17
|
search_path(:q => params[:q]),
|
18
18
|
:remote => true %></li>
|
19
|
-
<% SocialStream.
|
19
|
+
<% SocialStream::Search.keys(:extended).each do |model_sym| %>
|
20
20
|
<li>
|
21
|
-
<%=
|
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('
|
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('
|
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('
|
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
|