Checked 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Checked.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "Checked/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "Checked"
7
+ s.version = Checked::VERSION
8
+ s.authors = ["da99"]
9
+ s.email = ["i-hate-spam-45671204@mailinator.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Check your types and more.}
12
+ s.description = %q{
13
+ Various DSLs to clean, question (Ask), and validate (Demand) your objects,
14
+ their classes (data types), and their properties.
15
+ }
16
+
17
+ s.rubyforge_project = "Checked"
18
+
19
+ s.files = `git ls-files`.split("\n")
20
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
21
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
22
+ s.require_paths = ["lib"]
23
+
24
+ # specify any dependencies here; for example:
25
+ # s.add_development_dependency "rspec"
26
+ # s.add_runtime_dependency "rest-client"
27
+ s.add_development_dependency 'rake'
28
+ s.add_development_dependency 'bacon'
29
+ s.add_development_dependency 'Bacon_Colored'
30
+ end
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in Checked.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 da99
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,19 @@
1
+ = Checked
2
+
3
+ Check types and more in your code.
4
+
5
+ == Contributing to Checked
6
+
7
+ * Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
8
+ * Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
9
+ * Fork the project
10
+ * Start a feature/bugfix branch
11
+ * Commit and push until you are happy with your contribution
12
+ * Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
13
+ * Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
14
+
15
+ == Copyright
16
+
17
+ Copyright (c) 2011 da99. See LICENSE.txt for
18
+ further details.
19
+
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,55 @@
1
+
2
+ module Checked
3
+
4
+ class Args
5
+
6
+ Unknown_Class = Class.new(RuntimeError)
7
+
8
+ module Base
9
+
10
+ def initialize *arr
11
+ arr.flatten.each { |var|
12
+ case var
13
+ when Array
14
+ var.each { |k|
15
+ define k
16
+ }
17
+ when Hash
18
+ var.each { |k,v|
19
+ define k
20
+ send("#{k}=", v)
21
+ }
22
+ else
23
+ raise Unknown_Class, var.inspect
24
+ end
25
+ }
26
+ end
27
+
28
+ def define *raw
29
+ raw.flatten.each { |k|
30
+ eval %~
31
+
32
+ def #{k}
33
+ @#{k}
34
+ end
35
+
36
+ def #{k}= v
37
+ @#{k} = v
38
+ end
39
+
40
+ ~
41
+ }
42
+ end
43
+
44
+ def defined? key
45
+ respond_to?( key ) &&
46
+ respond_to?( :"#{key}=" )
47
+ end
48
+
49
+ end # === module Base
50
+
51
+ include Base
52
+
53
+ end # === module Args
54
+
55
+ end # === module Checked
@@ -0,0 +1,31 @@
1
+ require 'Checked/Demand/DSL'
2
+
3
+ module Checked
4
+ class Ask
5
+ module DSL
6
+
7
+ include Demand::DSL
8
+
9
+ def ask? target, *args
10
+ Checked::Ask.new(target) { |a|
11
+ a.<< args
12
+ }.true?
13
+ end
14
+
15
+ def true? target, *args
16
+ demand! block_given?, :no_block!
17
+ q = Ask.new(target)
18
+ q << args
19
+ q.true?
20
+ end
21
+
22
+ def any? target, *args
23
+ demand! block_given?, :no_block!
24
+ q = Ask.new(target)
25
+ q << args
26
+ q.any?
27
+ end
28
+
29
+ end # === module DSL
30
+ end # === class Ask
31
+ end # === module Checked
@@ -0,0 +1,25 @@
1
+
2
+
3
+ module Checked
4
+ class Ask
5
+ module Mods
6
+ module Arrays
7
+
8
+ def self.apply?(d)
9
+ d.target.is_a?(Array)
10
+ end
11
+
12
+ def symbols?
13
+ valid! target, :array!
14
+ return false if target.empty?
15
+ target.all? { |val| val.is_a? Symbol }
16
+ end
17
+
18
+ def excludes? matcher
19
+ !target.includes?(matcher)
20
+ end
21
+
22
+ end # === module Arrays
23
+ end # === module Mods
24
+ end # === class Ask
25
+ end # === class Checked
@@ -0,0 +1,26 @@
1
+
2
+ module Checked
3
+ class Ask
4
+ module Mods
5
+ module Strings
6
+
7
+ def self.apply? d
8
+ d.target.is_a?(String)
9
+ end
10
+
11
+ def empty?
12
+ target.strip.empty?
13
+ end
14
+
15
+ def includes? matcher
16
+ !!target[matcher]
17
+ end
18
+
19
+ def excludes? matcher
20
+ !includes?(matcher)
21
+ end
22
+
23
+ end # === module Strings
24
+ end # === module Mods
25
+ end # === class Ask
26
+ end # === module Checked
@@ -0,0 +1,12 @@
1
+
2
+ module Checked
3
+ class Ask
4
+ module Mods
5
+ module Vars
6
+
7
+
8
+
9
+ end # === module Vars
10
+ end # === module Mods
11
+ end # === class Ask
12
+ end # === module Checked
@@ -0,0 +1,69 @@
1
+ require 'Checked/Base'
2
+ require 'Checked/Ask/DSL'
3
+
4
+ module Checked
5
+ class Ask
6
+ module Base
7
+
8
+ private # ==============================
9
+
10
+ include ::Checked::Base
11
+
12
+ #
13
+ # Demand::DSL is not used here
14
+ # because it uses the Questioner.
15
+ # It would cause an stack level/infinite loop
16
+ # error.
17
+ #
18
+ def valid! target, *args
19
+ v = Demand.new(target)
20
+ if args.empty?
21
+ yield v
22
+ else
23
+ raise "No block allowed with arguments: #{args.inspect}" if block_given?
24
+ v << args
25
+ end
26
+
27
+ v.target
28
+ end
29
+
30
+ public # ==============================
31
+
32
+ attr_reader :records
33
+
34
+ def before_init
35
+ @records = []
36
+ end
37
+
38
+ def < name, *args, &blok
39
+ a = super
40
+ valid!(a, :bool!)
41
+ records << a
42
+ a
43
+ end
44
+
45
+ def << *methods
46
+ valid! block_given?, :no_block!
47
+ super(*methods) { |name|
48
+ self.< name
49
+ }
50
+ end
51
+
52
+ def true?
53
+ return false if records.empty?
54
+ records.all?
55
+ end
56
+
57
+ def any?
58
+ return false if records.empty?
59
+ records.any?
60
+ end
61
+
62
+ private # ==============================
63
+
64
+
65
+ end # === module Base
66
+
67
+ include Base
68
+ end # === class Ask
69
+ end # === module Checked
@@ -0,0 +1,119 @@
1
+
2
+ module Checked
3
+ module Base
4
+
5
+ def self.included var
6
+ klass_name = var.to_s.gsub(/::Base$/, '').split('::').last
7
+ klass = Checked.const_get(klass_name)
8
+
9
+ files = Dir.glob(File.join File.dirname(__FILE__), "#{klass_name}/Mods/*.rb")
10
+ raise "No Mods found for #{klass}" if files.empty?
11
+
12
+ files.each { |path|
13
+ name = File.basename(path).sub('.rb', '')
14
+ require "Checked/#{klass_name}/Mods/#{name}"
15
+ if name == 'Vars'
16
+ klass.class_eval {
17
+ include klass::Mods::Vars
18
+ }
19
+ else
20
+ klass.const_set(:Mod_List, []) unless klass.const_defined?(:Mod_List)
21
+ klass::Mod_List << klass::Mods.const_get(name)
22
+ end
23
+ }
24
+ end
25
+
26
+ attr_accessor :target
27
+ attr_reader :target_name
28
+
29
+ def initialize target, &blok
30
+
31
+ if respond_to? :before_init
32
+ if method(:before_init).parameters === []
33
+ before_init
34
+ else
35
+ before_init target, &blok
36
+ end
37
+ end
38
+
39
+ @target = target
40
+ @target_name = target.respond_to?(:english_name) ?
41
+ target.english_name :
42
+ "#{target.class.name.gsub('_', ' ')}, #{target.inspect},"
43
+
44
+ self.class.const_get(:Mod_List).each { |mod|
45
+ if mod.apply?(self)
46
+ extend mod
47
+ end
48
+ }
49
+
50
+ if respond_to? :after_init
51
+ if method(:after_init).parameters === []
52
+ after_init
53
+ else
54
+ after_init target, &blok
55
+ end
56
+ end
57
+
58
+ yield(self) if block_given?
59
+ end
60
+
61
+ #
62
+ # Sets the name.
63
+ #
64
+ def * name
65
+ @target_name = "#{name}, #{target.inspect},"
66
+ self
67
+ end
68
+
69
+ #
70
+ # ::Checked::Demand => demand
71
+ # ::Checked::Clean => clean
72
+ # ::Checked::Ask => ask
73
+ #
74
+ def purpose
75
+ @purpose ||= self.class.name.split('::').last.downcase.sub(/er$/, '')
76
+ end
77
+
78
+ def < name, *args, &blok
79
+ send(name, *args, &blok)
80
+ end
81
+
82
+ def << *methods
83
+ meths = begin
84
+ ::Checked::Demand.new(methods.flatten) { |d|
85
+ d.* "(Originally: #{target_name})"
86
+ d.instance_eval { not_empty!; symbols! }
87
+ }.target
88
+ end
89
+
90
+
91
+ meths.each { |name|
92
+
93
+ begin
94
+ if block_given?
95
+ yield name
96
+ else
97
+ send name
98
+ end
99
+ rescue NoMethodError => e
100
+ raise e if !e.message[/undefined method `#{name.to_s}' for/]
101
+ to_name = lambda { |m| m.to_s.split('::').last }
102
+ mods = self.class::Mod_List.select { |m| m.instance_methods.include?(name.to_sym) }
103
+ all = self.class::Mod_List
104
+
105
+ if mods.empty?
106
+ e_msg = e.message
107
+ raise NoMethodError, "#{e_msg} using mods: #{all.map(&to_name).join(', ')}"
108
+ else
109
+ raise NoMethodError, err_msg(
110
+ "...can not #{purpose} #{name}, which is found in: #{mods.map(&to_name).join(', ')}"
111
+ )
112
+ end
113
+ end
114
+ }
115
+ self
116
+ end
117
+
118
+ end # === module Base
119
+ end # === module Checked
@@ -0,0 +1,16 @@
1
+
2
+ module Checked
3
+ class Clean
4
+ module DSL
5
+
6
+ def clean target, *args
7
+ raise "No block allowed here." if block_given?
8
+
9
+ c = Clean.new(target)
10
+ c.<(*args)
11
+ c.target
12
+ end
13
+
14
+ end # === module DSL
15
+ end # === class Clean
16
+ end # === module Checked
@@ -0,0 +1,98 @@
1
+
2
+ module Checked
3
+ class Clean
4
+ module Mods
5
+ module Strings
6
+
7
+ def self.apply? d
8
+ d.target.is_a?(String) ||
9
+ d.target.is_a?(StringIO)
10
+ end
11
+
12
+ def self.on_apply d
13
+ case d.target
14
+ when StringIO
15
+ d.target.rewind
16
+ d.target= d.target.readlines
17
+ else
18
+ # Do nothing.
19
+ end
20
+ end
21
+
22
+ def file_names matcher
23
+ strip.split.select { |word| word[matcher] }
24
+ end
25
+
26
+ def file_names_by_ext ext
27
+ names = file_names(ext)
28
+ bases = names.map { |s|
29
+ s.sub(%r!#{ext}$!, '')
30
+ }
31
+
32
+ names.zip bases
33
+ end
34
+
35
+ def shell
36
+ target
37
+ .strip
38
+ .split("\n")
39
+ .map(&:strip)
40
+ .reject { |line| line.empty? }
41
+ .join(' && ')
42
+ end
43
+
44
+ def chop_ext
45
+ target.sub /\.[^\.]+$/, ''
46
+ end
47
+
48
+ def ruby_name
49
+ c = ::Checked::Clean.new( File.basename( target ) )
50
+ c.< :chop_rb
51
+ c.target
52
+ end
53
+
54
+ def chop_rb
55
+ target.sub %r!\.rb$!, ''
56
+ end
57
+
58
+ def chop_slash_r
59
+ target.gsub "\r", ''
60
+ end
61
+
62
+ def os_stardard
63
+ chop_slash_r.strip
64
+ end
65
+
66
+ def file_names matcher
67
+ strip.split.select { |word| word[matcher] }
68
+ end
69
+
70
+ def file_names_by_ext ext
71
+ names = file_names(ext)
72
+ bases = names.map { |s|
73
+ s.sub(%r!#{ext}$!, '')
74
+ }
75
+
76
+ names.zip bases
77
+ end
78
+
79
+ def to_single
80
+ target.gsub( /s\Z/, '' )
81
+ end
82
+
83
+ def to_plural
84
+ target.to_single + 's'
85
+ end
86
+
87
+ def to_class_name
88
+ target.split('_').map(&:capitalize).join('_')
89
+ end
90
+
91
+ def to_camel_case
92
+ target.split('_').map(&:capitalize).join
93
+ end
94
+
95
+ end # === module Strings
96
+ end # === module Mods
97
+ end # === class Clean
98
+ end # === module Checked
@@ -0,0 +1,41 @@
1
+ require "Checked/Base"
2
+ require "Checked/Clean/DSL"
3
+ require "Checked/Demand/DSL"
4
+
5
+ module Checked
6
+ class Clean
7
+ module Base
8
+
9
+ private # =============================
10
+ include ::Checked::Demand::DSL
11
+
12
+ public # ==============================
13
+ include ::Checked::Base
14
+
15
+ def < meth, *args
16
+ val = super
17
+ named_demand!("Cleaned val", val, :not_nil!)
18
+
19
+ self.target= super
20
+ end
21
+
22
+ def << *args
23
+ args.flatten.each { |name|
24
+ self.< name
25
+ }
26
+ end
27
+
28
+ private # ===========================================
29
+
30
+ def target= val
31
+ named_demand! "Clean target", val, :not_nil!
32
+
33
+ @target = val
34
+ end
35
+
36
+ end # === module Base
37
+
38
+ include Base
39
+
40
+ end # === class Clean
41
+ end # === class Checked
@@ -0,0 +1,29 @@
1
+
2
+ module Checked
3
+ class Demand
4
+ module DSL
5
+
6
+ def demand! target, *args
7
+ if block_given?
8
+ raise "No block allowed here."
9
+ end
10
+
11
+ Demand.new(target) { |d|
12
+ d.<< args
13
+ }.target
14
+ end
15
+
16
+ def named_demand! name, target, *args
17
+ if block_given?
18
+ raise "No block allowed here."
19
+ end
20
+
21
+ Demand.new(target) { |d|
22
+ d.* name
23
+ d.<< args
24
+ }.target
25
+ end
26
+
27
+ end # === module Dsl
28
+ end # === class Demand
29
+ end # === module Checked
@@ -0,0 +1,72 @@
1
+
2
+ module Checked
3
+ class Demand
4
+ module Mods
5
+ module Arrays
6
+
7
+ def self.before_apply d
8
+ end
9
+
10
+ def self.apply? d
11
+ d.target.is_a?(Array)
12
+ end
13
+
14
+ def self.after_apply d
15
+ end
16
+
17
+ def no_nils!
18
+ array!
19
+ if target.include?(nil)
20
+ fail!("...can't contain nils.")
21
+ end
22
+ end
23
+
24
+ def no_empty_strings!
25
+ array!
26
+ target.each { |s|
27
+
28
+ if s.respond_to?(:rewind)
29
+ s.rewind
30
+ end
31
+
32
+ final = if s.respond_to?(:readlines)
33
+ s.readlines
34
+ else
35
+ s
36
+ end
37
+
38
+ if final.is_a?(String) && final.strip.empty?
39
+ fail!("...can't contain empty strings.")
40
+ end
41
+ }
42
+ end
43
+
44
+ def symbols!
45
+ array!
46
+ not_empty!
47
+ if !target.all? { |v| v.is_a?(Symbol) }
48
+ fail! "...contains a non-symbol."
49
+ end
50
+ end
51
+
52
+ def include! matcher
53
+ included = target.include?(matcher)
54
+ return true if included
55
+ fail!("...must contain: #{matcher.inspect}")
56
+ end
57
+
58
+ def exclude! matcher
59
+ raise_e = val.include?(matcher)
60
+ return true unless raise_e
61
+ fail!("...can't contain #{matcher.inspect}")
62
+ end
63
+
64
+ def matches_only! matcher
65
+ arr = target.reject { |val| val == matcher }
66
+ fail!( "...invalid elements: #{arr.inspect}" ) if !arr.empty?
67
+ end
68
+
69
+ end # === module Arrays
70
+ end # === module Mods
71
+ end # === class Demand
72
+ end # === module Checked