safai 0.0.11 → 0.0.12

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: