fiksu-af 1.1.0

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.
Files changed (77) hide show
  1. data/.gitignore +24 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +14 -0
  4. data/Gemfile +22 -0
  5. data/LICENSE +30 -0
  6. data/README.md +175 -0
  7. data/Rakefile +42 -0
  8. data/examples/af_script_with_options.rb +73 -0
  9. data/examples/af_side_component.rb +16 -0
  10. data/examples/my_application.rb +8 -0
  11. data/fiksu-af.gemspec +27 -0
  12. data/lib/fiksu-af/application/component.rb +95 -0
  13. data/lib/fiksu-af/application.rb +361 -0
  14. data/lib/fiksu-af/deprecated.rb +15 -0
  15. data/lib/fiksu-af/get_options.rb +68 -0
  16. data/lib/fiksu-af/logging/configurator.rb +152 -0
  17. data/lib/fiksu-af/logging.rb +13 -0
  18. data/lib/fiksu-af/option_parser/columnizer.rb +36 -0
  19. data/lib/fiksu-af/option_parser/dsl.rb +290 -0
  20. data/lib/fiksu-af/option_parser/get_options.rb +65 -0
  21. data/lib/fiksu-af/option_parser/helper.rb +80 -0
  22. data/lib/fiksu-af/option_parser/instance_variable_setter.rb +117 -0
  23. data/lib/fiksu-af/option_parser/interface.rb +63 -0
  24. data/lib/fiksu-af/option_parser/option.rb +40 -0
  25. data/lib/fiksu-af/option_parser/option_check.rb +66 -0
  26. data/lib/fiksu-af/option_parser/option_finder.rb +82 -0
  27. data/lib/fiksu-af/option_parser/option_group.rb +37 -0
  28. data/lib/fiksu-af/option_parser/option_select.rb +68 -0
  29. data/lib/fiksu-af/option_parser/option_store.rb +89 -0
  30. data/lib/fiksu-af/option_parser/option_type.rb +59 -0
  31. data/lib/fiksu-af/option_parser.rb +145 -0
  32. data/lib/fiksu-af/q_thread/base.rb +20 -0
  33. data/lib/fiksu-af/q_thread/interface.rb +23 -0
  34. data/lib/fiksu-af/q_thread/message.rb +14 -0
  35. data/lib/fiksu-af/q_thread/message_handler.rb +30 -0
  36. data/lib/fiksu-af/tcp_command/client.rb +49 -0
  37. data/lib/fiksu-af/tcp_command/server.rb +119 -0
  38. data/lib/fiksu-af/thread_pool.rb +102 -0
  39. data/lib/fiksu-af/version.rb +4 -0
  40. data/lib/fiksu-af.rb +12 -0
  41. data/logging/af.yml +32 -0
  42. data/spec/dummy/.rspec +1 -0
  43. data/spec/dummy/README.rdoc +261 -0
  44. data/spec/dummy/Rakefile +7 -0
  45. data/spec/dummy/app/assets/javascripts/application.js +15 -0
  46. data/spec/dummy/app/assets/stylesheets/application.css +13 -0
  47. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  48. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  49. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  50. data/spec/dummy/config/application.rb +59 -0
  51. data/spec/dummy/config/boot.rb +10 -0
  52. data/spec/dummy/config/database-sample.yml +32 -0
  53. data/spec/dummy/config/environment.rb +5 -0
  54. data/spec/dummy/config/environments/development.rb +31 -0
  55. data/spec/dummy/config/environments/production.rb +67 -0
  56. data/spec/dummy/config/environments/test.rb +35 -0
  57. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  58. data/spec/dummy/config/initializers/inflections.rb +15 -0
  59. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  60. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  61. data/spec/dummy/config/initializers/session_store.rb +8 -0
  62. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  63. data/spec/dummy/config/locales/en.yml +5 -0
  64. data/spec/dummy/config/routes.rb +58 -0
  65. data/spec/dummy/config.ru +4 -0
  66. data/spec/dummy/public/404.html +26 -0
  67. data/spec/dummy/public/422.html +26 -0
  68. data/spec/dummy/public/500.html +25 -0
  69. data/spec/dummy/public/favicon.ico +0 -0
  70. data/spec/dummy/script/rails +6 -0
  71. data/spec/dummy/spec/spec_helper.rb +32 -0
  72. data/spec/lib/af/application_spec.rb +60 -0
  73. data/spec/lib/af/get_options_spec.rb +24 -0
  74. data/spec/lib/af/option_parser/option_check_spec.rb +50 -0
  75. data/spec/lib/af/option_parser/option_select_spec.rb +51 -0
  76. data/spec/spec_helper.rb +33 -0
  77. metadata +288 -0
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ # See http://help.github.com/ignore-files/ for more about ignoring files.
2
+ #
3
+ # If you find yourself ignoring temporary files generated by your text editor
4
+ # or operating system, you probably want to add a global ignore instead:
5
+ # git config --global core.excludesfile ~/.gitignore_global
6
+
7
+ # Ignore bundler config
8
+ /.bundle
9
+
10
+ # Ignore the default SQLite database.
11
+ /db/*.sqlite3
12
+
13
+ # Ignore all logfiles and tempfiles.
14
+ /log/*.log
15
+ /tmp
16
+ .idea/*
17
+ database.yml
18
+ /log/*.pid
19
+ spec/dummy/db/*.sqlite3
20
+ spec/dummy/log/*.log
21
+ spec/dummy/tmp/
22
+ spec/dummy/.sass-cache
23
+ spec/dummy/config/database.yml
24
+ spec/dummy/db/schema.rb
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,14 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ bundler_args: --without staging development deploy
5
+ before_install:
6
+ before_script: cp spec/dummy/config/database-sample.yml spec/dummy/config/database.yml; cd spec/dummy; bundle exec rake db:create;
7
+ script: rspec spec
8
+ branches:
9
+ only:
10
+ - master
11
+ notifications:
12
+ hipchat: 5d580c1746812c946d9cb0b58f7a66@FMA
13
+ email:
14
+ - dev-fma@fiksu.com
data/Gemfile ADDED
@@ -0,0 +1,22 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Declare your gem's dependencies in partitioned.gemspec.
4
+ # Bundler will treat runtime dependencies like base dependencies, and
5
+ # development dependencies will be added by default to the :development group.
6
+ gemspec
7
+
8
+ gem 'pg_application_name', '>= 1.0.0'
9
+ gem 'pg_advisory_locker', '>= 0.9.0'
10
+ gem 'log4r', '1.1.10'
11
+ gem 'reasonable_log4r', '>= 0.9.0'
12
+ gem 'uuid', '2.3.5'
13
+
14
+ gem 'awesome_print'
15
+
16
+ # Declare any dependencies that are still in development here instead of in
17
+ # your gemspec. These might include edge Rails or gems from your path or
18
+ # Git. Remember to move these dependencies to your gemspec before releasing
19
+ # your gem to rubygems.org.
20
+
21
+ # To use debugger
22
+ # gem 'ruby-debug'
data/LICENSE ADDED
@@ -0,0 +1,30 @@
1
+ Copyright (c) 2010-2013, Fiksu, Inc.
2
+ All rights reserved.
3
+
4
+ Redistribution and use in source and binary forms, with or without
5
+ modification, are permitted provided that the following conditions are
6
+ met:
7
+
8
+ o Redistributions of source code must retain the above copyright
9
+ notice, this list of conditions and the following disclaimer.
10
+
11
+ o Redistributions in binary form must reproduce the above copyright
12
+ notice, this list of conditions and the following disclaimer in the
13
+ documentation and/or other materials provided with the
14
+ distribution.
15
+
16
+ o Fiksu, Inc. nor the names of its contributors may be used to
17
+ endorse or promote products derived from this software without
18
+ specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21
+ "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22
+ LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23
+ A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24
+ HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26
+ LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27
+ DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28
+ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29
+ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
data/README.md ADDED
@@ -0,0 +1,175 @@
1
+ # Af - an application framework
2
+
3
+ gem 'fiksu-af'
4
+
5
+ This application framework supports:
6
+
7
+ * an Application class with supporting infrastruction
8
+ * command line options integrated into instance (and class) variables
9
+ * logging via log4r with support for papertrail
10
+ * postgres advisory locking via pg_advisor_locker gem
11
+ * postgres database connection updates via pg_application_name gem
12
+ * threads and message passing
13
+ * application components adding loggers and command line options
14
+
15
+ ## Application class
16
+
17
+ The class ::Af::Application provides a basic interface to the start-up
18
+ and management of Ruby on Rails scripts.
19
+
20
+ A simple example of an application which logs its startup and exits
21
+ is:
22
+
23
+ ```
24
+ class MyApplication < ::Af::Application
25
+ opt :word, "the word", :short => :w, :default => "bird"
26
+
27
+ def work
28
+ logger.info "Started up: #{@word} is the word"
29
+ exit 0
30
+ end
31
+ end
32
+ ```
33
+
34
+ Class-method "opt" specifies command line parameter(s) whose arguments
35
+ are stored in instance variables. MyApplication specifies a single
36
+ parameter "--word" with a short alias "-w" that accepts a string
37
+ argument (whose default is "bird", so we know it should be a string).
38
+ The parameters value will be stored in class instance variable: @word.
39
+ More information on command line option glue is provided in the
40
+ Command Line Options section.
41
+
42
+ The method "logger" is available to ::Af::Application to create and
43
+ fetch log4r loggers. In this case, we use the basic application
44
+ logger (named "MyApplication") and logs an INFO level message. More
45
+ information on the glue ::Af::Application provides with Log4r is
46
+ in the logging section below.
47
+
48
+ This application would be run from the command line as:
49
+
50
+ ```
51
+ $ script/rails runner MyApplication.run --word grease
52
+ ```
53
+
54
+ The class method #run provides start-up glue for applications, parsing
55
+ command line options, environment variables and configuration files.
56
+ The instance method #work is where application codes start their work.
57
+
58
+ ## Command Line Options
59
+
60
+ a more interesting example of options from multiple classes
61
+
62
+ ```
63
+ class AfSideComponent
64
+ include Af::Application::Component
65
+
66
+ opt_group :side_component_stuff, "options associated with this side component" do
67
+ opt :a_side_component_option, :default => "foo"
68
+ end
69
+
70
+ opt :basic_option_from_component, "this is a switch from the side component, in the basic (default) group"
71
+
72
+ create_proxy_logger :foo
73
+
74
+ def do_something
75
+ foo_logger.info "doing something @@a_side_component_option='#{@@a_side_component_option}'"
76
+ foo_logger.info "did something @@basic_option_from_component=#{@@basic_option_from_component.inspect}"
77
+ end
78
+ end
79
+ ```
80
+
81
+ ```
82
+ class AfScriptWithOptions < ::Af::Application
83
+ opt_group :singles, "parameters whose types are a single value" do
84
+ opt :a_switch, "a switch"
85
+ opt :an_int, "an integer of some sort", :default => 1
86
+ opt :a_float, "a float of some sort whose default is PI", :default => 3.14
87
+ opt :a_string, "a string of some sort", :type => :string
88
+ opt :a_uri, "some uri", :type => :uri
89
+ opt :a_date, "a date", :type => :date
90
+ opt :a_time, "a time", :type => :time
91
+ opt :a_datetime, "a datetime", :type => :datetime
92
+ opt :a_choice, "a choice", :argument_note => "COLOR", :choices => [:red, :blue, :green, :yellow, :white, :black, :orange]
93
+ end
94
+
95
+ # there is already an advanced option group -- it is set to hidden by default
96
+ opt_group :advanced, "advanced parameters", :hidden => false do
97
+ opt :a_small_integer, "another integer", :default => 10, :argument_note => "[1 >= INTEGER <= 10]" do |argument,option|
98
+ argument = argument.to_i
99
+ if (argument < 1 || argument > 10)
100
+ opt_error "ERROR: #{option.long_name}: value must be between 1 and 10 (inclusive)"
101
+ end
102
+ argument
103
+ end
104
+ opt :a_constrained_number, "a number which is not an integer", :requirement => :required, :argument_note => "NON-INTEGER" do |argument,option|
105
+ i_argument = argument.to_i
106
+ f_argument = argument.to_f
107
+ if (i_argument == f_argument)
108
+ opt_error "ERROR: #{option.long_name}: value must not be an integer"
109
+ end
110
+ f_argument
111
+ end
112
+ end
113
+
114
+ opt_group :collections, "parameters whose types are collections" do
115
+ opt :a_hash, "a key value pair", :type => :hash
116
+ opt :some_ints, "a list of integer", :type => :ints
117
+ opt :some_integers, "a list of integer", :type => :integers
118
+ opt :some_floats, "a list of floats", :type => :floats
119
+ opt :some_numbers, "a list of numbers", :type => :numbers
120
+ opt :some_strings, "a list of strings", :type => :strings
121
+ opt :some_uris, "a list of uris", :type => :uris
122
+ opt :some_dates, "a list of dates", :type => :dates
123
+ opt :some_times, "a list of times", :type => :times
124
+ opt :some_datetimes, "a list of datetimes", :type => :datetimes
125
+ opt :some_choices, "a list of choices", :choices => [:foo, :bar, :baz, :beltch]
126
+ end
127
+
128
+ opt_group :blank, "a blank group that won't be seen"
129
+
130
+ opt :word, "the word to print", :default => :foo, :choices => [:foo, :bar, :baz, :beltch]
131
+ opt :words, "the words to print", :default => [:foo], :choices => [:foo, :bar, :baz, :beltch]
132
+ opt :numbers, "the number lists", :default => [1,2,3]
133
+ opt :switcher, "this is a switch"
134
+
135
+ def af_opt_class_path
136
+ [AfSideComponent] + super
137
+ end
138
+
139
+ def logger
140
+ super('Process::T')
141
+ end
142
+
143
+ def work
144
+ logger.info "switcher: #{switcher.inspect}"
145
+ logger.info "WORK STARTED: #{@word}"
146
+ logger.info @words.inspect
147
+ logger.info "NUMBERS: #{@numbers.inspect}"
148
+
149
+ AfSideComponent.new.do_something
150
+
151
+ logger.info "WORK COMPLETED: #{@word}"
152
+ end
153
+ end
154
+
155
+ ```
156
+
157
+ ## Logging with Log4r
158
+
159
+ Some changes to Log4r:
160
+
161
+ * root loggers are no longer null loggers -- you can add outputters to them
162
+ * the global logger is used to set a global log level (root is no longer used for this)
163
+ * yaml configurator has been updated to handle new root logger semantics
164
+ * yaml configurator has been updated to accept a set of files AND sections (default section: log4r_config)
165
+
166
+ What this really means is that you can set up one outputter in the root
167
+ logger to manage the default logging behavior.
168
+
169
+ ## Thread Pool
170
+
171
+ *TODO*
172
+
173
+ ## TCP Message Passing
174
+
175
+ *TODO*
data/Rakefile ADDED
@@ -0,0 +1,42 @@
1
+ #!/usr/bin/env rake
2
+ begin
3
+ require 'bundler/setup'
4
+ rescue LoadError
5
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
6
+ end
7
+
8
+ begin
9
+ require 'rdoc/task'
10
+ rescue LoadError
11
+ require 'rdoc/rdoc'
12
+ require 'rake/rdoctask'
13
+ RDoc::Task = Rake::RDocTask
14
+ end
15
+
16
+ RDoc::Task.new(:rdoc) do |rdoc|
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = 'Af'
19
+ rdoc.options << '--line-numbers'
20
+ rdoc.rdoc_files.include('README')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+ end
23
+
24
+ # Eventually we will want a test application to use this Engine
25
+ # to see if it works!
26
+
27
+ APP_RAKEFILE = File.expand_path("../spec/dummy/Rakefile", __FILE__)
28
+
29
+ load 'rails/tasks/engine.rake'
30
+
31
+ Bundler::GemHelper.install_tasks
32
+
33
+ require 'rake'
34
+ require 'rspec/core'
35
+ require 'rspec/core/rake_task'
36
+
37
+ RSpec::Core::RakeTask.new(:spec) do |spec|
38
+ spec.pattern = FileList['spec/**/*_spec.rb']
39
+ end
40
+
41
+ desc 'Default: Run all specs.'
42
+ task :default => :spec
@@ -0,0 +1,73 @@
1
+ class AfScriptWithOptions < ::Af::Application
2
+ opt_group :singles, "parameters whose types are a single value" do
3
+ opt :a_switch, "a switch"
4
+ opt :an_int, "an integer of some sort", :default => 1
5
+ opt :a_float, "a float of some sort whose default is PI", :default => 3.14
6
+ opt :a_string, "a string of some sort", :type => :string
7
+ opt :a_uri, "some uri", :type => :uri
8
+ opt :a_date, "a date", :type => :date
9
+ opt :a_time, "a time", :type => :time
10
+ opt :a_datetime, "a datetime", :type => :datetime
11
+ opt :a_choice, "a choice", :argument_note => "COLOR", :choices => [:red, :blue, :green, :yellow, :white, :black, :orange]
12
+ end
13
+
14
+ # there is already an advanced option group -- it is set to hidden by default
15
+ opt_group :advanced, "advanced parameters", :hidden => false do
16
+ opt :a_small_integer, "another integer", :default => 10, :argument_note => "[1 >= INTEGER <= 10]" do |argument,option|
17
+ argument = argument.to_i
18
+ if (argument < 1 || argument > 10)
19
+ opt_error "ERROR: #{option.long_name}: value must be between 1 and 10 (inclusive)"
20
+ end
21
+ argument
22
+ end
23
+ opt :a_constrained_number, "a number which is not an integer", :requirement => :required, :argument_note => "NON-INTEGER" do |argument,option|
24
+ i_argument = argument.to_i
25
+ f_argument = argument.to_f
26
+ if (i_argument == f_argument)
27
+ opt_error "ERROR: #{option.long_name}: value must not be an integer"
28
+ end
29
+ f_argument
30
+ end
31
+ end
32
+
33
+ opt_group :collections, "parameters whose types are collections" do
34
+ opt :a_hash, "a key value pair", :type => :hash
35
+ opt :some_ints, "a list of integer", :type => :ints
36
+ opt :some_integers, "a list of integer", :type => :integers
37
+ opt :some_floats, "a list of floats", :type => :floats
38
+ opt :some_numbers, "a list of numbers", :type => :numbers
39
+ opt :some_strings, "a list of strings", :type => :strings
40
+ opt :some_uris, "a list of uris", :type => :uris
41
+ opt :some_dates, "a list of dates", :type => :dates
42
+ opt :some_times, "a list of times", :type => :times
43
+ opt :some_datetimes, "a list of datetimes", :type => :datetimes
44
+ opt :some_choices, "a list of choices", :choices => [:foo, :bar, :baz, :beltch]
45
+ end
46
+
47
+ opt_group :blank, "a blank group that won't be seen"
48
+
49
+ opt :word, "the word to print", :default => :foo, :choices => [:foo, :bar, :baz, :beltch]
50
+ opt :words, "the words to print", :default => [:foo], :choices => [:foo, :bar, :baz, :beltch]
51
+ opt :numbers, "the number lists", :default => [1,2,3]
52
+ opt :switcher, "this is a switch"
53
+
54
+ def af_opt_class_path
55
+ [AfSideComponent] + super
56
+ end
57
+
58
+ def logger
59
+ super('Process::T')
60
+ end
61
+
62
+ def work
63
+ logger.info "switcher: #{switcher.inspect}"
64
+ logger.info "WORK STARTED: #{@word}"
65
+ logger.info @words.inspect
66
+ logger.info "NUMBERS: #{@numbers.inspect}"
67
+
68
+ AfSideComponent.new.do_something
69
+
70
+ logger.info "WORK COMPLETED: #{@word}"
71
+ end
72
+ end
73
+
@@ -0,0 +1,16 @@
1
+ class AfSideComponent
2
+ include Af::Application::Component
3
+
4
+ opt_group :side_component_stuff, "options associated with this side component" do
5
+ opt :a_side_component_option, :default => "foo"
6
+ end
7
+
8
+ opt :basic_option_from_component, "this is a switch from the side component, in the basic (default) group"
9
+
10
+ create_proxy_logger :foo
11
+
12
+ def do_something
13
+ foo_logger.info "doing something @@a_side_component_option='#{@@a_side_component_option}'"
14
+ foo_logger.info "did something @@basic_option_from_component=#{@@basic_option_from_component.inspect}"
15
+ end
16
+ end
@@ -0,0 +1,8 @@
1
+ class MyApplication < ::Af::Application
2
+ opt :word, "the word", :short => :w, :default => "bird"
3
+
4
+ def work
5
+ logger.info "Started up: #{@word} is the word"
6
+ exit 0
7
+ end
8
+ end
data/fiksu-af.gemspec ADDED
@@ -0,0 +1,27 @@
1
+ $LOAD_PATH.push File.expand_path("../lib", __FILE__)
2
+
3
+ # Maintain your gem's version:
4
+ require "fiksu-af/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'fiksu-af'
8
+ s.version = Af::VERSION
9
+ s.license = 'New BSD License'
10
+ s.date = '2013-10-11'
11
+ s.summary = "An application framework for ruby on rails based scripts."
12
+ s.description = "Af groups together gems and provides some glue and helper classes to easily creating applications in a ruby on rails environment."
13
+ s.authors = ["Keith Gabryelski", "Leonardo Meira"]
14
+ s.email = ['keith@fiksu.com', 'lmeira@fiksu.com']
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.require_path = 'lib'
18
+ s.homepage = 'http://github.com/fiksu/af'
19
+ s.add_dependency 'pg_application_name', '>= 1.0.0'
20
+ s.add_dependency 'pg_advisory_locker', '>= 0.9.0'
21
+ s.add_dependency 'log4r', '1.1.10'
22
+ s.add_dependency "log4r_remote_syslog_outputter", "0.0.1"
23
+ s.add_dependency 'reasonable_log4r', '>= 0.9.0'
24
+ s.add_dependency 'uuid'
25
+ s.add_dependency "rails", '>= 3.0.0'
26
+ s.add_dependency 'rspec-rails', '>=2.12.0'
27
+ end
@@ -0,0 +1,95 @@
1
+ module Af
2
+ class Application
3
+ # Proxy's are used by dependant classes to interact with the Application framework
4
+ #
5
+ # consider a model that wishes to use the logging functionality of Af:
6
+ #
7
+ # class Foo < ActiveRecord::Base
8
+ # include ::Af::Application::Component
9
+ #
10
+ # after_create :do_something_after_create
11
+ #
12
+ # create_proxy_logger :foo
13
+ #
14
+ # private
15
+ # def do_something_after_create
16
+ # foo_logger.info "created: #{self.inspect}"
17
+ # end
18
+ # end
19
+ #
20
+ module Component
21
+ def self.included(base)
22
+ base.extend(ClassMethods)
23
+ base.send(:include, ::Af::Logging)
24
+ end
25
+
26
+ module ClassMethods
27
+ def create_proxy_logger(prefix = "", logger_name = self.name, create_class_method = false)
28
+ prefix = prefix.to_s
29
+ if !prefix.blank? && prefix[-1] != '_'
30
+ prefix = "#{prefix}_"
31
+ end
32
+
33
+ method_name = "#{prefix}logger"
34
+ class_eval <<-CLASS_EVAL
35
+ def #{create_class_method ? 'self.' : ''}#{method_name}
36
+ return Log4r::Logger['#{logger_name}'] || Log4r::Logger.new('#{logger_name}')
37
+ end
38
+ CLASS_EVAL
39
+ end
40
+
41
+ def create_class_proxy_logger(prefix = "", logger_name = self.name)
42
+ create_proxy_logger(prefix, logger_name, true)
43
+ end
44
+
45
+ def opt(long_name, *extra_stuff, &b)
46
+ add_target_container(extra_stuff)
47
+ return ::Af::Application.opt(long_name, *extra_stuff, &b)
48
+ end
49
+
50
+ def opt_group(group_name, *extra_stuff, &b)
51
+ add_target_container(extra_stuff)
52
+ return ::Af::Application.opt_group(group_name, *extra_stuff, &b)
53
+ end
54
+
55
+ def opt_check(var_name, *extra_stuff, &b)
56
+ add_target_container(extra_stuff)
57
+ return ::Af::Application.opt_check(var_name, *extra_stuff, &b)
58
+ end
59
+
60
+ def opt_select(var_name, *extra_stuff, &b)
61
+ add_target_container(extra_stuff)
62
+ return ::Af::Application.opt_select(var_name, *extra_stuff, &b)
63
+ end
64
+
65
+ def add_target_container(extra_stuff)
66
+ extra_hash = {}
67
+ if extra_stuff[-1].is_a? Hash
68
+ extra_hash = extra_stuff.pop
69
+ end
70
+ extra_stuff.push extra_hash.merge({ target_container: self })
71
+ end
72
+ end
73
+
74
+ def af_logger(logger_name = (af_name || "Unknown"))
75
+ return ::Af::Application.singleton.logger(logger_name)
76
+ end
77
+
78
+ def af_name
79
+ return ::Af::Application.singleton.try(:af_name)
80
+ end
81
+
82
+ def periodic_application_checkpoint
83
+ af_application.try(:periodic_application_checkpoint)
84
+ end
85
+
86
+ def protect_from_signals
87
+ af_application.try(:protect_from_signals)
88
+ end
89
+
90
+ def af_application
91
+ return ::Af::Application.singleton
92
+ end
93
+ end
94
+ end
95
+ end