social_stream-base 0.19.2 → 0.20.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (50) hide show
  1. data/app/assets/javascripts/social_stream.follow.js +23 -0
  2. data/app/assets/javascripts/social_stream.wall.js.erb +3 -3
  3. data/app/controllers/search_controller.rb +30 -16
  4. data/app/helpers/location_helper.rb +1 -44
  5. data/app/helpers/search_helper.rb +7 -7
  6. data/app/models/activity.rb +0 -21
  7. data/app/models/activity_action.rb +8 -0
  8. data/app/models/activity_object.rb +55 -25
  9. data/app/models/activity_object_audience.rb +8 -0
  10. data/app/models/actor.rb +9 -0
  11. data/app/models/comment.rb +1 -3
  12. data/app/models/group.rb +3 -0
  13. data/app/models/post.rb +1 -3
  14. data/app/models/relation.rb +5 -0
  15. data/app/models/relation/follow.rb +6 -7
  16. data/app/models/relation/public.rb +5 -0
  17. data/app/models/relation/single.rb +11 -1
  18. data/app/views/activities/_new.html.erb +1 -1
  19. data/app/views/contacts/_link_follow.html.erb +8 -4
  20. data/app/views/followers/update.js.erb +2 -0
  21. data/app/views/layouts/_search.html.erb +2 -2
  22. data/app/views/search/_extended_search.html.erb +17 -17
  23. data/app/views/search/_form.html.erb +4 -4
  24. data/app/views/search/_header_search.html.erb +2 -2
  25. data/app/views/search/index.html.erb +1 -1
  26. data/app/views/search/index.js.erb +4 -4
  27. data/db/migrate/20120403175913_create_activity_object_audiences.rb +34 -0
  28. data/db/migrate/20120411132550_add_visit_count_to_activity_object.rb +9 -0
  29. data/db/migrate/20120411151413_relation_public_permissions.rb +8 -0
  30. data/lib/generators/social_stream/base/templates/initializer.rb +3 -0
  31. data/lib/social_stream-base.rb +2 -1
  32. data/lib/social_stream/ability/base.rb +14 -8
  33. data/lib/social_stream/base/dependencies.rb +1 -0
  34. data/lib/social_stream/base/thinking-sphinx.rb +18 -0
  35. data/lib/social_stream/base/version.rb +1 -1
  36. data/lib/social_stream/controllers/objects.rb +6 -0
  37. data/lib/social_stream/test_helpers/controllers.rb +1 -1
  38. data/lib/social_stream/views/location.rb +48 -0
  39. data/lib/tasks/db/populate.rake +1 -1
  40. data/lib/thinking-sphinx/social_stream.rb +3 -0
  41. data/spec/controllers/groups_controller_spec.rb +6 -6
  42. data/spec/controllers/posts_controller_spec.rb +6 -6
  43. data/spec/controllers/users_controller_spec.rb +4 -4
  44. data/spec/dummy/config/initializers/social_stream.rb +3 -0
  45. data/spec/factories/activity.rb +24 -1
  46. data/spec/factories/post.rb +1 -1
  47. data/spec/models/activity_authorization_spec.rb +1 -1
  48. data/spec/models/post_spec.rb +0 -4
  49. data/spec/models/relation_follow_spec.rb +8 -0
  50. metadata +73 -64
@@ -0,0 +1,23 @@
1
+ SocialStream.Follow = (function(SS, $, undefined){
2
+ var initButtons = function(){
3
+ $(".following-button").mouseenter(function(){
4
+ $(this).hide();
5
+ $(this).siblings(".unfollow-button").show();
6
+ });
7
+
8
+ $(".unfollow-button").mouseleave(function(){
9
+ $(this).hide();
10
+ $(this).siblings(".following-button").show();
11
+ });
12
+
13
+ $(".unfollow-button").hide();
14
+ }
15
+
16
+ $(function(){
17
+ SocialStream.Follow.initButtons();
18
+ });
19
+
20
+ return {
21
+ initButtons: initButtons
22
+ };
23
+ })(SocialStream, jQuery);
@@ -91,7 +91,7 @@ SocialStream.Wall = (function(SS, $, undefined){
91
91
  });
