platanus 0.0.1 → 0.0.2

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.
data/README.md CHANGED
@@ -1,6 +1,8 @@
1
1
  # Platanus
2
2
 
3
- TODO: Write a gem description
3
+ Platan.us toolbelt.
4
+
5
+ This gem includes various ruby and rails utility classes we use across most of our rails proyects.
4
6
 
5
7
  ## Installation
6
8
 
@@ -16,7 +18,35 @@ Or install it yourself as:
16
18
 
17
19
  $ gem install platanus
18
20
 
19
- ## Usage
21
+ ## Tools & Usage
22
+
23
+ ### Stacked
24
+
25
+ TODO: Write usage instructions here
26
+
27
+ ### Activable
28
+
29
+ TODO: Write usage instructions here
30
+
31
+ ### Traceable
32
+
33
+ TODO: Write usage instructions here
34
+
35
+ ### Canned
36
+
37
+ TODO: Write usage instructions here
38
+
39
+ ### Gobal Controller
40
+
41
+ Requires explicit inclusion:
42
+
43
+ require 'platanus/gcontroller'
44
+
45
+ ### Template: Spreadsheet
46
+
47
+ TODO: Write usage instructions here
48
+
49
+ ### Template: prawn
20
50
 
21
51
  TODO: Write usage instructions here
22
52
 
@@ -0,0 +1,67 @@
1
+ # activable.rb : ActiveRecord Activable mod.
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ module Platanus
6
+
7
+ # When included in a model definition, this module
8
+ # provides soft delete capabilities via the +remove+ method.
9
+ #
10
+ # This module also defines a +remove+ callback.
11
+ #
12
+ module Activable
13
+
14
+ def self.included(base)
15
+ base.define_callbacks :remove
16
+ base.attr_protected :removed_at
17
+ base.send(:default_scope, base.where(:removed_at => nil))
18
+ base.extend ClassMethods
19
+ end
20
+
21
+ module ClassMethods
22
+ # Executes a mass remove, this wont call any callbacks!
23
+ def remove_all
24
+ # TODO: Find a way of doing mass updates and also call callbacks
25
+ # self.update_all(:removed_at => DateTime.now)
26
+ # For now, just call remove on each item
27
+ self.all.each { |item| item.remove! }
28
+ end
29
+
30
+ ## Shorthand method for adding callbacks before item removal
31
+ def before_remove(_callback)
32
+ self.set_callback :remove, :before, _callback
33
+ end
34
+
35
+ ## Shorthand method for adding callbacks after item removal
36
+ def after_remove(_callback)
37
+ self.set_callback :remove, :after, _callback
38
+ end
39
+ end
40
+
41
+ # Returns true if object hasnt been removed.
42
+ def is_active?
43
+ self.removed_at.nil?
44
+ end
45
+
46
+ # Deactivates a single record.
47
+ def remove!
48
+ self.transaction do
49
+ run_callbacks :remove do
50
+
51
+ # Retrieve dependant properties and remove them.
52
+ self.class.reflect_on_all_associations.select do |assoc|
53
+ if assoc.options[:dependent] == :destroy
54
+ collection = self.send(assoc.name)
55
+ collection.remove_all if collection.respond_to? :remove_all
56
+ end
57
+ end
58
+
59
+ self.removed_at = DateTime.now
60
+ self.save!
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+
67
+
@@ -0,0 +1,222 @@
1
+ # canned.rb : User profiling and authorization.
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ module Platanus
6
+
7
+ # User profiling and authorization module
8
+ module Canned
9
+
10
+ class Interrupt < Exception; end
11
+ class Error < StandardError; end
12
+ class AuthError < Error; end
13
+ class SetupError < Error; end
14
+
15
+ # Controller extension, include this in the the base application
16
+ # controller and use the barracks_setup method to define the profiles
17
+ # definition object and the user profile provider block.
18
+ module ControllerExt
19
+
20
+ attr_accessor :brk_tag
21
+
22
+ def self.included(klass)
23
+ class << klass
24
+ # Excluded actions are defined in per class basis
25
+ attr_accessor :brk_excluded
26
+ end
27
+ protected
28
+ # Definition and role provider are shared with subclasses
29
+ klass.cattr_accessor :brk_definition
30
+ klass.cattr_accessor :brk_provider
31
+ public
32
+ klass.extend ClassMethods
33
+ end
34
+
35
+ # Wraps a controller instance and provides the profile
36
+ # testing enviroment used by the role provider function.
37
+ class ActionWrapper
38
+
39
+ attr_reader :tag
40
+
41
+ # Loads the testing enviroment.
42
+ def initialize(_owner, _action, _actions_feats)
43
+ @owner = _owner
44
+ @action = _action
45
+ @feats = _actions_feats
46
+ @tag = nil
47
+ end
48
+
49
+ # Test if a profile can execute the current action, raises a
50
+ # BarracksInterrupt exception if conditions are met.
51
+ def test(_profile, _user_feats, _tag=nil)
52
+ if @owner.class.brk_definition.can?(_profile, @action, @feats, _user_feats)
53
+ @tag = _tag
54
+ raise Interrupt
55
+ end
56
+ end
57
+
58
+ # Since we need to provide with all of controller functionality
59
+ # to provider, then proxy al failed method calls to it.
60
+ def method_missing(_method, *_args, &_block)
61
+ @owner.send(_method, *_args, &_block)
62
+ end
63
+ end
64
+
65
+ # Test if an action can be executed using the currently loaded roles.
66
+ def can?(_action, _action_feat)
67
+ wrapper = ActionWrapper.new(self,_action,_action_feat)
68
+ begin
69
+ provider = if brk_provider.is_a? Symbol then self.method(brk_provider) else brk_provider end
70
+ wrapper.instance_eval &provider
71
+ return false
72
+ rescue Interrupt
73
+ return (if wrapper.tag.nil? then true else wrapper.tag end)
74
+ end
75
+ end
76
+
77
+ module ClassMethods
78
+
79
+ # Setups the controller user profile definitions and
80
+ # profile provider block (or proc)
81
+ def canned_setup(_definition, _provider=nil, &pblock)
82
+ self.brk_definition = _definition
83
+ self.brk_provider = _provider || pblock
84
+ self.before_filter do
85
+ # Before filter is an instance_eval?
86
+ break if self.class.brk_excluded == :all
87
+ break if !self.class.brk_excluded.nil? and self.class.brk_excluded.include? params[:action].to_sym
88
+ tag = self.can?(params[:controller], params)
89
+ tag ||= self.can?(params[:controller] + '#' + params[:action], params)
90
+ raise AuthError unless tag
91
+ self.brk_tag = tag
92
+ end
93
+ end
94
+
95
+ # Removes protection for all controller actions.
96
+ def uncan_all()
97
+ self.brk_excluded = :all
98
+ end
99
+
100
+ # Removes protection for the especified controller actions.
101
+ def uncanned(*_excluded)
102
+ self.brk_excluded ||= []
103
+ self.brk_excluded.push(*_excluded)
104
+ end
105
+ end
106
+ end
107
+
108
+ # Profile DSL
109
+ module ProfileManager
110
+
111
+ # Auxiliary class used by profile manager to store profiles.
112
+ class BProfile
113
+
114
+ # This is required for the copy constructor to work.
115
+ protected
116
+ attr_reader :rules
117
+ attr_reader :def_test
118
+ public
119
+
120
+ # The initializer takes another profile as rules base.
121
+ def initialize(_owner, _base, _def_test)
122
+ @owner = _owner
123
+ @rules = if _base.nil? then {} else _base.rules.clone end
124
+ @def_test = _def_test
125
+ end
126
+
127
+ # Adds a new ability.
128
+ def ability(*_args)
129
+ @rules[_args.first] = tests = {}
130
+ if _args.last.is_a? Hash
131
+ hook = _args.last.delete(@hook)
132
+ _args[1...-1].each { |sym| tests[sym] = @def_test }
133
+ tests.merge!(_args.last)
134
+ else
135
+ hook = nil
136
+ _args[1..-1].each { |sym| tests[sym] = @def_test }
137
+ end
138
+ end
139
+
140
+ # Removes an action by its name.
141
+ def remove(_name)
142
+ @rules.delete(_name)
143
+ end
144
+
145
+ # Test an action agaist this profile
146
+ def test(_action, _action_feats, _user_feats)
147
+ tests = @rules[_action]
148
+ return false if tests.nil?
149
+ tests.each do |sym, test|
150
+
151
+ # Analize test.
152
+ if test.is_a? Hash
153
+ test_name = test.fetch(:name,@def_test)
154
+ test_transform = test[:transform]
155
+ user_sym = test.fetch(:key,sym)
156
+ else
157
+ test_name = test
158
+ test_transform = nil
159
+ user_sym = sym
160
+ end
161
+
162
+ # Extract user and action features.
163
+ action_feat = _action_feats[sym]
164
+ raise SetupError if action_feat.nil?
165
+ user_feat = _user_feats[user_sym]
166
+ return false if user_feat.nil?
167
+ next if user_feat == :wildcard # Wildcard matches always
168
+
169
+ # Compare features.
170
+ action_feat = _owner.send(test_transform,action_feat) unless test_transform.nil?
171
+ case test_name
172
+ when :equals
173
+ return false unless user_feat == action_feat
174
+ when :equals_int
175
+ return false unless user_feat.to_i == action_feat.to_i
176
+ when :if_higher
177
+ return false unless user_feat > action_feat
178
+ when :if_lower
179
+ return false unless user_feat < action_feat
180
+ else
181
+ # TODO: Check that method exists first.
182
+ if @owner.method_defined? test_name
183
+ return false unless @owner.send(test_name,action_feat,user_value)
184
+ end
185
+ end
186
+ end
187
+
188
+ return true
189
+ end
190
+ end
191
+
192
+ def self.included(base)
193
+ class << base
194
+ # Add a profile property to extended class
195
+ attr_accessor :profiles
196
+ end
197
+ base.profiles = {}
198
+ base.extend ClassMethods
199
+ end
200
+
201
+ module ClassMethods
202
+
203
+ # Creates a new profile and passes it to the given block.
204
+ # This can optionally take an inherit parameter to use
205
+ # another profile as base for the new one.
206
+ def profile(_name, _options={})
207
+ inherit = _options.fetch(:inherits,nil)
208
+ def_test = _options.fetch(:default,:equals)
209
+ yield self.profiles[_name.to_s] = BProfile.new(self,self.profiles[inherit],def_test)
210
+ end
211
+
212
+ # Test if a user (profile + user data) can execute a given
213
+ # action (action name + action data).
214
+ def can?(_profile, _action, _action_feat, _user_data)
215
+ profile = self.profiles[_profile.to_s]
216
+ return false if profile.nil?
217
+ return profile.test(_action,_action_feat,_user_data)
218
+ end
219
+ end
220
+ end
221
+ end
222
+ end
@@ -0,0 +1,80 @@
1
+ module Platanus
2
+
3
+ module Cmap
4
+
5
+ class InvalidName < Exception; end
6
+
7
+ def self.included(base)
8
+ base.cattr_accessor :cmap
9
+ base.cmap = Hash.new { |hash, key| hash[key] = {} }
10
+ base.extend ClassMethods
11
+ end
12
+
13
+ module ClassMethods
14
+
15
+ def cmap_register(_key, _value, _cat=nil)
16
+ if _cat.nil?; self.cmap[_key] = _value
17
+ else; self.cmap[_cat.to_s][_key] = _value
18
+ end
19
+ end
20
+
21
+ def cmap_convert(_key, _cat=nil)
22
+ if _cat.nil?; return self.cmap[_key]
23
+ else; return self.cmap[_cat.to_s][_key]
24
+ end
25
+ end
26
+
27
+ def cmap_convert_back(_value, _cat=nil)
28
+ if _cat.nil?; return self.cmap.key(_value)
29
+ else; return self.cmap[_cat.to_s].key(_value)
30
+ end
31
+ end
32
+
33
+ def str_attr_accessor(_target, _options={})
34
+ str_attr_reader(_target,_options)
35
+ str_attr_writer(_target,_options)
36
+ end
37
+
38
+ def str_attr_writer(_target, _options={})
39
+ _target = _target.to_s
40
+ _self = _options.fetch(:extend, self)
41
+ _cat = _options[:cat]
42
+ _cmap = self.cmap
43
+
44
+ _self.send(:define_method, _target + '_str=') do |value|
45
+ if _cat.nil?; self.send(_target + '=', _cmap.fetch(value))
46
+ else; self.send(_target + '=', _cmap[_cat.to_s].fetch(value)); end
47
+ end
48
+ end
49
+
50
+ def str_attr_reader(_target, _options={})
51
+ _target = _target.to_s
52
+ _self = _options.fetch(:extend, self)
53
+ _cat = _options[:cat]
54
+ _cmap = self.cmap
55
+
56
+ _self.send(:define_method, _target + '_str') do
57
+ if _cat.nil?; _cmap.key(self.send(_target))
58
+ else; _cmap[_cat.to_s].key(self.send(_target)); end
59
+ end
60
+ end
61
+
62
+ # private
63
+ # def cmap_converters(_cat_or_name=nil)
64
+ # # Define new class methods.
65
+ # klass = (class << self; self; end)
66
+ # klass.send(:define_method, _target + '_to_str') do |value|
67
+ # if _cat.nil?; _cmap.index(value)
68
+ # else; _cmap[_cat].index(value); end
69
+ # end
70
+ #
71
+ # klass.send(:define_method, 'str_to_' + _target) do |value|
72
+ # if _cat.nil?; _cmap.fetch(value)
73
+ # else; _cmap[_cat].fetch(value); end
74
+ # end
75
+ # end
76
+ end
77
+ end
78
+ end
79
+
80
+
@@ -0,0 +1,26 @@
1
+ # gcontroller.rb : ActionController global access.
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ class Platanus::NotInRequestError < Exception; end
6
+
7
+ # This makes the current request controller globally avaliable.
8
+ class ActionController::Base
9
+ around_filter :wrap_store_controller
10
+
11
+ def wrap_store_controller
12
+ # We could do this instead: http://coderrr.wordpress.com/2008/04/10/lets-stop-polluting-the-threadcurrent-hash/
13
+ Thread.current[:controller] = self
14
+ begin; yield
15
+ ensure; Thread.current[:controller] = nil
16
+ end
17
+ end
18
+
19
+ # Gets the current controller.
20
+ #
21
+ # * *Raises* :
22
+ # - +Platanus::NotInRequestError+ -> If current controller instance is not avaliable.
23
+ def self.current
24
+ Thread.current[:controller] || (raise Platanus::NotInRequestError, 'Current controller not loaded')
25
+ end
26
+ end
@@ -0,0 +1,61 @@
1
+ # http_helpers.rb : Various HTTP Related helpers
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ module Platanus
6
+
7
+ ## HTTP STATUS EXCEPTIONS
8
+
9
+ # Allows to use an exception driven scheme to notify
10
+ # the request that a especial status should be send
11
+ # back to the client. Usefull when used with rescue_from.
12
+ class StatusError < StandardError
13
+
14
+ class << self
15
+ instance_variable_set(:@status, nil)
16
+ instance_variable_set(:@msg, nil)
17
+ end
18
+
19
+ def self.setup(_status, _msg)
20
+ @status = _status
21
+ @msg = _msg
22
+ end
23
+
24
+ def self.status; @status; end
25
+ def self.message; @msg; end
26
+
27
+ def self.as_json(_options={})
28
+ { 'status' => @status.to_s, 'msg' => @msg }
29
+ end
30
+
31
+ def initialize(_msg=nil)
32
+ @msg = _msg
33
+ end
34
+
35
+ def status; self.class.status; end
36
+ def message; if @msg.nil? then self.class.message else @msg end; end
37
+ def as_json(_options={})
38
+ { 'status' => status.to_s, 'msg' => message }
39
+ end
40
+ end
41
+
42
+ class StatusNotFound < StatusError
43
+ setup :not_found, 'Not found'
44
+ end
45
+
46
+ class StatusUnauthorized < StatusError
47
+ setup :unauthorized, 'Not authorized'
48
+ end
49
+
50
+ class StatusUnprocessable < StatusError
51
+ setup :unprocessable_entity, 'Invalid object'
52
+ end
53
+
54
+ class StatusBadRequest < StatusError
55
+ setup :bad_request, 'Invalid parameters'
56
+ end
57
+
58
+ class StatusConflict < StatusError
59
+ setup :conflict, 'Model conflict'
60
+ end
61
+ end
@@ -0,0 +1,23 @@
1
+ module Platanus
2
+
3
+ # Adds simple proxy capabilities to a class, allowing
4
+ # it instances to wrap other objects transparently
5
+ module Layered
6
+ attr_reader :lo_target
7
+
8
+ def initialize(_entity)
9
+ @lo_target = _entity
10
+ end
11
+
12
+ def respond_to?(_what)
13
+ return true if super(_what)
14
+ return @lo_target.respond_to? _what
15
+ end
16
+
17
+ def method_missing(_method, *_args, &_block)
18
+ @lo_target.send(_method, *_args, &_block)
19
+ end
20
+ end
21
+ end
22
+
23
+
@@ -0,0 +1,33 @@
1
+ # onetime.rb : One time setter.
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ module Kernel
6
+
7
+ # Creates a one time writer method.
8
+ #
9
+ # A one time writer is undefined after the first time it is used.
10
+ #
11
+ # * *Args* :
12
+ # - +_name+ -> Attribute name.
13
+ #
14
+ def onetime_attr_writer(_name)
15
+ define_method _name.to_s + '=' do |_value|
16
+ instance_variable_set('@' + _name.to_s, _value)
17
+ # Unset method by modifying singleton class.
18
+ metaclass = (class << self; self; end)
19
+ metaclass.send(:undef_method,_name.to_s + '=')
20
+ _value
21
+ end
22
+ end
23
+
24
+ # Adds a one time writer instead of a regular writer.
25
+ #
26
+ # * *Args* :
27
+ # - +_name+ -> Attribute name.
28
+ #
29
+ def onetime_attr_accessor(_name)
30
+ attr_reader(_name)
31
+ onetime_attr_writer(_name)
32
+ end
33
+ end
@@ -0,0 +1,86 @@
1
+ # stacked.rb : Stackable attributes for ActiveRecord
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ module Platanus
6
+
7
+ # Adds the has_stacked association to an ActiveRecord model.
8
+ #
9
+ module StackedAttr
10
+
11
+ def self.included(base)
12
+ base.extend ClassMethods
13
+ end
14
+
15
+ module ClassMethods
16
+
17
+ # Adds an stacked attribute to the model.
18
+ def has_stacked(_name, _options={}, &block)
19
+
20
+ tname = _name.to_s
21
+ to_cache = _options.delete(:cached)
22
+ to_cache_prf = if _options[:cache_prf].nil? then 'last_' else _options.delete(:cache_prf) end
23
+ stack_key = if _options[:stack_key].nil? then 'created_at DESC, id DESC' else _options.delete(:stack_key) end
24
+
25
+ _options[:order] = stack_key
26
+ _options[:limit] = 10 if _options[:limit].nil?
27
+
28
+ # Protect cached attributes.
29
+ unless to_cache.nil?
30
+ to_cache = to_cache.map { |name| name.to_s }
31
+ to_cache.each { |name| attr_protected(to_cache_prf + name) }
32
+ end
33
+
34
+ private
35
+ has_many(_name,_options)
36
+ public
37
+
38
+ send :define_method, 'push_' + tname[0...-1] + '!' do |obj|
39
+ self.class.transaction do
40
+
41
+ # Execute before callbacks
42
+ self.send(_options[:before_push], obj) if _options.has_key? :before_push
43
+ block.call(self, obj) unless block.nil?
44
+
45
+ # Cache required fields
46
+ unless to_cache.nil?
47
+ to_cache.each { |name| send(to_cache_prf + name + '=', obj.send(name)) }
48
+ end
49
+
50
+ # Save model and push attribute, cache last stacked attribute.
51
+ self.save! if _options[:autosave] and (self.new_record? or self.changed?)
52
+ raise ActiveRecord::RecordInvalid.new(obj) unless self.send(tname).send('<<',obj)
53
+ @_stacked_last = obj
54
+
55
+ # Execute after callback
56
+ self.send(_options[:after_push], obj) if _options.has_key? :after_push
57
+ end
58
+ end
59
+
60
+ send :define_method, 'push_' + tname[0...-1] do |obj|
61
+ begin
62
+ return self.send('push_' + tname[0...-1] + '!', obj)
63
+ rescue ActiveRecord::RecordInvalid
64
+ return false
65
+ end
66
+ end
67
+
68
+ send :define_method, 'top_' + tname[0...-1] do
69
+ # Storing the last stacked value will not prevent race conditions
70
+ # when simultaneous updates occur.
71
+ return @_stacked_last unless @_stacked_last.nil?
72
+ self.send(_name).first
73
+ end
74
+
75
+ # Generate shorcut properties for cached attributes.
76
+ unless to_cache.nil?
77
+ to_cache.each do |name|
78
+ send :define_method, name.to_s do
79
+ self.send(to_cache_prf + name)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
@@ -0,0 +1,26 @@
1
+ # prawn.rb : Prawn - Rails Templates integration.
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.ius+.
4
+
5
+ require 'prawn'
6
+
7
+ Mime::Type.register 'application/pdf', :pdf
8
+
9
+ module Platanus
10
+
11
+ # Template Handler, just exposes prawn to a template.
12
+ class PrawnBuilder
13
+
14
+ class_attribute :default_format
15
+ self.default_format = Mime::PDF
16
+
17
+ def self.call(template)
18
+ # Create a new pdf doc object using a block, populate the block using
19
+ # the template contents.
20
+ "pdf = Prawn::Document.new(:skip_page_creation => true);" + template.source + ";pdf.render;"
21
+ end
22
+ end
23
+ end
24
+
25
+ # Register the template handler for the .prawn extension.
26
+ ActionView::Template.register_template_handler :prawn, Platanus::PrawnBuilder
@@ -0,0 +1,24 @@
1
+ # spreadsheet.rb : Spreadsheet - Rails Templates integration.
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.ius+.
4
+
5
+ require 'spreadsheet'
6
+
7
+ Mime::Type.register 'application/vnd.ms-excel', :xls
8
+
9
+ module Platanus
10
+
11
+ # Template Handler, just exposes a spreadsheet's Workbook to a template.
12
+ class ExcelBuilder
13
+
14
+ class_attribute :default_format
15
+ self.default_format = Mime::XLS
16
+
17
+ def self.call(template)
18
+ "book = ::Spreadsheet::Workbook.new;" + template.source + ";io=StringIO.new('');book.write io;io.close;io.string;"
19
+ end
20
+ end
21
+ end
22
+
23
+ # Register the template handler for the .spreadsht extension
24
+ ActionView::Template.register_template_handler :spreadsht, Platanus::ExcelBuilder
@@ -0,0 +1,74 @@
1
+ # traceable.rb : Logged user action tracing
2
+ #
3
+ # Copyright April 2012, Ignacio Baixas +mailto:ignacio@platan.us+.
4
+
5
+ module Platanus
6
+
7
+ # When included in a model, this module will provide seamless C(R)UD operations
8
+ # tracing.
9
+ #
10
+ # This module operates under a couple of conventions:
11
+ # * When a new operation is detected it will look for the +user_id+ method for the current controller
12
+ # and assing it's value to the <action>_by attribute of the current model.
13
+ # * When a new operation is detected the controllers +trace+ method is called passing the action and
14
+ # the current model.
15
+ #
16
+ # This module will also trace +Activable.remove+ calls.
17
+ # Will only work if the gcontroller mod is active.
18
+ #
19
+ module Traceable
20
+
21
+ def self.included(base)
22
+ # Make sure gcontroller was loaded.
23
+ unless ActionController::Base.respond_to? :current
24
+ # TODO: better warning!
25
+ base.logger.warn 'gcontroller not loaded, tracing disabled'
26
+ return
27
+ end
28
+
29
+ base.around_create :__trace_create
30
+ base.around_update :__trace_update
31
+ base.around_destroy :__trace_destroy
32
+ # Activable support (remove event).
33
+ begin; base.set_callback :remove, :around, :__trace_remove; rescue; end
34
+ end
35
+
36
+ ## CALLBACKS
37
+
38
+ def __trace_create # :nodoc:
39
+ controller = ActionController::Base.current
40
+ if controller.respond_to? :trace_user_id and self.respond_to? :created_by=
41
+ self.created_by = controller.trace_user_id
42
+ end
43
+ yield
44
+ controller.trace(:create, self) if controller.respond_to? :trace
45
+ end
46
+
47
+ def __trace_update # :nodoc:
48
+ controller = ActionController::Base.current
49
+ if controller.respond_to? :trace_user_id and self.respond_to? :updated_by=
50
+ self.updated_by = controller.trace_user_id
51
+ end
52
+ yield
53
+ controller.trace(:update, self) if controller.respond_to? :trace
54
+ end
55
+
56
+ def __trace_destroy # :nodoc:
57
+ controller = ActionController::Base.current
58
+ if controller.respond_to? :trace_user_id and self.respond_to? :destroyed_by=
59
+ self.destroyed_by = controller.trace_user_id
60
+ end
61
+ yield
62
+ controller.trace(:destroy, self) if controller.respond_to? :trace
63
+ end
64
+
65
+ def __trace_remove # :nodoc:
66
+ controller = ActionController::Base.current
67
+ if controller.respond_to? :trace_user_id and self.respond_to? :removed_by=
68
+ self.removed_by = controller.trace_user_id
69
+ end
70
+ yield
71
+ controller.trace(:remove, self) if controller.respond_to? :trace
72
+ end
73
+ end
74
+ end
@@ -1,3 +1,3 @@
1
1
  module Platanus
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
data/lib/platanus.rb CHANGED
@@ -9,6 +9,7 @@ require 'platanus/cmap'
9
9
  require 'platanus/http_helpers'
