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.
- data/.gitignore +24 -0
- data/.rspec +2 -0
- data/.travis.yml +14 -0
- data/Gemfile +22 -0
- data/LICENSE +30 -0
- data/README.md +175 -0
- data/Rakefile +42 -0
- data/examples/af_script_with_options.rb +73 -0
- data/examples/af_side_component.rb +16 -0
- data/examples/my_application.rb +8 -0
- data/fiksu-af.gemspec +27 -0
- data/lib/fiksu-af/application/component.rb +95 -0
- data/lib/fiksu-af/application.rb +361 -0
- data/lib/fiksu-af/deprecated.rb +15 -0
- data/lib/fiksu-af/get_options.rb +68 -0
- data/lib/fiksu-af/logging/configurator.rb +152 -0
- data/lib/fiksu-af/logging.rb +13 -0
- data/lib/fiksu-af/option_parser/columnizer.rb +36 -0
- data/lib/fiksu-af/option_parser/dsl.rb +290 -0
- data/lib/fiksu-af/option_parser/get_options.rb +65 -0
- data/lib/fiksu-af/option_parser/helper.rb +80 -0
- data/lib/fiksu-af/option_parser/instance_variable_setter.rb +117 -0
- data/lib/fiksu-af/option_parser/interface.rb +63 -0
- data/lib/fiksu-af/option_parser/option.rb +40 -0
- data/lib/fiksu-af/option_parser/option_check.rb +66 -0
- data/lib/fiksu-af/option_parser/option_finder.rb +82 -0
- data/lib/fiksu-af/option_parser/option_group.rb +37 -0
- data/lib/fiksu-af/option_parser/option_select.rb +68 -0
- data/lib/fiksu-af/option_parser/option_store.rb +89 -0
- data/lib/fiksu-af/option_parser/option_type.rb +59 -0
- data/lib/fiksu-af/option_parser.rb +145 -0
- data/lib/fiksu-af/q_thread/base.rb +20 -0
- data/lib/fiksu-af/q_thread/interface.rb +23 -0
- data/lib/fiksu-af/q_thread/message.rb +14 -0
- data/lib/fiksu-af/q_thread/message_handler.rb +30 -0
- data/lib/fiksu-af/tcp_command/client.rb +49 -0
- data/lib/fiksu-af/tcp_command/server.rb +119 -0
- data/lib/fiksu-af/thread_pool.rb +102 -0
- data/lib/fiksu-af/version.rb +4 -0
- data/lib/fiksu-af.rb +12 -0
- data/logging/af.yml +32 -0
- data/spec/dummy/.rspec +1 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config/application.rb +59 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database-sample.yml +32 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +31 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +35 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec/spec_helper.rb +32 -0
- data/spec/lib/af/application_spec.rb +60 -0
- data/spec/lib/af/get_options_spec.rb +24 -0
- data/spec/lib/af/option_parser/option_check_spec.rb +50 -0
- data/spec/lib/af/option_parser/option_select_spec.rb +51 -0
- data/spec/spec_helper.rb +33 -0
- 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
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
|
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
|