92
92
  $("#masterSubmitButton").val(I18n.t('activity.sending') + '...').attr("disabled", true);
93
93
 
94
- // Add _relation_ids[] parameter from authorization selector
94
+ // Add relation_ids[] parameter from authorization selector
95
95
  $('.liveAdded').remove();
96
96
 
97
97
  var currentForm = $(this);
@@ -102,7 +102,7 @@ SocialStream.Wall = (function(SS, $, undefined){
102
102
  .addClass('liveAdded')
103
103
  .attr('type', 'hidden')
104
104
  .attr('name', currentForm
105
- .attr('id').split('_')[1]+'[_relation_ids][]')
105
+ .attr('id').split('_')[1]+'[relation_ids][]')
106
106
  .val($(this).attr('value')));
107
107
  });
108
108
  return true;
@@ -128,7 +128,7 @@ SocialStream.Wall = (function(SS, $, undefined){
128
128
  $(this).removeAttr("readonly").val("").blur();
129
129
  });
130
130
  //New comments
131
- $('.input_new_comments').each(function() {chosen.result_deselect(0)
131
+ $('.input_new_comments').each(function() {
132
132
  $(this).removeAttr("readonly").val("");
133
133
  });
134
134
  }
@@ -6,20 +6,35 @@ class SearchController < ApplicationController
6
6
  RESULTS_SEARCH_PER_PAGE=12
7
7
  MIN_QUERY=2
8
8
  def index
9
- if params[:search_query].blank? or too_short_query
10
- @search_result = []
11
- else
12
- if params[:mode].eql? "header_search"
13
- @search_result = search :quick
14
- render :partial => "header_search"
15
- return
9
+ @search_result =
10
+ if params[:q].blank? || too_short_query
11
+ []
12
+ elsif params[:mode].eql? "header_search"
13
+ search :quick
14
+ elsif params[:type].present?
15
+ focus_search
16
16
  else
17
- if params[:focus].present?
18
- @search_result = focus_search
19
- else
20
- @search_result = search :extended
21
- end
17
+ search :extended
22
18
  end
19
+
20
+ respond_to do |format|
21
+ format.html {
22
+ if params[:mode] == "header_search"
23
+ render :partial => "header_search"
24
+ end
25
+ }
26
+
27
+ format.json {
28
+ json_obj = (
29
+ params[:type].present? ?
30
+ { params[:type].pluralize => @search_result } :
31
+ @search_result
32
+ )
33
+
34
+ render :json => json_obj
35
+ }
36
+
37
+ format.js
23
38
  end
24
39
  end
25
40
 
@@ -43,7 +58,7 @@ class SearchController < ApplicationController
43
58
  end
44
59
 
45
60
  def focus_search
46
- @search_class_sym = params[:focus].singularize.to_sym unless params[:focus].blank?
61
+ @search_class_sym = params[:type].singularize.to_sym unless params[:type].blank?
47
62
  search_class = @search_class_sym.to_s.classify.constantize
48
63
  result = ThinkingSphinx.search(get_search_query, :classes => [search_class])
49
64
  result = authorization_filter result
@@ -51,13 +66,13 @@ class SearchController < ApplicationController
51
66
  end
52
67
 
53
68
  def too_short_query
54
- bare_query = strip_tags(params[:search_query]) unless bare_query.html_safe?
69
+ bare_query = strip_tags(params[:q]) unless bare_query.html_safe?
55
70
  return bare_query.strip.size < MIN_QUERY
56
71
  end
57
72
 
58
73
  def get_search_query
59
74
  search_query = ""
60
- param = strip_tags(params[:search_query]) || ""
75
+ param = strip_tags(params[:q]) || ""
61
76
  bare_query = param unless bare_query.html_safe?
62
77
  search_query_words = bare_query.strip.split
63
78
  search_query_words.each_index do |i|
@@ -70,7 +85,6 @@ class SearchController < ApplicationController
70
85
  def authorization_filter results
71
86
  filtered_results = Array.new
72
87
  results.each do |result|
73
- puts result
74
88
  if result.is_a? SocialStream::Models::Object
75
89
  filtered_results << result if can? :read, result
76
90
  else
@@ -1,46 +1,3 @@
1
1
  module LocationHelper
2
-
3
- # Renders the location stack for your view. You can add as many stack levels as you wish.
4
- #
5
- # Usage:
6
- # <%= location(level1,leve2,level3,level4,....) %>
7
- #
8
- # Output:
9
- # base > level1 > level2 > level3 > level 4
10
- #
11
- # Default configuration:
12
- # base => "You are here" ("location.base" on config/locales)
13
- # separator => ">" ("location.separator" on config/locales)
14
- #
15
- # Styles and HTML wrapping:
16
- # partial => location/_location.html.erb
17
- #
18
- # Example:
19
- # Render a location with two leves depth:
20
- #
21
- # <%= location(link_to(leve1.name, level1.url),link_to(leve2.name, level2.url)) %>
22
- #
23
- def location(*stack)
24
-
25
- location_body = render :partial => "location/location_body", :locals=>{:stack => stack}
26
-
27
- location_div = capture do
28
- render :partial => "location/location", :locals=>{:location_body => location_body}
29
- end
30
-
31
- case request.format
32
- when Mime::JS
33
- response = <<-EOJ
34
-
35
- $('#map_location').html("#{ escape_javascript(location_div) }");
36
- EOJ
37
-
38
- response.html_safe
39
- else
40
- content_for(:location) do
41
- location_div
42
- end
43
- end
44
-
45
- end
2
+ include SocialStream::Views::Location
46
3
  end
@@ -1,7 +1,7 @@
1
1
  module SearchHelper
2
2
  def too_short_query?
3
- return true if params[:search_query].blank?
4
- bare_query = strip_tags(params[:search_query]) unless bare_query.html_safe?
3
+ return true if params[:q].blank?
4
+ bare_query = strip_tags(params[:q]) unless bare_query.html_safe?
5
5
  return bare_query.strip.size < SearchController::MIN_QUERY
6
6
  end
7
7
 
@@ -26,15 +26,15 @@ module SearchHelper
26
26
 
27
27
  def get_search_query_words
28
28
  search_query = ""
29
- bare_query = strip_tags(params[:search_query]) unless bare_query.html_safe?
29
+ bare_query = strip_tags(params[:q]) unless bare_query.html_safe?
30
30
  return bare_query.strip.split
31
31
  end
32
32
 
33
33
  def search_class(type, model_sym)
34
34
  case type
35
35
  when :selected
36
- params[:focus].present? &&
37
- params[:focus].eql?(model_sym.to_s) &&
36
+ params[:type].present? &&
37
+ params[:type].eql?(model_sym.to_s) &&
38
38
  'selected' || ''
39
39
  when :disabled
40
40
  search_results?(model_sym) &&
@@ -61,8 +61,8 @@ module SearchHelper
61
61
 
62
62
  link_to_if results,
63
63
  content_tag(:span, t("#{ model_sym }.title.other"), span_options),
64
- search_path(:focus => model_sym,
65
- :search_query => params[:search_query]),
64
+ search_path(:type => model_sym,
65
+ :q => params[:q]),
66
66
  :remote => true
67
67
  end
68
68
  end
@@ -90,8 +90,6 @@ class Activity < ActiveRecord::Base
90
90
  order("created_at desc")
91
91
  }
92
92
 
93
- before_validation :fill_relations
94
-
95
93
  after_create :increment_like_count
96
94
  after_destroy :decrement_like_count, :delete_notifications
97
95
 
@@ -325,25 +323,6 @@ class Activity < ActiveRecord::Base
325
323
 
326
324
  private
327
325
 
328
- # Before validation callback
329
- #
330
- # Fill the relations when posting to other subject's wall
331
- def fill_relations
332
- return if relation_ids.present?
333
-
334
- self.relation_ids =
335
- # FIXME: repeated in ActivityObject#_relation_ids
336
- if SocialStream.relation_model == :custom
337
- if channel.reflexive?
338
- receiver.relation_customs.map(&:id)
339
- else
340
- receiver.relation_customs.allow(channel.author, 'create', 'activity').map(&:id)
341
- end
342
- else
343
- Array.wrap Relation::Public.instance.id
344
- end
345
- end
346
-
347
326
  #
348
327
  # Get the email subject for the activity's notification
349
328
  #
@@ -19,6 +19,14 @@ class ActivityAction < ActiveRecord::Base
19
19
  where(:activity_object_id => ActivityObject.normalize_id(activity_object))
20
20
  }
21
21
 
22
+ scope :authored_or_owned, where(arel_table[:author].eq(true).
23
+ or(arel_table[:user_author].eq(true)).
24
+ or(arel_table[:owner].eq(true)))
25
+
26
+ scope :authored_or_owned_by, lambda{ |subject|
27
+ authored_or_owned.sent_by(subject)
28
+ }
29
+
22
30
  before_create :follow_by_author_and_owner
23
31
 
24
32
  private
@@ -9,7 +9,6 @@
9
9
  # Objects are added to +config/initializers/social_stream.rb+
10
10
  #
11
11
  class ActivityObject < ActiveRecord::Base
12
- attr_writer :_relation_ids
13
12
  attr_reader :_activity_parent_id
14
13
 
15
14
  # ActivityObject is a supertype of SocialStream.objects
@@ -17,6 +16,9 @@ class ActivityObject < ActiveRecord::Base
17
16
 
18
17
  acts_as_taggable
19
18
 
19
+ has_many :activity_object_audiences, :dependent => :destroy
20
+ has_many :relations, :through => :activity_object_audiences
21
+
20
22
  has_many :activity_object_activities, :dependent => :destroy
21
23
  has_many :activities, :through => :activity_object_activities
22
24
 
@@ -29,6 +31,11 @@ class ActivityObject < ActiveRecord::Base
29
31
  :source => :actor,
30
32
  :conditions => { 'activity_actions.follow' => true }
31
33
 
34
+ # Associations for indexing
35
+ has_many :author_action,
36
+ :class_name => "ActivityAction",
37
+ :conditions => { 'activity_actions.author' => true }
38
+
32
39
  has_many :activity_object_properties,
33
40
  :dependent => :destroy
34
41
  has_many :object_properties,
@@ -42,7 +49,10 @@ class ActivityObject < ActiveRecord::Base
42
49
  :through => :activity_object_holders,
43
50
  :source => :activity_object
44
51
 
52
+ before_validation :fill_relation_ids, :if => lambda { |obj| obj.object_type != "Actor" }
53
+
45
54
  validates_presence_of :object_type
55
+ validate :allowed_relations, :if => lambda { |obj| obj.object_type != "Actor" }
46
56
 
47
57
  # TODO: This is currently defined in lib/social_stream/models/object.rb
48
58
  #
@@ -110,6 +120,15 @@ class ActivityObject < ActiveRecord::Base
110
120
  class_eval code, __FILE__, __LINE__ - code.lines.count - 2
111
121
  end
112
122
 
123
+ # subject was the author, user author or owner of this {ActivityObject}?
124
+ def authored_or_owned_by?(subject)
125
+ return false if subject.blank?
126
+
127
+ received_actions.
128
+ merge(ActivityAction.authored_or_owned_by(subject)).
129
+ any?
130
+ end
131
+
113
132
  # Was the author represented when this {ActivityObject} was created?
114
133
  def represented_author?
115
134
  author_id != user_author_id
@@ -146,28 +165,7 @@ class ActivityObject < ActiveRecord::Base
146
165
  Activity.new :author => author,
147
166
  :user_author => user_author,
148
167
  :owner => owner,
