activity_stream 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
data/Gemfile CHANGED
@@ -3,4 +3,5 @@ source "http://rubygems.org"
3
3
  # Specify your gem's dependencies in activity_stream.gemspec
4
4
  gemspec
5
5
 
6
- gem "sqlite3-ruby", :require => "sqlite3"
6
+ gem "sqlite3-ruby", :require => "sqlite3"
7
+ gem "ruby-debug"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- activity_stream (0.0.1)
4
+ activity_stream (0.0.3)
5
5
 
6
6
  GEM
7
7
  remote: http://rubygems.org/
@@ -28,10 +28,12 @@ GEM
28
28
  celerity (0.8.2)
29
29
  childprocess (0.1.3)
30
30
  ffi (~> 0.6.3)
31
+ columnize (0.3.1)
31
32
  culerity (0.2.12)
32
33
  ffi (0.6.3)
33
34
  rake (>= 0.8.7)
34
35
  json_pure (1.4.6)
36
+ linecache (0.43)
35
37
  mime-types (1.16)
36
38
  nokogiri (1.4.3.1)
37
39
  rack (1.1.0)
@@ -49,6 +51,11 @@ GEM
49
51
  rspec-rails (1.3.3)
50
52
  rack (>= 1.0.0)
51
53
  rspec (= 1.3.1)
54
+ ruby-debug (0.10.3)
55
+ columnize (>= 0.1)
56
+ ruby-debug-base (~> 0.10.3.0)
57
+ ruby-debug-base (0.10.3)
58
+ linecache (>= 0.3)
52
59
  rubyzip (0.9.4)
53
60
  selenium-webdriver (0.0.29)
54
61
  childprocess (>= 0.0.7)
@@ -67,4 +74,5 @@ DEPENDENCIES
67
74
  capybara
68
75
  rails (~> 2.3.10)
69
76
  rspec-rails (~> 1.3.0)
77
+ ruby-debug
70
78
  sqlite3-ruby
