safai 0.0.11 → 0.0.12

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.
@@ -0,0 +1,9 @@
1
+ class SafaiGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate',
5
+ :migration_file_name => 'create_timeline_events'
6
+ m.template 'model.rb', 'app/models/timeline_event.rb'
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ class CreateTimelineEvents < ActiveRecord::Migration
2
+ def self.change
3
+ create_table :timeline_events do |t|
4
+ t.string :event_type, :subject_type, :actor_type, :secondary_subject_type, :link
5
+ t.integer :subject_id, :actor_id, :secondary_subject_id
6
+ t.text :message
7
+ t.timestamps
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,38 @@
1
+ class TimelineEvent < ActiveRecord::Base
2
+
3
+ #GEMS USED
4
+ #ACCESSORS
5
+ attr_accessible :event_type, :actor, :subject, :secondary_subject, :link, :message
6
+
7
+ #ASSOCIATIONS
8
+ belongs_to :actor, :polymorphic => true
9
+ belongs_to :subject, :polymorphic => true
10
+ belongs_to :secondary_subject, :polymorphic => true
11
+
12
+ #CALLBACKS
13
+ #VALIDATIONS
14
+ #QUERY SCOPES
15
+ #CUSTOM SCOPES
16
+ #SORTING SCOPES
17
+ default_scope :order => "created_at desc"
18
+
19
+ #OTHER STUFF
20
+
21
+ def tag
22
+ if alertable_type == "Campaign"
23
+ return "<span class='tag1'>Campaign</span>".html_safe
24
+ elsif alertable_type == "Impact" or alertable_type == "Project"
25
+ return "<span class='tag2'>Project</span>".html_safe
26
+ elsif alertable_type == "Bank"
27
+ return "<span class='tag3'>Bank Account</span>".html_safe
28
+ end
29
+ end
30
+
31
+ #PRIVATE STUFF
32
+ private
33
+
34
+ end
35
+
36
+
37
+
38
+
@@ -0,0 +1,39 @@
1
+ module Safai
2
+ module Fires
3
+ def self.included(klass)
4
+ klass.send(:extend, ClassMethods)
5
+ end
6
+
7
+ module ClassMethods
8
+ def fires(event_type, opts)
9
+ raise ArgumentError, "Argument :on is mandatory" unless opts.has_key?(:on)
10
+
11
+ # Array provided, set multiple callbacks
12
+ if opts[:on].kind_of?(Array)
13
+ opts[:on].each { |on| fires(event_type, opts.merge({:on => on})) }
14
+ return
15
+ end
16
+
17
+ opts[:subject] = :self unless opts.has_key?(:subject)
18
+
19
+ send(:"after_#{opts[:on]}", :if => opts[:if]) do
20
+ create_options = [:actor, :subject, :secondary_subject].inject({}) do |memo, sym|
21
+ if opts[sym]
22
+ if opts[sym].respond_to?(:call)
23
+ memo[sym] = opts[sym].call(self)
24
+ elsif opts[sym] == :self
25
+ memo[sym] = self
26
+ else
27
+ memo[sym] = send(opts[sym])
28
+ end
29
+ end
30
+ memo
31
+ end
32
+ create_options[:event_type] = event_type.to_s
33
+
34
+ TimelineEvent.create!(create_options)
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,20 @@
1
+ module Safai
2
+ module Macros
3
+ def should_fire_event(event_type, opts = {})
4
+ should "fire #{event_type} on #{opts[:on]}" do
5
+ matcher = fire_event(event_type, opts)
6
+
7
+ assert_accepts matcher, self.class.name.gsub(/Test$/, '').constantize
8
+ end
9
+ end
10
+
11
+ def should_not_fire_event(event_type, opts = {})
12
+ should "fire #{event_type} on #{opts[:on]}" do
13
+ matcher = fire_event(event_type, opts)
14
+
15
+ assert_rejects matcher, self.class.name.gsub(/Test$/, '').constantize
16
+ end
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,58 @@
1
+ module Safai
2
+ module Matchers
3
+ class FireEvent
4
+ def initialize(event_type, opts = {})
5
+ @event_type = event_type
6
+ @opts = opts
7
+ @method = :"fire_#{@event_type}_after_#{@opts[:on]}"
8
+ end
9
+
10
+ def matches?(subject)
11
+ @subject = subject
12
+
13
+ defines_callback_method? && setups_up_callback?
14
+ end
15
+
16
+ def defines_callback_method?
17
+ if @subject.instance_methods.include?(@method.to_s)
18
+ true
19
+ else
20
+ @missing = "#{@subject.name} does not respond to #{@method}"
21
+ false
22
+ end
23
+ end
24
+
25
+ def setups_up_callback?
26
+ callback_chain_name = "after_#{@opts[:on]}_callback_chain"
27
+ callback_chain = @subject.send(callback_chain_name)
28
+ if callback_chain.any? {|chain| chain.method == @method }
29
+ true
30
+ else
31
+ @missing = "does setup after #{@opts[:on]} callback for #{@method}"
32
+ false
33
+ end
34
+ end
35
+
36
+ def description
37
+ "fire a #{@event_type} event"
38
+ end
39
+
40
+ def expectation
41
+ expected = "#{@subject.name} to #{description}"
42
+ end
43
+
44
+ def failure_message
45
+ "Expected #{expectation} (#{@missing})"
46
+ end
47
+
48
+ def negative_failure_message
49
+ "Did not expect #{expectation}"
50
+ end
51
+
52
+ end
53
+
54
+ def fire_event(event_type, opts)
55
+ FireEvent.new(event_type, opts)
56
+ end
57
+ end
58
+ end
data/lib/safai.rb CHANGED
@@ -123,5 +123,7 @@ require 'safai/clean'
123
123
  require 'safai/gravatar'
124
124
  require 'safai/money'
125
125
  require 'safai/date'
126
+ require 'timeline_fu/fires'
127
+ ActiveRecord::Base.send :include, Safai::Fires
126
128
  ActionView::Base.send :include, Safai::Helpers
127
129
  ActionView::Base.send :include, Safai::DeviseHelpers
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: safai
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.11
4
+ version: 0.0.12
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -57,6 +57,12 @@ files:
57
57
  - lib/safai/gravatar.rb
58
58
  - lib/safai/money.rb
59
59
  - lib/safai/date.rb
60
+ - generators/safai/templates/migration.rb
61
+ - generators/safai/templates/model.rb
62
+ - generators/safai/safai_generator.rb
63
+ - lib/safai/fires.rb
64
+ - lib/safai/macros.rb
65
+ - lib/safai/matchers.rb
60
66
  homepage: http://rubygems.org/gems/safai
61
67
  licenses: []
62
68
  post_install_message: