platanus 0.0.1 → 0.0.2

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