149
- :relation_ids => Array(_relation_ids)
150
- end
151
-
152
- def _relation_ids
153
- @_relation_ids ||=
154
- if author.blank? || owner.blank?
155
- nil
156
- else
157
- # FIXME: repeated in Activity#fill_relations
158
- if SocialStream.relation_model == :custom
159
- if author == owner
160
- owner.relation_customs.map(&:id)
161
- else
162
- owner.
163
- relation_customs.
164
- allow(author, 'create', 'activity').
165
- map(&:id)
166
- end
167
- else
168
- Array.wrap Relation::Public.instance.id
169
- end
170
- end
168
+ :relation_ids => relation_ids
171
169
  end
172
170
 
173
171
  def _activity_parent
@@ -175,12 +173,44 @@ class ActivityObject < ActiveRecord::Base
175
173
  end
176
174
 
177
175
  def _activity_parent_id=(id)
178
- self._relation_ids = Activity.find(id).relation_ids
176
+ self.relation_ids = Activity.find(id).relation_ids
179
177
  @_activity_parent_id = id
180
178
  end
181
179
 
182
180
  private
183
181
 
182
+ def fill_relation_ids
183
+ return if relation_ids.present? || author.blank? || owner.blank?
184
+
185
+ @valid_relations = true
186
+
187
+ self.relation_ids =
188
+ if SocialStream.relation_model == :custom
189
+ owner.
190
+ relations.
191
+ allowing('read', 'activity').
192
+ map(&:id)
193
+ else
194
+ Array.wrap Relation::Public.instance.id
195
+ end
196
+ end
197
+
198
+ # validate method
199
+ #
200
+ # check relations are included in
201
+ def allowed_relations
202
+ return if @valid_relations
203
+
204
+ allowed_rels =
205
+ owner.relations.allowing('read', 'activity') +
206
+ Relation::Single.allowing('read', 'activity')
207
+
208
+ if (relation_ids - allowed_rels.map(&:id)).any?
209
+ errors.add(:relation_ids, "not allowed")
210
+ end
211
+ end
212
+
213
+
184
214
  def create_post_activity
185
215
  create_activity "post"
186
216
  end
@@ -194,7 +224,7 @@ class ActivityObject < ActiveRecord::Base
194
224
  :author_id => author_id,
195
225
  :user_author => user_author,
196
226
  :owner => owner,
197
- :relation_ids => _relation_ids,
227
+ :relation_ids => relation_ids,
198
228
  :parent_id => _activity_parent_id
199
229
 
200
230
  a.activity_objects << self
@@ -0,0 +1,8 @@
1
+ # Every {ActivityObject} ({Post}, {Comment}, etc.) is shared with one or more {Relation Relations}.
2
+ #
3
+ # Each {Relation} is equivalent to a set {Actor Actors}, which are the ones that have {Tie Ties}
4
+ # to that {Relation}, in other words, the contacts that were added to that {Relation}
5
+ class ActivityObjectAudience < ActiveRecord::Base
6
+ belongs_to :activity_object
7
+ belongs_to :relation
8
+ end
data/app/models/actor.rb CHANGED
@@ -57,6 +57,10 @@ class Actor < ActiveRecord::Base
57
57
  has_many :received_ties,
58
58
  :through => :received_contacts,
59
59
  :source => :ties
60
+
61
+ has_many :received_relations,
62
+ :through => :received_ties,
63
+ :source => :relation
60
64
 
61
65
  has_many :senders,
62
66
  :through => :received_contacts,
@@ -313,6 +317,11 @@ class Actor < ActiveRecord::Base
313
317
  map(&:id)
314
318
  end
315
319
 
320
+ # Does this {Actor} allow subject to perform action on object?
321
+ def allow?(subject, action, object)
322
+ ties_to(subject).with_permissions(action, object).any?
323
+ end
324
+
316
325
  # The {Channel} of this {Actor} to self (totally close!)
317
326
  def self_channel
318
327
  Channel.find_or_create_by_author_id_and_user_author_id_and_owner_id id, id, id
@@ -5,9 +5,7 @@ class Comment < ActiveRecord::Base
5
5
  validates_presence_of :text
6
6
 
7
7
  define_index do
8
- indexes activity_object.description
9
-
10
- has created_at
8
+ activity_object_index
11
9
  end
12
10
 
13
11
  def parent_post