stream_rails 1.0

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.
checksums.yaml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ YTMwN2JiNjM1YTNhYjQwZjBkNmNlMTc2YTM3ZjQ0NTllOTRjMjI3Yg==
5
+ data.tar.gz: !binary |-
6
+ OTY1NjJkMzc2YTJjZDI0ZjIwZTY3YjIxYTI3NWVlY2FlNTc1N2NhMg==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ MGQ3YWE0NjI5M2I0NzdlMDcyZjhmN2ExMjFjOWU4ZTY2MTc4NzBjYTkyZTI5
10
+ Nzg4ZTNiMTU2OWE3NzI0ZGM2ZmZmNDRjYTNlNzQ3MDA0MTU0ZDFmZDBmOThi
11
+ MzI5YjQ0M2U2NzljNjQ1MjQxNDI0ZmY2Yjg1MzZjNmI1YmZlZWI=
12
+ data.tar.gz: !binary |-
13
+ M2Y4ODA5YWQ0OTZjZjllNjRkYjkyZTNkMmFkYzY2NGFmYmYyZjIzZmQ1ODE4
14
+ YmE1OTk1MzAyMTNlOTUwMGM1NGNlYWE2ZjE3ODIxZDAwMTljMWU0Y2VhZWRi
15
+ NjU0ZjYxZTUwMzQ4MGRhY2UxNjE2YzM4MjEzMWJkZTc5MmNkMWY=
data/LICENSE ADDED
@@ -0,0 +1,27 @@
1
+ Copyright (c) 2014, Tommaso Barbugli
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are met:
6
+
7
+ * Redistributions of source code must retain the above copyright notice, this
8
+ list of conditions and the following disclaimer.
9
+
10
+ * Redistributions in binary form must reproduce the above copyright notice,
11
+ this list of conditions and the following disclaimer in the documentation
12
+ and/or other materials provided with the distribution.
13
+
14
+ * Neither the name of the {organization} nor the names of its
15
+ contributors may be used to endorse or promote products derived from
16
+ this software without specific prior written permission.
17
+
18
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
19
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
22
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
25
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
26
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,262 @@
1
+ Stream Rails
2
+ ============
3
+
4
+ [![image](https://secure.travis-ci.org/GetStream/stream-rails.png?branch=master)](http://travis-ci.org/GetStream/stream-rails)
5
+
6
+
7
+ This package helps you create activity streams & newsfeeds with Ruby on Rails and [GetStream.io](https://getstream.io).
8
+
9
+ ###Activity Streams & Newsfeeds
10
+
11
+ ![](https://dvqg2dogggmn6.cloudfront.net/images/mood-home.png)
12
+
13
+ What you can build:
14
+
15
+ * Activity streams such as seen on Github
16
+ * A twitter style newsfeed
17
+ * A feed like instagram/ pinterest
18
+ * Facebook style newsfeeds
19
+ * A notification system
20
+
21
+ ###Table of Contents
22
+
23
+ ### Gem installation
24
+
25
+ You can install ```stream_rails``` as you would any other gem:
26
+
27
+ ```gem install stream_rails```
28
+
29
+ or in your Gemfile:
30
+
31
+ ```gem 'stream_rails'```
32
+
33
+
34
+ ### Setup
35
+
36
+ Login with Github on getstream.io and get your ```api_key``` and ```api_secret``` from your app configuration (Dashboard screen).
37
+
38
+ Then you can add the StreamRails configuration in ```config/initializers/stream_rails.rb```
39
+
40
+ ```
41
+ require 'stream_rails'
42
+
43
+ StreamRails.configure do |config|
44
+ config.api_key = "YOUR API KEY"
45
+ config.api_secret = "YOUR API SECRET"
46
+ end
47
+ ```
48
+
49
+ ### Model configuration
50
+
51
+ Include StreamRails::Activity and add as_activity to the model you want to integrate with your feeds.
52
+
53
+ ```ruby
54
+ class Pin < ActiveRecord::Base
55
+ belongs_to :user
56
+ belongs_to :item
57
+
58
+ validates :item, presence: true
59
+ validates :user, presence: true
60
+
61
+ include StreamRails::Activity
62
+ as_activity
63
+ end
64
+ ```
65
+ Everytime a Pin is created it will be stored in the feed of the user that created it, and when a Pin instance is deleted than it will get removed as well.
66
+
67
+ ####Activity fields
68
+
69
+ Models are stored in feeds as activities. An activity is composed of at least the following data fields: **actor**, **verb**, **object**, **time**. You can also add more custom data if needed.
70
+
71
+ **object** is a reference to the model instance itself
72
+ **actor** is a reference to the user attribute of the instance
73
+ **verb** is a string representation of the class name
74
+
75
+ In order to work out-of-the-box, the Activity class makes makes few assumptions:
76
+
77
+ 1. the Model class belongs to a user
78
+ 2. the model table has timestamp columns (created_at is required)
79
+
80
+ You can change this behaviour by overriding ```#activity_actor```.
81
+
82
+ Below shows an example how to change your class if the model belongs to an author instead of to a user.
83
+
84
+ ```ruby
85
+ class Pin < ActiveRecord::Base
86
+ belongs_to :author
87
+ belongs_to :item
88
+
89
+ include StreamRails::Activity
90
+ as_activity
91
+
92
+ def activity_actor
93
+ self.author
94
+ end
95
+
96
+ end
97
+ ```
98
+
99
+ ####Activity extra data
100
+
101
+ Often you'll want to store more data than just the basic fields. You achieve this by implementing ```#activity_extra_data``` in your model.
102
+
103
+
104
+ ```ruby
105
+ class Pin < ActiveRecord::Base
106
+ belongs_to :author
107
+ belongs_to :item
108
+
109
+ include StreamRails::Activity
110
+ as_activity
111
+
112
+ def activity_extra_data
113
+ {'is_retweet' => self.is_retweet}
114
+ end
115
+
116
+ end
117
+ ```
118
+
119
+ ###Feed manager
120
+
121
+ ```stream_rails``` comes with a Feed Manager class that helps with all common feed operations. You can get an instance of the manager with ```StreamRails.feed_manager```.
122
+
123
+ ```ruby
124
+ feed = StreamRails.feed_manager.get_user_feed(current_user.id)
125
+ ```
126
+
127
+ ####Feeds bundled with feed_manager
128
+
129
+ To get you started the manager has 4 feeds pre configured. You can add more feeds if your application needs it.
130
+ Feeds are divided in three categories.
131
+
132
+ #####User feed:
133
+ The user feed stores all activities for a user. Think of it as your personal Facebook page. You can easily get this feed from the manager.
134
+ ```ruby
135
+ feed = StreamRails.feed_manager.get_user_feed(current_user.id)
136
+ ```
137
+
138
+ #####News feeds:
139
+ The news feeds store the activities from the people you follow.
140
+ There is both a flat newsfeed (similar to twitter) and an aggregated newsfeed (like facebook).
141
+
142
+ ```php
143
+ feed = StreamRails.feed_manager.get_news_feeds(current_user.id)[:flat]
144
+ aggregated_feed = StreamRails.feed_manager.get_news_feeds(current_user.id)[:aggregated]
145
+ ```
146
+
147
+ #####Notification feed:
148
+ The notification feed can be used to build notification functionality.
149
+
150
+ ![Notification feed](http://feedly.readthedocs.org/en/latest/_images/fb_notification_system.png)
151
+
152
+ Below we show an example of how you can read the notification feed.
153
+ ```ruby
154
+ notification_feed = StreamRails.feed_manager.get_notification_feed(current_user.id)
155
+
156
+ ```
157
+ By default the notification feed will be empty. You can specify which users to notify when your model gets created. In the case of a retweet you probably want to notify the user of the parent tweet.
158
+
159
+ ```ruby
160
+ class Pin < ActiveRecord::Base
161
+ belongs_to :author
162
+ belongs_to :item
163
+
164
+ include StreamRails::Activity
165
+ as_activity
166
+
167
+ def activity_notify
168
+ if self.is_retweet
169
+ [feed_manager.get_notification_feed(self.parent.user_id)]
170
+ end
171
+ end
172
+
173
+ end
174
+ ```
175
+
176
+ Another example would be following a user. You would commonly want to notify the user which is being followed.
177
+
178
+ ```ruby
179
+ class Follow < ActiveRecord::Base
180
+ belongs_to :user
181
+ belongs_to :target
182
+
183
+ validates :target_id, presence: true
184
+ validates :user, presence: true
185
+
186
+ include StreamRails::Activity
187
+ as_activity
188
+
189
+ def activity_notify
190
+ [feed_manager.get_notification_feed(self.target_id)]
191
+ end
192
+
193
+ end
194
+ ```
195
+
196
+ ####Follow a feed
197
+ The create the newsfeeds you need to notify the system about follow relationships. The manager comes with APIs to let a user's news feeds follow another user's feed. This code lets the current user's flat and aggregated feeds follow the target_user's personal feed.
198
+
199
+ ```
200
+ StreamRails.feed_manager.follow_user(user_id, target_id)
201
+ ```
202
+
203
+ ### Showing the newsfeed
204
+
205
+ ####Activity enrichment
206
+
207
+ When you read data from feeds, a pin activity will look like this:
208
+
209
+ ```json
210
+ {"actor": "User:1", "verb": "like", "object": "Pin:42"}
211
+ ```
212
+
213
+ This is far from ready for usage in your template. We call the process of loading the references from the database enrichment. An example is shown below:
214
+
215
+ ```ruby
216
+ enricher = StreamRails::Enrich.new
217
+
218
+ feed = StreamRails.feed_manager.get_news_feeds(current_user.id)[:flat]
219
+ results = feed.get()['results']
220
+ activities = enricher.enrich_activities(results)
221
+ ```
222
+
223
+ ####Templating
224
+
225
+ Now that you've enriched the activities you can render them in a view.
226
+ For convenience we includes a basic view:
227
+
228
+ ```
229
+ <div class="container">
230
+ <div class="container-pins">
231
+ <% for activity in @activities %>
232
+ <%= render_activity activity %>
233
+ <% end %>
234
+ </div>
235
+ </div>
236
+ ```
237
+
238
+ The ```render_activity``` view helper will render the activity by picking the partial ```activity/_pin``` for a pin activity, ```aggregated/_follow``` for an aggregated activity with verb follow.
239
+
240
+ The helper will automatically send ```activity``` to the local scope of the partial; additional parameters can be send as well as use different layouts, and prefix the name
241
+
242
+
243
+ eg. renders the activity partial using the ```small_activity``` layout.
244
+
245
+ ```
246
+ <%= render_activity activity, :layout => "small_activity" %>
247
+ ```
248
+
249
+
250
+ eg. prefixes the name of the template with "notification_"
251
+
252
+ ```
253
+ <%= render_activity activity, :prefix => "notification_" %>
254
+ ```
255
+
256
+ eg. adds the extra_var to the partial scope
257
+
258
+ ```
259
+ <%= render_activity activity, :locals => {:extra_var => 42} %>
260
+ ```
261
+
262
+
@@ -0,0 +1,47 @@
1
+ require 'active_support'
2
+ require 'action_view'
3
+ require 'stream'
4
+ require 'stream_rails/enrich'
5
+ require 'stream_rails/logger'
6
+
7
+ module StreamRails
8
+ extend ActiveSupport::Autoload
9
+
10
+ autoload :Activity
11
+ autoload :Config
12
+ autoload :FeedManager, 'stream_rails/feed_manager'
13
+ autoload :Renderable
14
+ autoload :VERSION
15
+
16
+ def self.client
17
+ Stream::Client.new(self.config.api_key, self.config.api_secret)
18
+ end
19
+
20
+ # Returns StreamRails's configuration object.
21
+ def self.config
22
+ @config ||= StreamRails::Config.new
23
+ end
24
+
25
+ # Returns StreamRails's configuration object.
26
+ def self.feed_manager
27
+ @feed_manager ||= StreamRails::FeedManager.new(self.client, self.config.feed_configs)
28
+ end
29
+
30
+ # Lets you set global configuration options.
31
+ #
32
+ # All available options and their defaults are in the example below:
33
+ # @example Initializer for Rails
34
+ # StreamRails.configure do |config|
35
+ # config.api_key = "key"
36
+ # config.api_secret = "secret"
37
+ # config.api_site_id = "42"
38
+ # config.enabled = true
39
+ # end
40
+ def self.configure(&block)
41
+ yield(config) if block_given?
42
+ end
43
+
44
+ end
45
+
46
+ require 'stream_rails/utils/view_helpers'
47
+ require 'stream_rails/railtie' if defined?(Rails)
@@ -0,0 +1,93 @@
1
+ require 'active_record'
2
+ require 'stream_rails/sync_policies'
3
+
4
+ module StreamRails
5
+
6
+ class << self
7
+ def create_reference(record)
8
+ if record.is_a? ActiveRecord::Base
9
+ "#{record.class.model_name}:#{record.id}"
10
+ else
11
+ record.to_s unless record.nil?
12
+ end
13
+ end
14
+ end
15
+
16
+ module ClassMethods
17
+
18
+ def as_activity(opts = {})
19
+ default_opts = {:track_deletes => true, :sync_policy => nil}
20
+ options = default_opts.merge(opts)
21
+ if options[:sync_policy].nil?
22
+ include StreamRails::SyncPolicy::SyncCreate
23
+ if options[:track_deletes]
24
+ include StreamRails::SyncPolicy::SyncDestroy
25
+ end
26
+ else
27
+ include options[:sync_policy]
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ module Activity
34
+
35
+ def self.included base
36
+ base.extend ClassMethods
37
+ end
38
+
39
+ def activity_owner_id
40
+ self.user_id
41
+ end
42
+
43
+ def activity_actor
44
+ self.user
45
+ end
46
+
47
+ def activity_owner_feed
48
+ 'user'
49
+ end
50
+
51
+ def activity_actor_id
52
+ StreamRails.create_reference(self.activity_actor)
53
+ end
54
+
55
+ def activity_verb
56
+ self.class.model_name.to_s
57
+ end
58
+
59
+ def activity_object_id
60
+ StreamRails.create_reference(self)
61
+ end
62
+
63
+ def activity_foreign_id
64
+ StreamRails.create_reference(self)
65
+ end
66
+
67
+ def activity_notify
68
+ end
69
+
70
+ def activity_extra_data
71
+ {}
72
+ end
73
+
74
+ def activity_time
75
+ self.created_at
76
+ end
77
+
78
+ def create_activity
79
+ activity = {
80
+ :actor => self.activity_actor_id,
81
+ :verb => self.activity_verb,
82
+ :object => self.activity_object_id,
83
+ :foreign_id => self.activity_foreign_id,
84
+ :time => self.activity_time,
85
+ }
86
+ if !self.activity_notify.nil?
87
+ activity[:to] = self.activity_notify.map{|f| f.feed_id}
88
+ end
89
+ activity.merge(self.activity_extra_data)
90
+ end
91
+
92
+ end
93
+ end
@@ -0,0 +1,27 @@
1
+ module StreamRails
2
+ # Class used to initialize configuration object.
3
+ class Config
4
+ attr_accessor :api_key
5
+ attr_accessor :api_secret
6
+ attr_accessor :api_site_id
7
+ attr_accessor :enabled
8
+
9
+ attr_accessor :news_feeds
10
+ attr_accessor :notification_feed
11
+ attr_accessor :user_feed
12
+
13
+ def initialize
14
+ @enabled = true
15
+ @news_feeds = {:flat=>'flat', :aggregated=>'aggregated'}
16
+ @notification_feed = 'notification'
17
+ @user_feed = 'user'
18
+ end
19
+
20
+ def feed_configs
21
+ {:news_feeds=>@news_feeds,
22
+ :notification_feed=>@notification_feed,
23
+ :user_feed=>@user_feed}
24
+ end
25
+
26
+ end
27
+ end
@@ -0,0 +1,104 @@
1
+ require 'active_record'
2
+
3
+ module StreamRails
4
+
5
+ class ActivityResult < Hash
6
+ attr_accessor :enriched
7
+ attr_reader :failed_to_enrich
8
+
9
+ def initialize
10
+ @failed_to_enrich = Hash.new
11
+ super
12
+ end
13
+
14
+ def from_activity(h)
15
+ self.merge(h)
16
+ end
17
+
18
+ def enriched?
19
+ @failed_to_enrich.keys.length == 0
20
+ end
21
+
22
+ def not_enriched_fields
23
+ @failed_to_enrich.keys
24
+ end
25
+
26
+ def track_not_enriched_field(field, value = nil)
27
+ @failed_to_enrich[field] = value
28
+ end
29
+
30
+ end
31
+
32
+ class Enrich
33
+
34
+ def initialize(fields = nil)
35
+ @fields = fields || [:actor, :object]
36
+ end
37
+
38
+ def model_field?(field_value)
39
+ bits = field_value.split(':')
40
+ if bits.length < 2
41
+ return false
42
+ end
43
+ begin
44
+ bits[0].classify.constantize
45
+ rescue NameError
46
+ return false
47
+ else
48
+ return true
49
+ end
50
+ end
51
+
52
+ def enrich_activities(activities)
53
+ references = self.collect_references(activities)
54
+ objects = self.retrieve_objects(references)
55
+ self.inject_objects(activities, objects)
56
+ end
57
+
58
+ def enrich_aggregated_activities(aggregated_activities)
59
+ references = Hash.new
60
+ aggregated_activities.each do |aggregated|
61
+ refs = self.collect_references(aggregated['activities'])
62
+ references = references.merge(refs){|key, v1, v2| v1.merge(v2)}
63
+ end
64
+ objects = self.retrieve_objects(references)
65
+ aggregated_activities.each do |aggregated|
66
+ aggregated['activities'] = self.inject_objects(aggregated['activities'], objects)
67
+ end
68
+ aggregated_activities.map {|a| ActivityResult.new().from_activity(a)}
69
+ end
70
+
71
+ def collect_references(activities)
72
+ model_refs = Hash.new{ |h,k| h[k] = Hash.new}
73
+ activities.each do |activity|
74
+ activity.select{|k,v| @fields.include? k.to_sym}.each do |field, value|
75
+ next unless self.model_field?(value)
76
+ model, id = value.split(':')
77
+ model_refs[model][id] = 0
78
+ end
79
+ end
80
+ model_refs
81
+ end
82
+
83
+ def retrieve_objects(references)
84
+ Hash[references.map{ |model, ids| [model, Hash[model.classify.constantize.where(id: ids.keys).map {|i| [i.id.to_s, i]}] ] }]
85
+ end
86
+
87
+ def inject_objects(activities, objects)
88
+ activities = activities.map {|a| ActivityResult.new().from_activity(a)}
89
+ activities.each do |activity|
90
+ activity.select{|k,v| @fields.include? k.to_sym}.each do |field, value|
91
+ next unless self.model_field?(value)
92
+ model, id = value.split(':')
93
+ activity[field] = objects[model][id] || value
94
+ if objects[model][id].nil?
95
+ activity.track_not_enriched_field(field, value)
96
+ end
97
+ end
98
+ end
99
+ activities
100
+ end
101
+
102
+ end
103
+
104
+ end
@@ -0,0 +1,61 @@
1
+ module StreamRails
2
+ # Class used to manage feeds
3
+ class FeedManager
4
+ attr_reader :client
5
+
6
+ def initialize(client, opts={})
7
+ @client = client
8
+ @user_feed = opts[:user_feed]
9
+ @news_feeds = opts[:news_feeds]
10
+ @notification_feed = opts[:notification_feed]
11
+ end
12
+
13
+ def get_user_feed(user_id)
14
+ @client.feed("#{@user_feed}:#{user_id}")
15
+ end
16
+
17
+ def get_news_feeds(user_id)
18
+ Hash[@news_feeds.map{ |k,v| [k, self.get_feed(k, user_id)] }]
19
+ end
20
+
21
+ def get_notification_feed(user_id)
22
+ @client.feed("#{@notification_feed}:#{user_id}")
23
+ end
24
+
25
+ def get_feed(feed_type, user_id)
26
+ @client.feed("#{feed_type}:#{user_id}")
27
+ end
28
+
29
+ def follow_user(user_id, target_id)
30
+ target_feed = self.get_user_feed(target_id)
31
+ @news_feeds.each do |_, feed|
32
+ news_feed = self.get_feed(feed, user_id)
33
+ news_feed.follow(target_feed.feed_id)
34
+ end
35
+ end
36
+
37
+ def unfollow_user(user_id, target_id)
38
+ target_feed = self.get_user_feed(target_id)
39
+ @news_feeds.each do |_, feed|
40
+ news_feed = self.get_feed(feed, user_id)
41
+ news_feed.unfollow(target_feed.feed_id)
42
+ end
43
+ end
44
+
45
+ def get_owner_feed(instance)
46
+ self.get_feed(instance.activity_owner_feed, instance.activity_owner_id)
47
+ end
48
+
49
+ def created_activity(instance)
50
+ activity = instance.create_activity
51
+ feed = self.get_owner_feed(instance)
52
+ feed.add_activity(activity)
53
+ end
54
+
55
+ def destroyed_activity(instance)
56
+ feed = self.get_owner_feed(instance)
57
+ feed.remove(instance.activity_foreign_id, foreign_id=true)
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,6 @@
1
+ module StreamRails
2
+ class << self
3
+ attr_accessor :logger
4
+ end
5
+ self.logger = Logger.new(STDOUT)
6
+ end
@@ -0,0 +1,7 @@
1
+ module StreamRails
2
+ class Railtie < ::Rails::Railtie
3
+ initializer 'stream_rails.setup_logging' do
4
+ StreamRails.logger = Rails.logger
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,66 @@
1
+ module StreamRails
2
+ # Provides logic for rendering activities. (different templates per activity verb).
3
+ module Renderable
4
+
5
+ class << self
6
+
7
+ def render(activity, context, params = {})
8
+ aggregated = activity.has_key? 'activities'
9
+ partial = partial_path(activity, aggregated, *params.values_at(:prefix, :partial, :partial_root))
10
+ layout = layout_path(*params.values_at(:layout, :layout_root))
11
+ locals = prepare_locals(activity, params)
12
+ params = params.merge(partial: partial, locals: locals, layout: layout)
13
+ if aggregated
14
+ render_aggregated(activity, context, params)
15
+ else
16
+ render_simple(activity, context, params)
17
+ end
18
+ end
19
+
20
+ def render_simple(activity, context, params)
21
+ if activity.enriched?
22
+ context.render params
23
+ else
24
+ StreamRails.logger.warn "trying to display a non enriched activity #{activity.inspect} #{activity.failed_to_enrich}"
25
+ return ''
26
+ end
27
+ end
28
+
29
+ def render_aggregated(activity, context, params)
30
+ if !activity['activities'].map {|a| !a.enriched?}.all?
31
+ context.render params
32
+ else
33
+ first_activity = activity['activities'][0]
34
+ StreamRails.logger.warn "trying to display a non enriched activity #{first_activity.inspect} #{first_activity.failed_to_enrich}"
35
+ return ''
36
+ end
37
+ end
38
+
39
+ def layout_path(path = nil, root = nil)
40
+ path.nil? and return
41
+ root ||= 'layouts'
42
+ select_path path, root
43
+ end
44
+
45
+ def partial_path(activity, aggregated, prefix = '', path = nil, root = nil)
46
+ root ||= (if aggregated then 'aggregated_activity' else 'activity' end)
47
+ path ||= "#{activity['verb']}".downcase
48
+ path = "#{prefix}_#{path}" if prefix
49
+ select_path path, root
50
+ end
51
+
52
+ def prepare_locals(activity, params)
53
+ locals = params.delete(:locals) || Hash.new
54
+ locals.merge\
55
+ activity: activity,
56
+ parameters: params
57
+ end
58
+
59
+ private
60
+ def select_path path, root
61
+ [root, path].map(&:to_s).join('/')
62
+ end
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,30 @@
1
+ module StreamRails
2
+
3
+ module SyncPolicy
4
+
5
+ module SyncCreate
6
+
7
+ def self.included(base)
8
+ base.after_commit :add_to_feed, on: [:create]
9
+ end
10
+
11
+ private
12
+ def add_to_feed
13
+ StreamRails.feed_manager.created_activity(self)
14
+ end
15
+ end
16
+
17
+ module SyncDestroy
18
+
19
+ def self.included(base)
20
+ base.after_commit :remove_from_feed, on: [:destroy]
21
+ end
22
+
23
+ private
24
+ def remove_from_feed
25
+ StreamRails.feed_manager.destroyed_activity(self)
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,15 @@
1
+ # Provides a shortcut from views to the rendering method.
2
+ module StreamRails
3
+ # Module extending ActionView::Base and adding `render_activity` helper.
4
+ module ViewHelpers
5
+ # View helper for rendering an activity
6
+ def render_activity activity, options = {}
7
+ Renderable.render(activity, self, options)
8
+ end
9
+ # View helper for rendering many activities
10
+ def render_activities activities, options = {}
11
+ activities.map {|activity| Renderable.render(activity, self, options.dup) }.join.html_safe
12
+ end
13
+ end
14
+ ActionView::Base.class_eval { include ViewHelpers }
15
+ end
@@ -0,0 +1,3 @@
1
+ module StreamRails
2
+ VERSION = '1.0'
3
+ end
metadata ADDED
@@ -0,0 +1,185 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: stream_rails
3
+ version: !ruby/object:Gem::Version
4
+ version: '1.0'
5
+ platform: ruby
6
+ authors:
7
+ - Tommaso Barbugli
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-24 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: actionpack
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ! '>='
18
+ - !ruby/object:Gem::Version
19
+ version: 3.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ! '>='
25
+ - !ruby/object:Gem::Version
26
+ version: 3.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ! '>='
32
+ - !ruby/object:Gem::Version
33
+ version: 3.0.0
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ! '>='
39
+ - !ruby/object:Gem::Version
40
+ version: 3.0.0
41
+ - !ruby/object:Gem::Dependency
42
+ name: stream-ruby
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: 1.0.2
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: 1.0.2
55
+ - !ruby/object:Gem::Dependency
56
+ name: activerecord
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 3.0.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ! '>='
67
+ - !ruby/object:Gem::Version
68
+ version: 3.0.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ! '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ! '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fakeweb
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ! '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ! '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sqlite3
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ! '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ! '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: '2.10'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: '2.10'
125
+ - !ruby/object:Gem::Dependency
126
+ name: simplecov
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ~>
130
+ - !ruby/object:Gem::Version
131
+ version: 0.7.1
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ~>
137
+ - !ruby/object:Gem::Version
138
+ version: 0.7.1
139
+ description:
140
+ email: tbarbugli@gmail.com
141
+ executables: []
142
+ extensions: []
143
+ extra_rdoc_files:
144
+ - README.md
145
+ - LICENSE
146
+ files:
147
+ - LICENSE
148
+ - README.md
149
+ - lib/stream_rails.rb
150
+ - lib/stream_rails/activity.rb
151
+ - lib/stream_rails/config.rb
152
+ - lib/stream_rails/enrich.rb
153
+ - lib/stream_rails/feed_manager.rb
154
+ - lib/stream_rails/logger.rb
155
+ - lib/stream_rails/railtie.rb
156
+ - lib/stream_rails/renderable.rb
157
+ - lib/stream_rails/sync_policies.rb
158
+ - lib/stream_rails/utils/view_helpers.rb
159
+ - lib/stream_rails/version.rb
160
+ homepage: http://github.com/tbarbugli/stream-ruby
161
+ licenses:
162
+ - Apache-2.0
163
+ metadata: {}
164
+ post_install_message:
165
+ rdoc_options: []
166
+ require_paths:
167
+ - lib
168
+ required_ruby_version: !ruby/object:Gem::Requirement
169
+ requirements:
170
+ - - ! '>='
171
+ - !ruby/object:Gem::Version
172
+ version: 1.9.2
173
+ required_rubygems_version: !ruby/object:Gem::Requirement
174
+ requirements:
175
+ - - ! '>='
176
+ - !ruby/object:Gem::Version
177
+ version: '0'
178
+ requirements: []
179
+ rubyforge_project:
180
+ rubygems_version: 2.2.2
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: A gem that provides a client interface for getstream.io
184
+ test_files: []
185
+ has_rdoc: true