narrator 0.0.1.alpha → 0.0.1.beta

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa1bb48cf586a6f4f347ed23bad29ef890b6a970
4
+ data.tar.gz: 61fc99168cf94e4bf24b68652747e4df0822d6da
5
+ SHA512:
6
+ metadata.gz: fa6d4ce60133cca0a0c8596fb5bc9dfc314ddb46f278c52d2c470bac44a5d0457a4f87b29a210093bbf4191f46c64897e2f4463ffccd2920146d455a9396a3e5
7
+ data.tar.gz: a264d17ae149cb7713ffed1b36f1884b62103ff442431f4539bebaaada182964ba6acc4b753ca3691440c5082d4298a65c45a1466395691dc0038854eb4ae58e
data/.travis.yml CHANGED
@@ -1,8 +1,7 @@
1
1
  language: ruby
2
2
  rvm:
3
- - "1.8.7"
4
- - "1.9.2"
5
- - "1.9.3"
3
+ - 1.8.7
4
+ - 1.9.3
6
5
  #- jruby-18mode # JRuby in 1.8 mode
7
6
  #- jruby-19mode # JRuby in 1.9 mode
8
7
  #- rbx-18mode
data/README.rdoc CHANGED
@@ -1,3 +1,4 @@
1
+ = This gem is currently unstable as it is being developed.
1
2
  = Narrator {<img src="https://secure.travis-ci.org/jweakley/narrator.png?branch=master" />}[http://travis-ci.org/jweakley/narrator]
2
3
 
3
4
  Narrator is an activity library for Ruby on Rails that allow you to track what is happening on models and later use to build an activity or news stream. Tracking is done at the controller level with a simple narrate_resource command (which was inspired by the simplicity of Ryan Bates' CanCan gem).
@@ -8,9 +9,73 @@ In <b> Rails 3 </b> add this line to your application's Gemfile and run the +bun
8
9
 
9
10
  gem "narrator"
10
11
 
12
+ Once you have the Narrator gem installed you will need to run the generator:
13
+
14
+ rails generate narrator:install
15
+
16
+ This generator will add the migrations needed for the activity tracking. Currently this only works for ActiveRecord.
17
+
18
+ After the migration has been added you will need to migrate your database to run the new migration.
19
+
20
+ rake db:migrate
21
+
11
22
  == Getting Started
12
23
 
13
- * Coming Soon
24
+ Narrator expects a +current_user+ method to exist in the controller. First, set up some authentication (such as Authlogic[https://github.com/binarylogic/authlogic] or Devise[https://github.com/plataformatec/devise]).
25
+
26
+ === 1. Mark a Model as Narratable
27
+
28
+ Any model that we would like to have tracked by narrator needs to have <tt>narratable_model</tt> added to it.
29
+
30
+ class Article
31
+ narratable_model
32
+ ...
33
+ end
34
+
35
+ See {Narrated Model}[https://github.com/jweakley/narrator/wiki/Narrated-Model] for more details and features.
36
+
37
+ === 1. Mark a Model as Narratable
38
+
39
+ Any model that we would like to create activites (normally just User) needs to have <tt>narratable_actor</tt> added to it.
40
+
41
+ class User
42
+ narratable_actor
43
+ ...
44
+ end
45
+
46
+ See {Narrated Actor}[https://github.com/jweakley/narrator/wiki/Narrated-ACtor] for more details and features.
47
+
48
+
49
+ === 3. Narrate the Model's activities from the controller
50
+
51
+ The <tt>narrate</tt> method in the controller will narrate something important.
52
+
53
+ def create
54
+ ...
55
+ @article = Article.new(params[:article])
56
+ ...
57
+ narrate @article if @article.save
58
+ ....
59
+ end
60
+
61
+ In this example, if the article is successfully saved, an activity gets logged for the article.
62
+
63
+ See {Tracked Activities}[https://github.com/jweakley/narrator/wiki/Tracked-Activities] for more details and features with tracked activities.
64
+
65
+ == Future Features
66
+
67
+ Automagical Narration
68
+
69
+ class ArticlesController < ApplicationController
70
+ narrate_resource
71
+
72
+ def create
73
+ ...
74
+ respond_with @article
75
+ # @article is automaticly tracked if it is valid
76
+ end
77
+ end
78
+
14
79
 
15
80
  == Wiki Docs
16
81
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rake'
2
3
  require 'rspec/core/rake_task'
3
4
 
4
5
  RSpec::Core::RakeTask.new(:spec)
5
- task default: :spec
6
+ task :default => :spec
@@ -0,0 +1,41 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Narrator
5
+ class InstallGenerator < Rails::Generators::Base
6
+ include Rails::Generators::Migration
7
+ desc 'Generates migration for Activity model'
8
+
9
+ def self.orm
10
+ Rails::Generators.options[:rails][:orm]
11
+ end
12
+
13
+ def self.source_root
14
+ File.join(
15
+ File.dirname(__FILE__),
16
+ 'templates',
17
+ (orm.to_s unless orm.class.eql?(String))
18
+ )
19
+ end
20
+
21
+ def self.orm_has_migration?
22
+ [:active_record].include? orm
23
+ end
24
+
25
+ def self.next_migration_number(dirname)
26
+ if ActiveRecord::Base.timestamped_migrations
27
+ migration_number = Time.now.utc.strftime('%Y%m%d%H%M%S').to_i
28
+ migration_number += 1
29
+ migration_number.to_s
30
+ else
31
+ sprintf '%.3d' , (current_migration_number(dirname) + 1)
32
+ end
33
+ end
34
+
35
+ def create_migration_file
36
+ if self.class.orm_has_migration?
37
+ migration_template 'migration.rb', 'db/migrate/narrator_migration'
38
+ end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,31 @@
1
+ class NarratorMigration < ActiveRecord::Migration
2
+ def change
3
+ if table_exists?(:activities)
4
+ say 'Activities table already exists! Narrator was unable to install.'
5
+ raise 'Narrator was unable to resolve clashing table names.'
6
+ else
7
+ suppress_messages do
8
+ create_table :activities do |t|
9
+ t.belongs_to :owner
10
+ t.string :owner_type
11
+ t.belongs_to :actor
12
+ t.string :actor_type
13
+ t.text :context
14
+ t.belongs_to :subject
15
+ t.string :subject_type
16
+ t.belongs_to :target
17
+ t.string :target_type
18
+ t.string :verb
19
+ t.boolean :has_seen, default: false
20
+
21
+ t.timestamps
22
+ end
23
+ add_index :activities, [:owner_id, :owner_type]
24
+ add_index :activities, [:actor_id, :actor_type]
25
+ add_index :activities, [:subject_id, :subject_type]
26
+ add_index :activities, [:target_id, :target_type]
27
+ end
28
+ say 'Created tables for Narrator'
29
+ end
30
+ end
31
+ end
@@ -1,4 +1,28 @@
1
1
  module Narrator
2
- module Activity
2
+ class Activity < ::ActiveRecord::Base
3
+ ###
4
+ # Attribute accessible
5
+ ###
6
+ attr_accessible :owner, :subject, :actor, :target, :verb, :context, :has_seen
7
+
8
+ ###
9
+ # Associations
10
+ ###
11
+ belongs_to :owner, polymorphic: true
12
+ belongs_to :actor, polymorphic: true
13
+ belongs_to :subject, polymorphic: true
14
+ belongs_to :target, polymorphic: true
15
+
16
+ ###
17
+ # Validate
18
+ ###
19
+ validates :subject, presence: true
20
+ validates :verb, presence: true
21
+
22
+ ###
23
+ # Scopes
24
+ ###
25
+ scope :unseen, where(has_seen: false)
26
+ scope :seen, where(has_seen: true)
3
27
  end
4
28
  end
@@ -3,23 +3,37 @@ module Narrator
3
3
  module ClassMethods
4
4
 
5
5
  def narrate_resource(*args)
6
- narrator_resource_class.add_before_filter(self, :narrate_resource, *args)
7
- end
8
-
9
- def narrate(subject, target = nil, verb = params[:action], actor_id = current_user.user_profile_id)
10
- if user_signed_in?
11
- subject.class.delay.track_user_activity(subject.id, actor_id, target.class.to_s, (target.blank? ? nil : target.id), verb.to_s)
12
- end
6
+ narrator_resource_class.add_after_filter(self, :narrate_resource, *args)
13
7
  end
14
8
 
15
9
  def narrator_resource_class
10
+ if ancestors.map(&:to_s).include? 'InheritedResources::Actions'
11
+ InheritedResource
12
+ else
16
13
  ControllerResource
14
+ end
17
15
  end
16
+ end
18
17
 
19
- def self.included(base)
20
- base.extend ClassMethods
21
- end
18
+ def self.included(base)
19
+ base.extend ClassMethods
20
+ base.helper_method :narrate
21
+ end
22
22
 
23
+ def narrate(subject, actor = current_user, target = nil, verb = params[:action], context = nil)
24
+ if subject.class.respond_to? :track_user_activity
25
+ # Add some config way of determining to use delayed jobs.
26
+ subject.class.track_user_activity(
27
+ (subject.blank? ? nil : subject.id),
28
+ subject.class.to_s,
29
+ (actor.blank? ? nil : actor.id),
30
+ actor.class.to_s,
31
+ (target.blank? ? nil : target.id),
32
+ target.class.to_s,
33
+ verb,
34
+ context
35
+ )
36
+ end
23
37
  end
24
38
  end
25
39
  end
@@ -1,6 +1,15 @@
1
1
  module Narrator
2
2
  class ControllerResource
3
3
 
4
+ def self.add_after_filter(controller_class, method, *args)
5
+ options = args.extract_options!
6
+ resource_name = args.first
7
+ after_filter_method = options.delete(:prepend) ? :prepend_after_filter : :after_filter
8
+ controller_class.send(after_filter_method, options.slice(:only, :except, :if, :unless)) do |controller|
9
+ controller.class.narrator_resource_class.new(controller, resource_name, options.except(:only, :except, :if, :unless)).send(method)
10
+ end
11
+ end
12
+
4
13
  def initialize(controller, *args)
5
14
  @controller = controller
6
15
  @params = controller.params
@@ -9,8 +18,7 @@ module Narrator
9
18
  end
10
19
 
11
20
  def narrate_resource
12
- # TODO Add skipper for this method
13
- @controller.narrate(subject, nil, params[:action], current_user)
21
+ @controller.narrate(resource_instance) if resource_instance.valid?
14
22
  end
15
23
 
16
24
  protected
@@ -19,12 +27,20 @@ module Narrator
19
27
  @controller.send(:current_user)
20
28
  end
21
29
 
22
- def resource_class
23
- case @options[:class]
24
- when String then @options[:class].constantize
25
- else @options[:class]
26
- end
30
+ def resource_instance
31
+ @controller.instance_variable_get("@#{instance_name}")
27
32
  end
28
33
 
34
+ def name
35
+ @name || name_from_controller
36
+ end
37
+
38
+ def name_from_controller
39
+ @params[:controller].sub('Controller', '').underscore.split('/').last.singularize
40
+ end
41
+
42
+ def instance_name
43
+ @options[:instance_name] || name
44
+ end
29
45
  end
30
46
  end
@@ -0,0 +1,34 @@
1
+ module Narrator
2
+ module ModelAdditions
3
+ include ::ActiveSupport::Inflector
4
+ def narratable_model
5
+ ###
6
+ # Includes
7
+ ###
8
+ include Narrator::ModelResources
9
+
10
+ ###
11
+ # Associations
12
+ ###
13
+ has_many :activities, as: :subject, class_name: 'Narrator::Activity', dependent: :destroy
14
+
15
+ ###
16
+ # Instance Methods
17
+ ###
18
+
19
+ # TODO Add documentation once format is determined.
20
+ def track_user_activity(subject_id, subject_class, actor_id, actor_class, target_id, target_class, verb, context)
21
+ actor = actor_id.blank? ? nil : actor_class.constantize.find_by_id(actor_id)
22
+ subject = subject_id.blank? ? nil : subject_class.constantize.find_by_id(subject_id)
23
+ target = target_id.blank? ? nil : target_class.constantize.find_by_id(target_id)
24
+ Narrator::Activity.create!(owner: nil, subject: subject, actor: actor, target: target, verb: verb, context: context)
25
+ end
26
+ end
27
+ def narratable_actor
28
+ ###
29
+ # Associations
30
+ ###
31
+ has_many :activities, as: :actor, class_name: 'Narrator::Activity', dependent: :destroy
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,9 @@
1
+ module Narrator
2
+ module ModelResources
3
+
4
+ # TODO Remove this test method.
5
+ def haldo
6
+ puts 'Haldo!'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ module Narrator
2
+ class NarratorRailtie < Rails::Railtie
3
+ initializer 'narrator.model_additions' do
4
+ ActiveSupport.on_load :active_record do
5
+ extend ModelAdditions
6
+ end
7
+ end
8
+ end
9
+ end
@@ -1,3 +1,3 @@
1
1
  module Narrator
2
- VERSION = "0.0.1.alpha"
2
+ VERSION = '0.0.1.beta'
3
3
  end
data/lib/narrator.rb CHANGED
@@ -1,9 +1,7 @@
1
- require 'narrator/ability'
2
- require 'narrator/controller_resource'
1
+ require 'narrator/version'
2
+ require 'narrator/activity'
3
+ require 'narrator/model_additions'
4
+ require 'narrator/model_resources'
3
5
  require 'narrator/controller_additions'
4
-
5
- require "narrator/version"
6
-
7
- module Narrator
8
- # Your code goes here...
9
- end
6
+ require 'narrator/controller_resource'
7
+ require 'narrator/narrator_railtie.rb' if defined?(Rails)
data/narrator.gemspec CHANGED
@@ -17,5 +17,8 @@ Gem::Specification.new do |gem|
17
17
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
18
18
  gem.require_paths = ["lib"]
19
19
 
20
+ gem.add_dependency('rails', '~>3.0')
21
+
20
22
  gem.add_development_dependency "rspec"
23
+ gem.add_development_dependency "rake"
21
24
  end
@@ -1,5 +1,8 @@
1
1
  require 'spec_helper'
2
2
 
3
3
  describe Narrator do
4
- pending "Add moar tests!"
4
+ it 'should pass' do
5
+ true.should eq true
6
+ end
7
+ pending 'Add MOAR TESTS!'
5
8
  end
data/spec/spec_helper.rb CHANGED
@@ -1 +1 @@
1
- require "narrator"
1
+ require 'narrator'
metadata CHANGED
@@ -1,30 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: narrator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1.alpha
5
- prerelease: 6
4
+ version: 0.0.1.beta
6
5
  platform: ruby
7
6
  authors:
8
7
  - Joe Weakley
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2013-04-08 00:00:00.000000000 Z
11
+ date: 2013-10-23 00:00:00.000000000 Z
13
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '3.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'
14
27
  - !ruby/object:Gem::Dependency
15
28
  name: rspec
16
29
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
30
  requirements:
19
- - - ! '>='
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
20
46
  - !ruby/object:Gem::Version
21
47
  version: '0'
22
48
  type: :development
23
49
  prerelease: false
24
50
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
51
  requirements:
27
- - - ! '>='
52
+ - - '>='
28
53
  - !ruby/object:Gem::Version
29
54
  version: '0'
30
55
  description: Straightforward and flexable activity tracking for rails that is designed
@@ -43,40 +68,41 @@ files:
43
68
  - LICENSE.txt
44
69
  - README.rdoc
45
70
  - Rakefile
46
- - lib/generators/narrator/activity/USAGE
47
- - lib/generators/narrator/activity/activity_generator.rb
48
- - lib/generators/narrator/activity/templates/activity.rb
71
+ - lib/generators/narrator/install_generator.rb
72
+ - lib/generators/narrator/templates/active_record/migration.rb
49
73
  - lib/narrator.rb
50
74
  - lib/narrator/activity.rb
51
75
  - lib/narrator/controller_additions.rb
52
76
  - lib/narrator/controller_resource.rb
77
+ - lib/narrator/model_additions.rb
78
+ - lib/narrator/model_resources.rb
79
+ - lib/narrator/narrator_railtie.rb
53
80
  - lib/narrator/version.rb
54
81
  - narrator.gemspec
55
82
  - spec/narrator/narrator_spec.rb
56
83
  - spec/spec_helper.rb
57
84
  homepage: https://github.com/jweakley/narrator
58
85
  licenses: []
86
+ metadata: {}
59
87
  post_install_message:
60
88
  rdoc_options: []
61
89
  require_paths:
62
90
  - lib
63
91
  required_ruby_version: !ruby/object:Gem::Requirement
64
- none: false
65
92
  requirements:
66
- - - ! '>='
93
+ - - '>='
67
94
  - !ruby/object:Gem::Version
68
95
  version: '0'
69
96
  required_rubygems_version: !ruby/object:Gem::Requirement
70
- none: false
71
97
  requirements:
72
- - - ! '>'
98
+ - - '>'
73
99
  - !ruby/object:Gem::Version
74
100
  version: 1.3.1
75
101
  requirements: []
76
102
  rubyforge_project:
77
- rubygems_version: 1.8.24
103
+ rubygems_version: 2.0.3
78
104
  signing_key:
79
- specification_version: 3
105
+ specification_version: 4
80
106
  summary: Straightforward and flexable activity tracking for rails.
81
107
  test_files:
82
108
  - spec/narrator/narrator_spec.rb
@@ -1,4 +0,0 @@
1
- Description:
2
- The narrator:activity generator creates an Activity class in the models
3
- directory. You can move this file anywhere you want as long as it
4
- is in the load path.
@@ -1,11 +0,0 @@
1
- module Narrator
2
- module Generators
3
- class ActivityGenerator < Rails::Generators::Base
4
- source_root File.expand_path('../templates', __FILE__)
5
-
6
- def generate_ability
7
- copy_file "activity.rb", "app/models/activity.rb"
8
- end
9
- end
10
- end
11
- end
@@ -1,30 +0,0 @@
1
- class Activity
2
- include Narrator::Activity
3
- ###
4
- # Attribute accessible
5
- ###
6
- attr_accessible :owner, :subject, :actor, :target, :target_id, :target_type, :verb, :context, :has_seen
7
-
8
- ###
9
- # Associations
10
- ###
11
- belongs_to :owner, class_name: 'UserProfile'
12
- belongs_to :actor, class_name: 'UserProfile'
13
- belongs_to :subject, polymorphic: true
14
- belongs_to :target, polymorphic: true
15
-
16
- ###
17
- # Validate
18
- ###
19
- validates :owner, presence: true
20
- validates :subject, presence: true
21
- validates :verb, presence: true
22
-
23
- ###
24
- # Scopes
25
- ###
26
- scope :unseen, where{has_seen.eq false}
27
- scope :seen, where{has_seen.eq true}
28
- scope :recent, order('created_at DESC')
29
-
30
- end