@@ -0,0 +1,77 @@
1
+ module ActivityStream
2
+
3
+ class Activity < ActiveRecord::Base
4
+
5
+ belongs_to :actor, :polymorphic => true
6
+
7
+ before_save :ensure_occurred_at_set
8
+
9
+ # @param name [Symbol] (see ActivityStream::Definition#new)
10
+ # @return [ActivityStream::Definition] the new definitions
11
+ #
12
+ def self.define(name, &block)
13
+ definition = ActivityStream::DefinitionProxy.new(name)
14
+ definition.instance_eval(&block)
15
+ ActivityStream::Definition.register(definition)
16
+ end
17
+
18
+ def self.new_with_name_and_metadata(name, metadata = {})
19
+ new(:kind => name.to_s, :metadata => metadata)
20
+ end
21
+
22
+ named_scope :in_reverse_chronological_order, :order => 'occurred_at DESC'
23
+
24
+ named_scope :in_chronological_order, :order => 'occurred_at ASC'
25
+
26
+ # @param actors [Array] An array of [ActorClass, actor_id] sets
27
+ # or [ActorClass, [actor_id, actor_id, actor_id...]
28
+ #
29
+ named_scope :by_actors, lambda { |actors|
30
+ if actors.first.is_a?(Array)
31
+ conditions = actors.map do |(actor_type, actor_id)|
32
+ %{("activities"."actor_id" = #{actor_id.to_param} AND "activities"."actor_type" = '#{actor_type.to_param}')}
33
+ end
34
+ {:conditions => conditions.join(' OR ') }
35
+ elsif actors.first.is_a?(Class)
36
+ {:conditions => {:actor_id => actors.last, :actor_type => actors.first.to_param}}
37
+ else
38
+ {} # Not sure what to do here.
39
+ end
40
+ }
41
+
42
+ serialize :metadata, ActivityStream::Metadata
43
+
44
+ delegate :template, :icon_path, :to => :definition
45
+
46
+ def metadata
47
+ self[:metadata] ||= ActivityStream::Metadata.new(self[:kind])
48
+ end
49
+
50
+ def metadata=(new_data = {})
51
+ new_data = new_data.presence || {}
52
+ occurred_at = new_data.delete(:occurred_at)
53
+ new_data.each do |key, value|
54
+ metadata.store(key, value)
55
+ end
56
+ end
57
+
58
+ def definition
59
+ ActivityStream::Definition.find_by_name(self[:kind])
60
+ end
61
+
62
+ def kind=(val)
63
+ write_attribute(:kind, val.to_s)
64
+ end
65
+
66
+ def kind
67
+ read_attribute(:kind).to_sym
68
+ end
69
+
70
+ private
71
+
72
+ def ensure_occurred_at_set
73
+ self.occurred_at ||= Time.now
74
+ end
75
+
76
+ end
77
+ end
@@ -6,8 +6,8 @@ class ActivityStreamGenerator < Rails::Generator::Base
6
6
  def manifest
7
7
  record do |m|
8
8
 
9
- m.directory(File.join('app','models','activities'))
10
- m.template('example_activity.rb', 'app/models/activities/example_activity.rb')
9
+ m.directory(File.join('config','initializers'))
10
+ m.template('initializer.rb', 'config/initializers/activity_stream.rb')
11
11
 
12
12
  user_model = 'app/models/user.rb'
13
13
  if File.exists?(user_model)
@@ -25,23 +25,25 @@ module ActivityStream
25
25
  base.extend(ClassMethods)
26
26
  base.class_eval do
27
27
  has_many :activities, :as => :actor
28
- activity_stream(:all, :actors => :activity_stream_actors)
28
+ activity_stream(:default, :actors => :followed_actors)
29
29
  end
30
30
  end
31
31
 
32
32
  # @param name [Symbol] An activity identifer defined by Activity.define
33
- def create_activity(name)
34
-
33
+ def publish_activity(name, metadata = {})
34
+ activity = ::Activity.new_with_name_and_metadata(name, metadata)
35
+ self.activities << activity
36
+ activity
35
37
  end
36
38
 
37
39
  # Creates and returns an ActivityStream::Stream for the predefined
38
40
  # list of actors.
39
41
  # @param name [Symbol] The key of a defined activity stream
40
- def activity_stream(name)
42
+ def activity_stream(name = :default)
41
43
  ActivityStream::Stream.new(name, self, self.class.defined_streams[name])
42
44
  end
43
-
44
- def activity_stream_actors
45
+ # Override this to change the default actors
46
+ def followed_actors
45
47
  self.class.all.map{|actor| [actor.class, actor.id]}
46
48
  end
47
49
 
@@ -2,51 +2,35 @@ require 'active_support/core_ext/array/extract_options'
2
2
 
3
3
  module ActivityStream
4
4
 
5
- def definitions
6
- @@definitions ||= []
7
- end
8
-
5
+ # Defines a type of activity. You don't actually interact with this class directly.
9
6
  class Definition
10
7
 
11
- attr_reader :name
12
-
13
- # @param name [Symbol] the unique name of the Activity
14
- def initialize(name)
15
- @name = name.to_sym
16
- @metadata = {}
17
- end
18
-
19
- # @param filename [String] the icon's name inside of the
20
- # `public/images/activity_stream/icons` directory
21
- def icon(filename)
22
- @icon = filename
23
- end
24
-
25
- # @overload metadata
26
- # @return [Hash] A hash of defined metadata
27
- # @overload metadata(name, opts = {})
28
- # @param name [Symbol] the unique name for the metadata attribute
29
- # @option opts :default The default value for that metadata
30
- def metadata(*args)
31
- if args.empty?
32
- @metadata
33
- else
34
- opts = args.extract_options!
35
- @metadata[args.first.to_sym] = opts
36
- end
8
+ attr_reader :name, :icon, :metadata, :template
9
+
10
+ # @param proxy [ActivityStream::DefinitionProxy] A constructed proxy that
11
+ # will set the values for this Definition
12
+ def initialize(proxy)
13
+ @name = proxy[:name]
14
+ @metadata = proxy[:metadata] || {}
15
+ @template = proxy[:template] || 'activity'
16
+ @icon = proxy[:icon] || 'activity_icon.png'
37
17
  end
38
18
 
39
- #
40
- def template
41
- 'activity'
19
+ def icon_path
20
+ 'activity_stream/icons/%s' % self.icon
42
21
  end
43
-
22
+
44
23
  class << self
45
24
  # @param definition [Definition] The definition to be made available
46
25
  # @return [Definition] Returns the registered definition
47
26
  def register(definition)
48
- self.all << definition
49
- definition
27
+ definition = new(definition) if definition.is_a? DefinitionProxy
28
+ if definition.is_a? Definition
29
+ self.all << definition
30
+ definition
31
+ else
32
+ false
33
+ end
50
34
  end
51
35
 
52
36
  # List of registered definitions
@@ -58,15 +42,15 @@ module ActivityStream
58
42
  # end
59
43
  # ActivityStream::Definition.all
60
44
  def all
61
- @@definitions ||= []
45
+ @definitions ||= []
62
46
  end
63
47
 
64
48
  # Find a registered definition by its symbolic name
65
49
  # @param name [Symbol] the name to find
66
50
  # @return [ActivityStream::Definition]
67
51
  def find_by_name(name)
68
- unless definition = all.find{|d| d.name == name.to_sym}
69
- raise ActivityStream::UndefinedActivity, "Could not find a definition for `#{name}`"
52
+ unless definition = all.find{|definition| definition.name == name.to_sym}
53
+ raise UndefinedActivity, "Could not find a definition for `#{name}`"
70
54
  else
71
55
  definition
72
56
  end
@@ -0,0 +1,49 @@
1
+ module ActivityStream
2
+
3
+ # Provides a DSL to define an Activity. It is used in Activity.define
4
+ class DefinitionProxy
5
+
6
+ # @param name [Symbol] The name of the activity
7
+ def initialize(name)
8
+ @attributes = {
9
+ :name => name.to_sym,
10
+ :icon => 'activity_icon.png',
11
+ :metadata => {},
12
+ :template => 'activity'
13
+ }
14
+ end
15
+
16
+ # Define the activity's icon
17
+ # @param filename [String] the icon's name inside of the
18
+ # `public/images/activity_stream/icons` directory
19
+ def icon(filename)
20
+ @attributes.store(:icon, filename)
21
+ end
22
+
23
+ # Define metadata for the activity
24
+ # @param name [Symbol] the unique name for the metadata attribute
25
+ # @option opts :default The default value for that metadata
26
+ # @option opts [Boolean] :required (false) Mark this metadata as required
27
+ def metadata(*args)
28
+ opts = args.extract_options!
29
+ args.each do |name|
30
+ self.add_metadata(name, opts)
31
+ end
32
+ end
33
+
34
+ # Define a custom template
35
+ # @param name [String] the name of the template for this Activity.
36
+ # Should be located in `app/views/activities/*`
37
+ def template(template_name)
38
+ @attributes.store(template_name)
39
+ end
40
+
41
+ delegate :[], :to => :@attributes
42
+
43
+ def add_metadata(name, opts = {})
44
+ @attributes[:metadata][name] = opts
45
+ end
46
+
47
+ end
48
+
49
+ end
@@ -1,15 +1,56 @@
1
+ require 'active_support/core_ext/module/delegation'
2
+ require 'active_support/core_ext/object/singleton_class'
3
+
1
4
  module ActivityStream
2
5
 
6
+ # Storage for an activities metadata.
3
7
  class Metadata
4
8
 
9
+ attr_reader :data
10
+
5
11
  def initialize(definition_name)
6
-
12
+ @definition_name = definition_name
13
+ @data = {}
14
+ end
15
+
16
+ delegate :merge, :store, :to => :data
17
+
18
+ def definition
19
+ @definition ||= Definition.find_by_name(@definition_name)
20
+ end
21
+
22
+ def to_yaml_properties
23
+ ["@data","@definition_name"]
24
+ end
25
+
26
+ def valid?
27
+ # TODO: Check definition for required keys, and loop through the
28
+ # values in @data to see what is missing
29
+ true
30
+ end
31
+
32
+ def method_missing(method_name)
33
+ case method_name
34
+ when *definition.metadata.keys
35
+ @data[method_name]
36
+ else
37
+ super
38
+ end
7
39
  end
40
+
41
+ private
8
42
 
9
- def store
10
- @store ||= {}
43
+ def define_metadata_method(name)
44
+ self.singleton_class.class_eval do
45
+ define_method(name) do
46
+ self.data[name]
47
+ end
48
+ define_method(:"#{name.to_s}=") do |value|
49
+ self.data[name]= value
50
+ end
51
+ end
11
52
  end
12
53
 
13
54
  end
14
55
 
15
- end
56
+ end
@@ -12,11 +12,13 @@ module ActivityStream
12
12
  @collection = initialize_collection(opts[:actors])
13
13
  end
14
14
 
15
+ # @param reload [Boolean] Return to the database for new activities
16
+ # @return the activities for the collection of actors
15
17
  def activities(reload = false)
16
18
  if @activities && !reload
17
19
  @activities
18
20
  else
19
- @activities = Activity.by_actors(@collection)
21
+ @activities = ::Activity.by_actors(@collection)
20
22
  end
21
23
  end
22
24
 
@@ -1,3 +1,3 @@
1
1
  module ActivityStream
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -0,0 +1,43 @@
1
+ require 'spec_helper'
2
+
3
+ describe ActivityStream::Metadata do
4
+
5
+ let(:metadata) { ActivityStream::Metadata.new(:example_action) }
6
+
7
+ before(:each) do
8
+ Activity.define(:example_action) do
9
+ metadata(:one_data)
10
+ metadata(:two_data)
11
+ end
12
+ end
13
+
14
+ after(:each) do
15
+ ActivityStream::Definition.all.delete(:example_action)
16
+ end
17
+
18
+ it 'should be initialized with a definition name' do
19
+ ActivityStream::Metadata.new(:example_action)
20
+ end
21
+
22
+ context 'data storage' do
23
+
24
+ it 'should accept new data' do
25
+ metadata.store(:one_data, 1)
26
+ end
27
+
28
+ it 'should retrieve previously set data' do
29
+ metadata.store(:two_data, 2)
30
+ metadata.data[:two_data].should be(2)
31
+ end
32
+
33
+ end
34
+
35
+ context 'definition' do
36
+
37
+ it 'should return one' do
38
+ metadata.definition.should be_a(ActivityStream::Definition)
39
+ end
40
+
41
+ end
42
+
43
+ end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activity_stream
3
3
  version: !ruby/object:Gem::Version
4
- hash: 27
4
+ hash: 25
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 0
9
- - 2
10
- version: 0.0.2
9
+ - 3
10
+ version: 0.0.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Andrew Smith
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-02 00:00:00 -04:00
18
+ date: 2010-11-06 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -81,16 +81,17 @@ files:
81
81
  - Rakefile
82
82
  - Readme.md
83
83
  - activity_stream.gemspec
84
- - app/models/activity.rb
84
+ - app/models/activity_stream/activity.rb
85
85
  - generators/activity_stream/activity_stream_generator.rb
86
86
  - generators/activity_stream/lib/insert_commands.rb
87
- - generators/activity_stream/templates/example_activity.rb
87
+ - generators/activity_stream/templates/initializer.rb
88
88
  - generators/activity_stream/templates/migration.rb
89
89
  - generators/activity_stream/templates/user.rb
90
90
  - lib/activity_stream.rb
91
91
  - lib/activity_stream/activities_helper.rb
92
92
  - lib/activity_stream/actor.rb
93
93
  - lib/activity_stream/definition.rb
94
+ - lib/activity_stream/definition_proxy.rb
94
95
  - lib/activity_stream/errors.rb
95
96
  - lib/activity_stream/metadata.rb
96
97
  - lib/activity_stream/stream.rb
@@ -149,6 +150,7 @@ files:
149
150
  - spec/integration/activity_model_spec.rb
150
151
  - spec/lib/actor_spec.rb
151
152
  - spec/lib/definition_spec.rb
153
+ - spec/lib/metadata_spec.rb
152
154
  - spec/lib/stream_spec.rb
153
155
  - spec/spec_helper.rb
154
156
  has_rdoc: true
@@ -239,5 +241,6 @@ test_files:
239
241
  - spec/integration/activity_model_spec.rb
240
242
  - spec/lib/actor_spec.rb
241
243
  - spec/lib/definition_spec.rb
244
+ - spec/lib/metadata_spec.rb
242
245
  - spec/lib/stream_spec.rb
243
246
  - spec/spec_helper.rb
@@ -1,46 +0,0 @@
1
- class Activity < ActiveRecord::Base
2
-
3
- belongs_to :actor, :polymorphic => true
4
-
5
- # @param name [Symbol] (see ActivityStream::Definition#new)
6
- # @return [ActivityStream::Definition] the new definitions
7
- #
8
- def self.define(name, &block)
9
- definition = ActivityStream::Definition.new(name)
10
- definition.instance_eval(&block)
11
- ActivityStream::Definition.register(definition)
12
- end
13
-
14
- named_scope :in_reverse_chronological_order, :order => 'occurred_at DESC'
15
-
16
- named_scope :in_chronological_order, :order => 'occurred_at ASC'
17
-
18
- # @param actors [Array] An array of [ActorClass, actor_id] sets
19
- # or [ActorClass, [actor_id, actor_id, actor_id...]
20
- #
21
- named_scope :by_actors, lambda { |actors|
22
- if actors.first.is_a?(Array)
23
- conditions = actors.map do |(actor_type, actor_id)|
24
- %{("activities"."actor_id" = #{actor_id.to_param} AND "activities"."actor_type" = '#{actor_type.to_param}')}
25
- end
26
- {:conditions => conditions.join(' OR ') }
27
- elsif actors.first.is_a?(Class)
28
- {:conditions => {:actor_id => actors.last, :actor_type => actors.first.to_param}}
29
- else
30
- {} # Not sure what to do here.
31
- end
32
- }
33
-
34
- serialize :metadata, ActivityStream::Metadata
35
-
36
- delegate :template, :icon, :to => :definition
37
-
38
- def metadata
39
- self[:metadata] ||= ActivityStream::Metadata.new(self[:kind])
40
- end
41
-
42
- def definition
43
- ActivityStream::Definition.find_by_name(self[:kind])
44
- end
45
-
46
- end