appkernel 0.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/History.txt +4 -0
- data/Manifest.txt +15 -0
- data/README.rdoc +73 -0
- data/Rakefile +29 -0
- data/lib/appkernel/function.rb +153 -0
- data/lib/appkernel/validation.rb +60 -0
- data/lib/appkernel.rb +6 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/spec/appkernel/function_spec.rb +211 -0
- data/spec/appkernel/validation_spec.rb +32 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +10 -0
- data/tasks/rspec.rake +21 -0
- metadata +94 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.rdoc
|
4
|
+
Rakefile
|
5
|
+
lib/appkernel.rb
|
6
|
+
lib/appkernel/function.rb
|
7
|
+
lib/appkernel/validation.rb
|
8
|
+
script/console
|
9
|
+
script/destroy
|
10
|
+
script/generate
|
11
|
+
spec/appkernel/function_spec.rb
|
12
|
+
spec/appkernel/validation_spec.rb
|
13
|
+
spec/spec.opts
|
14
|
+
spec/spec_helper.rb
|
15
|
+
tasks/rspec.rake
|
data/README.rdoc
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
= appkernel
|
2
|
+
|
3
|
+
* http://github.com/cowboyd/appkernel
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
AppKernel is a microframework for capturing your application in terms of minute, self-validating functions.
|
8
|
+
Once defined, these functions can be used in rails, cocoa, an sms gateway, or wherever you want to take them.
|
9
|
+
|
10
|
+
== FEATURES:
|
11
|
+
|
12
|
+
* Package the bits of your application in terms of what it *does*, not the entities it contains.
|
13
|
+
* Get a command line interface for free (that's better than vanilla script/console)
|
14
|
+
|
15
|
+
== SYNOPSIS:
|
16
|
+
|
17
|
+
module Foo
|
18
|
+
include AppKernel::Function
|
19
|
+
|
20
|
+
function :Hello do
|
21
|
+
option :to, :index => 1, :required => true
|
22
|
+
|
23
|
+
validate do
|
24
|
+
@to.check(@to != "spam", "I don't like spam!")
|
25
|
+
end
|
26
|
+
|
27
|
+
execute do
|
28
|
+
"Hello #{@to}!"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
Hello("George") #=> "Hello, George!"
|
33
|
+
Hello(:to => "George") #=> "Hello, George!"
|
34
|
+
apply(Hello, "George").success? #=> true
|
35
|
+
apply(Hello, "George").return_value => "Hello, George!"
|
36
|
+
|
37
|
+
#Error Reporting
|
38
|
+
|
39
|
+
Hello("spam") #=> "Exception!! I don't like spam!"
|
40
|
+
apply(Hello, "spam").success? #=> false
|
41
|
+
apply(Hello, "spam").return_value #=> nil
|
42
|
+
apply(Hello, "spam").errors[:to] #=> "I don't like spam"
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
== INSTALL:
|
47
|
+
|
48
|
+
sudo gem install appkernel
|
49
|
+
|
50
|
+
== LICENSE:
|
51
|
+
|
52
|
+
(The MIT License)
|
53
|
+
|
54
|
+
Copyright (c) 2009 Charles Lowell <cowboyd@thefrontside.net>
|
55
|
+
|
56
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
57
|
+
a copy of this software and associated documentation files (the
|
58
|
+
'Software'), to deal in the Software without restriction, including
|
59
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
60
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
61
|
+
permit persons to whom the Software is furnished to do so, subject to
|
62
|
+
the following conditions:
|
63
|
+
|
64
|
+
The above copyright notice and this permission notice shall be
|
65
|
+
included in all copies or substantial portions of the Software.
|
66
|
+
|
67
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
68
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
69
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
70
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
71
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
72
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
73
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
2
|
+
%w[rake rake/clean fileutils newgem rubigen].each { |f| require f }
|
3
|
+
$:.unshift(File.dirname(__FILE__) + '/lib') unless $:.member?(File.dirname(__FILE__) + '/lib')
|
4
|
+
require 'appkernel'
|
5
|
+
|
6
|
+
# Generate all the Rake tasks
|
7
|
+
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
8
|
+
$hoe = Hoe.new('appkernel', AppKernel::VERSION) do |p|
|
9
|
+
p.developer('Charles Lowell', 'cowboyd@thefrontside.net')
|
10
|
+
p.changes = p.paragraphs_of("History.txt", 0..1).join("\n\n")
|
11
|
+
p.rubyforge_name = p.name # TODO this is default value
|
12
|
+
# p.extra_deps = [
|
13
|
+
# ['activesupport','>= 2.0.2'],
|
14
|
+
# ]
|
15
|
+
p.extra_dev_deps = [
|
16
|
+
['newgem', ">= #{::Newgem::VERSION}"]
|
17
|
+
]
|
18
|
+
|
19
|
+
p.clean_globs |= %w[**/.DS_Store tmp *.log]
|
20
|
+
path = (p.rubyforge_name == p.name) ? p.rubyforge_name : "\#{p.rubyforge_name}/\#{p.name}"
|
21
|
+
p.remote_rdoc_dir = File.join(path.gsub(/^#{p.rubyforge_name}\/?/,''), 'rdoc')
|
22
|
+
p.rsync_args = '-av --delete --ignore-errors'
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'newgem/tasks' # load /tasks/*.rake
|
26
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
27
|
+
|
28
|
+
# TODO - want other tests/tasks run by default? Add them to the list
|
29
|
+
# task :default => [:spec, :features]
|
@@ -0,0 +1,153 @@
|
|
1
|
+
require 'set'
|
2
|
+
|
3
|
+
class AppKernel
|
4
|
+
module Function
|
5
|
+
|
6
|
+
def apply(fun, *args)
|
7
|
+
FunctionApplication.new(fun, *args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.included(mod)
|
11
|
+
class << mod
|
12
|
+
def function(symbol, &definition)
|
13
|
+
fun = ::AppKernel::FunctionDefinition.new(definition)
|
14
|
+
self.const_set(symbol, fun)
|
15
|
+
self.send(:define_method, symbol) do |*args|
|
16
|
+
FunctionApplication.apply_or_die(fun, *args)
|
17
|
+
end
|
18
|
+
if self.class == Module
|
19
|
+
self.send(:module_function, symbol)
|
20
|
+
else
|
21
|
+
class << self;self;end.send(:define_method, symbol) do |*args|
|
22
|
+
FunctionApplication.apply_or_die(fun, *args)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def apply(fun, *args)
|
28
|
+
FunctionApplication.new(fun, *args)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class FunctionApplication
|
35
|
+
|
36
|
+
attr_reader :return_value, :errors, :function, :options
|
37
|
+
|
38
|
+
def initialize(fun, *args)
|
39
|
+
@function = fun
|
40
|
+
@args = args
|
41
|
+
@options = {}
|
42
|
+
@errors = {}
|
43
|
+
@return_value = self.class.do_apply(self, *args)
|
44
|
+
end
|
45
|
+
|
46
|
+
def successful?
|
47
|
+
@errors.empty?
|
48
|
+
end
|
49
|
+
|
50
|
+
class << self
|
51
|
+
|
52
|
+
def apply_or_die(fun, *args)
|
53
|
+
app = new(fun, *args)
|
54
|
+
if app.successful?
|
55
|
+
app.return_value
|
56
|
+
else
|
57
|
+
raise ValidationError, app
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def do_apply(app, *args)
|
62
|
+
fun = app.function
|
63
|
+
instance = Object.new
|
64
|
+
indexed_options = fun.indexed_options
|
65
|
+
required_options = Set.new(fun.options.values.select {|o| o.required?})
|
66
|
+
for arg in args do
|
67
|
+
if arg.kind_of?(Hash)
|
68
|
+
arg.each do |k,v|
|
69
|
+
if opt = fun.options[k.to_sym]
|
70
|
+
opt.set instance, v
|
71
|
+
required_options.delete opt
|
72
|
+
app.options[opt.name] = v
|
73
|
+
end
|
74
|
+
end
|
75
|
+
elsif opt = indexed_options.shift
|
76
|
+
opt.set instance, arg
|
77
|
+
required_options.delete opt
|
78
|
+
app.options[opt.name] = arg
|
79
|
+
end
|
80
|
+
end
|
81
|
+
for opt in required_options do
|
82
|
+
app.errors[opt.name] = "Missing required option '#{opt.name}'"
|
83
|
+
end
|
84
|
+
app.errors.merge! fun.validation.validate(app.options)
|
85
|
+
instance.instance_eval &fun.impl if app.successful?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class FunctionDefinition
|
91
|
+
|
92
|
+
attr_reader :impl, :options, :validation
|
93
|
+
|
94
|
+
def initialize(definition)
|
95
|
+
@options = {}
|
96
|
+
@impl = lambda {}
|
97
|
+
@validation = ::AppKernel::Validation::Validator.new
|
98
|
+
self.instance_eval &definition
|
99
|
+
end
|
100
|
+
|
101
|
+
def option(name, params = {})
|
102
|
+
name = name.to_sym
|
103
|
+
@options[name] = Option.new(name, params)
|
104
|
+
end
|
105
|
+
|
106
|
+
def indexed_options
|
107
|
+
@options.values.select {|o| o.index}.sort_by {|a| a.index}
|
108
|
+
end
|
109
|
+
|
110
|
+
def execute(&impl)
|
111
|
+
@impl = impl
|
112
|
+
end
|
113
|
+
|
114
|
+
def validate(&checks)
|
115
|
+
@validation = AppKernel::Validation::Validator.new(&checks)
|
116
|
+
end
|
117
|
+
|
118
|
+
class Option
|
119
|
+
attr_reader :name, :index
|
120
|
+
def initialize(name, params)
|
121
|
+
@name = name
|
122
|
+
@index = params[:index]
|
123
|
+
@required = params[:required] == true
|
124
|
+
end
|
125
|
+
|
126
|
+
def set(o, value)
|
127
|
+
o.instance_variable_set("@#{@name}", value)
|
128
|
+
end
|
129
|
+
|
130
|
+
def required?
|
131
|
+
@required
|
132
|
+
end
|
133
|
+
|
134
|
+
def optional?
|
135
|
+
!@required
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
class Validator
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
class ValidationError < StandardError
|
144
|
+
def initialize(application)
|
145
|
+
@app = application
|
146
|
+
end
|
147
|
+
|
148
|
+
def message
|
149
|
+
@app.errors.values.first
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
153
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'delegate'
|
2
|
+
module AppKernel::Validation
|
3
|
+
class Validator
|
4
|
+
|
5
|
+
attr_reader :errors
|
6
|
+
|
7
|
+
def initialize(&block)
|
8
|
+
@body = block
|
9
|
+
end
|
10
|
+
|
11
|
+
def validate(vars = {})
|
12
|
+
errors = {}
|
13
|
+
scope = Object.new
|
14
|
+
for k,v in vars do
|
15
|
+
val = case v
|
16
|
+
when nil
|
17
|
+
NilValue.new
|
18
|
+
when Fixnum
|
19
|
+
FixnumValue.new(v)
|
20
|
+
else
|
21
|
+
v.dup
|
22
|
+
end
|
23
|
+
val.extend Check
|
24
|
+
val.instance_eval do
|
25
|
+
@_add_validation_error = lambda {|message|
|
26
|
+
errors[k] = message
|
27
|
+
}
|
28
|
+
end
|
29
|
+
scope.instance_variable_set("@#{k}", val)
|
30
|
+
end
|
31
|
+
scope.instance_eval &@body if @body
|
32
|
+
errors
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
module Check
|
38
|
+
def check(condition, message)
|
39
|
+
unless condition
|
40
|
+
@_add_validation_error.call(message)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class NilValue < DelegateClass(NilClass)
|
46
|
+
def initialize
|
47
|
+
super(nil)
|
48
|
+
end
|
49
|
+
|
50
|
+
def nil?
|
51
|
+
true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
class FixnumValue < DelegateClass(Fixnum)
|
56
|
+
def initialize(val)
|
57
|
+
super(val)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/appkernel.rb
ADDED
data/script/console
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# File: script/console
|
3
|
+
irb = RUBY_PLATFORM =~ /(:?mswin|mingw)/ ? 'irb.bat' : 'irb'
|
4
|
+
|
5
|
+
libs = " -r irb/completion"
|
6
|
+
# Perhaps use a console_lib to store any extra methods I may want available in the cosole
|
7
|
+
# libs << " -r #{File.dirname(__FILE__) + '/../lib/console_lib/console_logger.rb'}"
|
8
|
+
libs << " -r #{File.dirname(__FILE__) + '/../lib/appkernel.rb'}"
|
9
|
+
puts "Loading appkernel gem"
|
10
|
+
exec "#{irb} #{libs} --simple-prompt"
|
data/script/destroy
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/destroy'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Destroy.new.run(ARGV)
|
data/script/generate
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
APP_ROOT = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'rubigen'
|
6
|
+
rescue LoadError
|
7
|
+
require 'rubygems'
|
8
|
+
require 'rubigen'
|
9
|
+
end
|
10
|
+
require 'rubigen/scripts/generate'
|
11
|
+
|
12
|
+
ARGV.shift if ['--help', '-h'].include?(ARGV[0])
|
13
|
+
RubiGen::Base.use_component_sources! [:rubygems, :newgem, :newgem_theme, :test_unit]
|
14
|
+
RubiGen::Scripts::Generate.new.run(ARGV)
|
@@ -0,0 +1,211 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe AppKernel::Function do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@mod = Module.new do |mod|
|
7
|
+
mod.module_eval do
|
8
|
+
include AppKernel::Function
|
9
|
+
end
|
10
|
+
end
|
11
|
+
extend @mod
|
12
|
+
@klass = Class.new.class_eval do
|
13
|
+
include AppKernel::Function; self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
it "allows modules to define an function functions" do
|
18
|
+
@mod.module_eval do
|
19
|
+
function :Say do
|
20
|
+
option :word
|
21
|
+
|
22
|
+
execute do
|
23
|
+
@word
|
24
|
+
end
|
25
|
+
end
|
26
|
+
Say(:word => "hello").should == "hello"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
it "allows certain options to be the default option" do
|
31
|
+
@mod.module_eval do
|
32
|
+
function :Say do
|
33
|
+
option :greeting, :index => 0
|
34
|
+
option :to, :index => 1
|
35
|
+
option :extra
|
36
|
+
|
37
|
+
execute do
|
38
|
+
"#{@greeting} #{@to}#{(', ' + @extra) if @extra}"
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
Say("Hello", "Charles", :extra => "How are you?").should == "Hello Charles, How are you?"
|
44
|
+
Say("Hello", "Charles").should == "Hello Charles"
|
45
|
+
Say(:greeting => "Hello", :to => "Charles").should == "Hello Charles"
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
it "allows classes that include the module to also use the commands from that module" do
|
50
|
+
@mod.module_eval do
|
51
|
+
function :Included do
|
52
|
+
execute do
|
53
|
+
"It worked!"
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
mod = @mod
|
58
|
+
Class.new(Object).class_eval do
|
59
|
+
include mod
|
60
|
+
self
|
61
|
+
end.new.instance_eval do
|
62
|
+
Included().should == "It worked!"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
it "allows classes to define functions as well as modules" do
|
67
|
+
@klass.class_eval do
|
68
|
+
function :Say do
|
69
|
+
option :word, :index => 1
|
70
|
+
execute do
|
71
|
+
@word
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
it "can be called by using the apply method instead of invoking it directly" do
|
78
|
+
@mod.module_eval do
|
79
|
+
function :FiveAlive do
|
80
|
+
option :desc, :index => 1
|
81
|
+
execute do
|
82
|
+
"FiveAlive is a #{@desc}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
result = apply(@mod::FiveAlive, "candy bar")
|
87
|
+
result.return_value.should == "FiveAlive is a candy bar"
|
88
|
+
result.successful?.should be(true)
|
89
|
+
end
|
90
|
+
|
91
|
+
it "can have required options, but they are never required by default" do
|
92
|
+
@mod.module_eval do
|
93
|
+
function :Say do
|
94
|
+
option :greeting, :index => 1, :required => true
|
95
|
+
option :to, :index => 2, :required => true
|
96
|
+
option :extra, :index => 3
|
97
|
+
end
|
98
|
+
end
|
99
|
+
result = apply(@mod::Say, "Hello", "World", "I'm doing fine.")
|
100
|
+
result.successful?.should be(true)
|
101
|
+
result = apply(@mod::Say)
|
102
|
+
result.return_value.should be(nil)
|
103
|
+
result.successful?.should be(false)
|
104
|
+
result.errors[:greeting].should_not be(nil)
|
105
|
+
result.errors[:to].should_not be(nil)
|
106
|
+
result.errors[:extra].should be(nil)
|
107
|
+
end
|
108
|
+
|
109
|
+
it "raises an error immediately if you try to call a function that has invalid arguments" do
|
110
|
+
@mod.module_eval do
|
111
|
+
function :Harpo do
|
112
|
+
option :mandatory, :required => true
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
lambda {
|
117
|
+
Harpo()
|
118
|
+
}.should raise_error(AppKernel::ValidationError)
|
119
|
+
end
|
120
|
+
|
121
|
+
it "allows validation of its arguments" do
|
122
|
+
@mod.module_eval do
|
123
|
+
function :Picky do
|
124
|
+
option :arg, :index => 1
|
125
|
+
validate do
|
126
|
+
@arg.check @arg == 5 && @arg != 6, "must be 5 and not be 6"
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
apply(@mod::Picky, 5).successful?.should be(true)
|
132
|
+
result = apply(@mod::Picky, 6)
|
133
|
+
result.successful?.should be(false)
|
134
|
+
result.errors[:arg].should == "must be 5 and not be 6"
|
135
|
+
|
136
|
+
result = apply(@mod::Picky, 7)
|
137
|
+
result.successful?.should be(false)
|
138
|
+
result.errors[:arg].should == "must be 5 and not be 6"
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
|
143
|
+
# module Awacs::Ssid
|
144
|
+
# include AppKernel::Function
|
145
|
+
#
|
146
|
+
# function :GetErrorCountBySource do
|
147
|
+
# option :solr, :nil => false
|
148
|
+
# option :source, :nil => false, :empty => false
|
149
|
+
#
|
150
|
+
# item = Struct.new(:source, :error_count)
|
151
|
+
# execute do
|
152
|
+
# @solr.query("sys_error_marker:(\"SSID-AUGMENTATION-ERROR\")",
|
153
|
+
# :filter_queries => ["PublicationTitle_t:[* TO *]"],
|
154
|
+
# :rows => 0,
|
155
|
+
# :facets => {:fields => "sys_source_id", :mincount => 1, :limit => 1000, :sort => "count"}
|
156
|
+
# ).data['facet_counts']['facet_fields']['sys_source_id'].enum_for(:each_slice, 2).map do |slice|
|
157
|
+
# item.new(*slice)
|
158
|
+
# end
|
159
|
+
# end
|
160
|
+
# end
|
161
|
+
#
|
162
|
+
# function :GetErrorCountByPublicationTitle do
|
163
|
+
# option :solr, :nil => false
|
164
|
+
# option :source, :nil => false, :empty => false
|
165
|
+
# option :title, :nil => false, :empty => false
|
166
|
+
#
|
167
|
+
# item = Struct.new(:title, :error_count)
|
168
|
+
#
|
169
|
+
# execute do
|
170
|
+
# @solr.query(%Q{sys_error_marker:("SSID-AUGMENT-FAILED")},
|
171
|
+
# :filter_queries => %Q{sys_source_id:("#{@source}")},
|
172
|
+
# :facets => {:fields => ['PublicationTitle_sfacet'], :mincount => 1, :limit => 1000, :sort => :count}
|
173
|
+
# ).data['facet_counts']['facet_fields']['PublicationTitle_sfacet'].enum_for(:each_slice, 2).map do |slice|
|
174
|
+
# item.new(*slice)
|
175
|
+
# end
|
176
|
+
# end
|
177
|
+
# end
|
178
|
+
#
|
179
|
+
#
|
180
|
+
# executeable :AddMapping do
|
181
|
+
# option :type, :nil => false, :type => SsidMatchType, :lookup => proc {|s| SsidMatchType.find_by_name s}
|
182
|
+
# option :value, :nil => false
|
183
|
+
# option :ssid, :nil => false
|
184
|
+
#
|
185
|
+
# execute do
|
186
|
+
# SsidMapping.create :match_rule => FindOrCreateRule(:type => @type, :value => @value), :ssid => @ssid
|
187
|
+
# end
|
188
|
+
# end
|
189
|
+
#
|
190
|
+
# function :DeleteMapping do
|
191
|
+
# option :mapping, :index => 1, :type => SsidMapping, :lookup => proc {|s| SsidMapping.find(s)}
|
192
|
+
#
|
193
|
+
# execute do
|
194
|
+
# @mapping.delete!
|
195
|
+
# end
|
196
|
+
# end
|
197
|
+
|
198
|
+
# function :SaveMappings do
|
199
|
+
# option :adds, :default => [], :massage => proc {|o| [o].flatten}
|
200
|
+
# option :deletes, :default => [], :massage => proc {|o| [o].flatten}
|
201
|
+
# end
|
202
|
+
#
|
203
|
+
# end
|
204
|
+
#
|
205
|
+
# #later on....
|
206
|
+
# include Awacs::Ssid
|
207
|
+
# GetErrorCountBySource :source => "proquest"
|
208
|
+
# GetErrorCountByPublicationTitle, :source => "proquest", :title => "Journal of Water Law"
|
209
|
+
# AddMapping :rule => {:match_type => 'ISSN', :match_value => '001287'}, :ssid => '123459'
|
210
|
+
# AddMapping :rule => 89, :ssid => 1234569
|
211
|
+
#
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper.rb'
|
2
|
+
|
3
|
+
describe AppKernel::Validation do
|
4
|
+
|
5
|
+
|
6
|
+
it "can do assertions which are associated with a field" do
|
7
|
+
validate({:foo => 'bar'}) do
|
8
|
+
@foo.check(!@foo.nil?, "'foo' cannot be nil")
|
9
|
+
end.should be_empty
|
10
|
+
|
11
|
+
validate({:foo => nil}) do
|
12
|
+
@foo.check(!@foo.nil?, "cannot be nil.")
|
13
|
+
end[:foo].should == "cannot be nil."
|
14
|
+
end
|
15
|
+
|
16
|
+
it "returns a positive result if there is no validation body passed" do
|
17
|
+
validate().should be_empty
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
it "can validate fixnum fields fixnums" do
|
22
|
+
validate({:num => 5}) do
|
23
|
+
@num.check(@num < 5, "too big number!")
|
24
|
+
end[:num].should == "too big number!"
|
25
|
+
end
|
26
|
+
|
27
|
+
def validate(vars = {}, &block)
|
28
|
+
v = AppKernel::Validation::Validator.new(&block)
|
29
|
+
v.validate vars
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/spec/spec.opts
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/spec/spec_helper.rb
ADDED
data/tasks/rspec.rake
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
begin
|
2
|
+
require 'spec'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems' unless ENV['NO_RUBYGEMS']
|
5
|
+
require 'spec'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'spec/rake/spectask'
|
9
|
+
rescue LoadError
|
10
|
+
puts <<-EOS
|
11
|
+
To use rspec for testing you must install rspec gem:
|
12
|
+
gem install rspec
|
13
|
+
EOS
|
14
|
+
exit(0)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "Run the specs under spec/models"
|
18
|
+
Spec::Rake::SpecTask.new do |t|
|
19
|
+
t.spec_opts = ['--options', "spec/spec.opts"]
|
20
|
+
t.spec_files = FileList['spec/**/*_spec.rb']
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: appkernel
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Charles Lowell
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-29 00:00:00 -05:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: newgem
|
17
|
+
type: :development
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.4.1
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: hoe
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 1.8.0
|
34
|
+
version:
|
35
|
+
description: |-
|
36
|
+
AppKernel is a microframework for capturing your application in terms of minute, self-validating functions.
|
37
|
+
Once defined, these functions can be used in rails, cocoa, an sms gateway, or wherever you want to take them.
|
38
|
+
email:
|
39
|
+
- cowboyd@thefrontside.net
|
40
|
+
executables: []
|
41
|
+
|
42
|
+
extensions: []
|
43
|
+
|
44
|
+
extra_rdoc_files:
|
45
|
+
- History.txt
|
46
|
+
- Manifest.txt
|
47
|
+
- README.rdoc
|
48
|
+
files:
|
49
|
+
- History.txt
|
50
|
+
- Manifest.txt
|
51
|
+
- README.rdoc
|
52
|
+
- Rakefile
|
53
|
+
- lib/appkernel.rb
|
54
|
+
- lib/appkernel/function.rb
|
55
|
+
- lib/appkernel/validation.rb
|
56
|
+
- script/console
|
57
|
+
- script/destroy
|
58
|
+
- script/generate
|
59
|
+
- spec/appkernel/function_spec.rb
|
60
|
+
- spec/appkernel/validation_spec.rb
|
61
|
+
- spec/spec.opts
|
62
|
+
- spec/spec_helper.rb
|
63
|
+
- tasks/rspec.rake
|
64
|
+
has_rdoc: true
|
65
|
+
homepage: http://github.com/cowboyd/appkernel
|
66
|
+
licenses: []
|
67
|
+
|
68
|
+
post_install_message:
|
69
|
+
rdoc_options:
|
70
|
+
- --main
|
71
|
+
- README.rdoc
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
requirements:
|
76
|
+
- - ">="
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: "0"
|
79
|
+
version:
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
version: "0"
|
85
|
+
version:
|
86
|
+
requirements: []
|
87
|
+
|
88
|
+
rubyforge_project: appkernel
|
89
|
+
rubygems_version: 1.3.4
|
90
|
+
signing_key:
|
91
|
+
specification_version: 3
|
92
|
+
summary: AppKernel is a microframework for capturing your application in terms of minute, self-validating functions
|
93
|
+
test_files: []
|
94
|
+
|