10
10
 
11
11
  # require 'platanus/onetime'
12
+ # require 'platanus/gcontroller'
12
13
  # require 'platanus/template/spreadsheet'
13
14
  # require 'platanus/template/prawn'
14
15
 
data/platanus.gemspec CHANGED
@@ -12,6 +12,6 @@ Gem::Specification.new do |gem|
12
12
  gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
13
  gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
14
  gem.name = "platanus"
15
- gem.require_paths = ["lib"]
15
+ gem.require_paths = ["lib","lib/platanus"]
16
16
  gem.version = Platanus::VERSION
17
17
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: platanus
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -24,6 +24,17 @@ files:
24
24
  - README.md
25
25
  - Rakefile
26
26
  - lib/platanus.rb
27
+ - lib/platanus/activable.rb
28
+ - lib/platanus/canned.rb
29
+ - lib/platanus/cmap.rb
30
+ - lib/platanus/gcontroller.rb
31
+ - lib/platanus/http_helpers.rb
32
+ - lib/platanus/layered.rb
33
+ - lib/platanus/onetime.rb
34
+ - lib/platanus/stacked.rb
35
+ - lib/platanus/templates/prawn.rb
36
+ - lib/platanus/templates/spreadsheet.rb
37
+ - lib/platanus/traceable.rb
27
38
  - lib/platanus/version.rb
28
39
  - platanus.gemspec
29
40
  homepage: http://www.platan.us
@@ -32,6 +43,7 @@ post_install_message:
32
43
  rdoc_options: []
33
44
  require_paths:
34
45
  - lib
46
+ - lib/platanus
35
47
  required_ruby_version: !ruby/object:Gem::Requirement
36
48
  none: false
37
49
  requirements: