fact_checker 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ coverage
6
+ .DS_Store
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.9.2@fact_checker 2>/dev/null
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in fact_checker.gemspec
4
+ gemspec
data/README ADDED
@@ -0,0 +1,23 @@
1
+ 1. What is FactChecker
2
+
3
+ Simple ruby gem to check hierarchically dependent "facts" about objects.
4
+
5
+ 2. Getting started
6
+
7
+ 2.1 Installation
8
+
9
+ gem install fact_checker
10
+
11
+ 2.2 Usage
12
+
13
+ https://github.com/alexis/fact_checker/tree/master/examples
14
+
15
+ 3. Development / Contributing
16
+
17
+ 3.1 Testing code with rspec
18
+
19
+ rake spec
20
+
21
+ 3.2 Testing code coverage with rcov for ruby 1.8
22
+
23
+ rcov -Ilib:spec --exclude gem spec/fact_checker_spec.rb
data/Rakefile ADDED
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rake'
4
+ require 'bundler'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ Dir['lib/tasks/**/*.rake'].
9
+ concat(Dir['tasks/**/*.rake']).
10
+ concat(Dir['{test,spec}/*.rake']).each { |rake| load(rake) }
11
+
12
+ task :default => :spec
13
+ task :test => :spec # for http://test.rubygems.org/
@@ -0,0 +1,72 @@
1
+ # FactChecker / Examples
2
+
3
+ ## How to run
4
+
5
+ ``` ruby
6
+ bundle exec ruby -rubygems examples/basic.rb
7
+ ```
8
+
9
+ ## BasicExample
10
+
11
+ ``` ruby
12
+ # encoding: utf-8
13
+
14
+ require 'fact_checker'
15
+
16
+ class BasicExample
17
+ include FactChecker
18
+
19
+ def_fact :be
20
+ def_fact :be_or => :be
21
+ def_fact :be_or_not => :be, :if => :my_requirement?
22
+ def_fact :be_or_not_to => [:be, :be_or_not], :if => :my_requirement?
23
+ def_fact :be_or_not_to_be => :be, :if => lambda { |context| !context.my_requirement? }
24
+ end
25
+
26
+ target = BasicExample.new
27
+
28
+ def target.my_requirement?; false end
29
+
30
+ p target.fact_possible? :be
31
+ # => true
32
+ p target.fact_accomplished? :be
33
+ # => true
34
+ p target.be?
35
+ # => true
36
+
37
+ puts
38
+
39
+ p target.fact_possible? :be_or
40
+ # => true
41
+ p target.fact_accomplished? :be_or
42
+ # => true
43
+ p target.be_or?
44
+ # => true
45
+
46
+ puts
47
+
48
+ p target.fact_possible? :be_or_not
49
+ # => true
50
+ p target.fact_accomplished? :be_or_not
51
+ # => false
52
+ p target.be_or_not?
53
+ # => false
54
+
55
+ puts
56
+
57
+ p target.fact_possible? :be_or_not_to
58
+ # => false
59
+ p target.fact_accomplished? :be_or_not_to
60
+ # => false
61
+ p target.be_or_not_to?
62
+ # => false
63
+
64
+ puts
65
+
66
+ p target.fact_possible? :be_or_not_to_be
67
+ # => true
68
+ p target.fact_accomplished? :be_or_not_to_be
69
+ # => true
70
+ p target.be_or_not_to_be?
71
+ # => true
72
+ ```
data/examples/basic.rb ADDED
@@ -0,0 +1,60 @@
1
+ # encoding: utf-8
2
+
3
+ require 'fact_checker'
4
+
5
+ class BasicExample
6
+ include FactChecker
7
+
8
+ def_fact :be
9
+ def_fact :be_or => :be
10
+ def_fact :be_or_not => :be, :if => :my_requirement?
11
+ def_fact :be_or_not_to => [:be, :be_or_not], :if => :my_requirement?
12
+ def_fact :be_or_not_to_be => :be, :if => lambda { |context| !context.my_requirement? }
13
+ end
14
+
15
+ target = BasicExample.new
16
+
17
+ def target.my_requirement?; false end
18
+
19
+ p target.fact_possible? :be
20
+ # => true
21
+ p target.fact_accomplished? :be
22
+ # => true
23
+ p target.be?
24
+ # => true
25
+
26
+ puts
27
+
28
+ p target.fact_possible? :be_or
29
+ # => true
30
+ p target.fact_accomplished? :be_or
31
+ # => true
32
+ p target.be_or?
33
+ # => true
34
+
35
+ puts
36
+
37
+ p target.fact_possible? :be_or_not
38
+ # => true
39
+ p target.fact_accomplished? :be_or_not
40
+ # => false
41
+ p target.be_or_not?
42
+ # => false
43
+
44
+ puts
45
+
46
+ p target.fact_possible? :be_or_not_to
47
+ # => false
48
+ p target.fact_accomplished? :be_or_not_to
49
+ # => false
50
+ p target.be_or_not_to?
51
+ # => false
52
+
53
+ puts
54
+
55
+ p target.fact_possible? :be_or_not_to_be
56
+ # => true
57
+ p target.fact_accomplished? :be_or_not_to_be
58
+ # => true
59
+ p target.be_or_not_to_be?
60
+ # => true
@@ -0,0 +1,29 @@
1
+ # encoding: utf-8
2
+
3
+ $:.push File.expand_path("../lib", __FILE__)
4
+ require "fact_checker/version"
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = "fact_checker"
8
+ s.version = FactChecker::VERSION
9
+ s.platform = Gem::Platform::RUBY
10
+ s.authors = ["Alexey Smolianinov", "Ivan Povalyukhin"]
11
+ s.email = ["alexisowl+fact_checker@gmail.com"]
12
+ s.homepage = "https://github.com/alexis/fact_checker"
13
+ s.summary = %q{Checks facts which may depend on other facts}
14
+ s.description = %q{Simple gem to check hierarchically dependent "facts" about objects}
15
+
16
+ s.rubyforge_project = "fact_checker"
17
+
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
20
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
21
+ s.require_paths = ["lib"]
22
+
23
+ s.required_ruby_version = ">= 1.8.7"
24
+ s.required_rubygems_version = ">= 1.3.5"
25
+
26
+ s.add_development_dependency 'rspec', '~> 2.6'
27
+ s.add_development_dependency 'rake'
28
+ s.add_development_dependency 'bundler'
29
+ end
@@ -0,0 +1,78 @@
1
+ # encoding: utf-8
2
+
3
+ module FactChecker
4
+ class Base
5
+ attr_accessor :facts, :dependencies, :requirements
6
+
7
+ def initialize(facts = nil, deps = nil, reqs = nil)
8
+ @facts = facts || []
9
+ @dependencies = deps || {}
10
+ @requirements = reqs || {}
11
+ end
12
+
13
+ def initialize_copy(orig)
14
+ super
15
+ @facts = orig.facts.dup
16
+ @dependencies = orig.dependencies.dup
17
+ @requirements = orig.requirements.dup
18
+ end
19
+
20
+ def accomplished_facts(context)
21
+ facts.select{ |fact| fact_accomplished?(context, fact) }
22
+ end
23
+ def possible_facts(context)
24
+ facts.select{ |fact| fact_possible?(context, fact) }
25
+ end
26
+
27
+ # Checks if requirement and dependency for the fact are satisfied
28
+ def fact_accomplished?(context, fact)
29
+ fact_possible?(context, fact) && requirement_satisfied_for?(context, fact)
30
+ end
31
+
32
+ # Checks if dependency for the fact is satisfied
33
+ def fact_possible?(context, fact)
34
+ [* @dependencies[fact] || []].all?{ |dep| fact_accomplished?(context, dep) }
35
+ end
36
+
37
+ # Checks if requirement for the fact is satisfied (no dependency checks here)
38
+ def requirement_satisfied_for?(context, fact)
39
+ return false unless @facts.include?(fact)
40
+
41
+ case req = @requirements[fact]
42
+ when Symbol then context.send(req)
43
+ when Proc then req.arity < 1 ? req.call : req.call(context)
44
+ when NilClass then true
45
+ else raise RuntimeError, "can't check this fact - wrong requirement"
46
+ end
47
+ end
48
+
49
+ # Syntactic sugar, adds fact with its requirement and dependency. Examples:
50
+ # - def_fact(:fact)
51
+ # - def_fact(:fact, :if => :requirement)
52
+ # - def_fact(:fact => :dependency)
53
+ # - def_fact(:fact => :dependency, :if => :requirement)
54
+ def def_fact(*opt)
55
+ raise ArgumentError, "wrong number of arguments (#{opt.size} for 2)" if opt.size > 2
56
+ raise ArgumentError, "wrong number of arguments (0 for 1)" if opt.size == 0
57
+
58
+ if opt[0].is_a?(Hash)
59
+ raise ArgumentError, "wrong arguments (hash argument can only be the last one)" if opt.size > 1
60
+ hash = opt[0]
61
+ else
62
+ raise ArgumentError, "wrong arguments (second argument must be a hash)" if opt[1] && ! opt[1].is_a?(Hash)
63
+ hash = (opt[1] || {}).merge(opt[0] => nil)
64
+ end
65
+
66
+ req = hash.delete(:if)
67
+ fact = hash.keys.first
68
+ dep = hash.delete(fact)
69
+
70
+ raise ArgumentError, "wrong arguments: #{hash.keys.join(', ')}" if hash.size > 0
71
+
72
+ @requirements[fact] = req
73
+ @dependencies[fact] = dep
74
+ @facts |= [fact]
75
+ fact
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,5 @@
1
+ # encoding: utf-8
2
+
3
+ module FactChecker
4
+ VERSION = "0.0.1"
5
+ end
@@ -0,0 +1,31 @@
1
+ # encoding: utf-8
2
+
3
+ require "fact_checker/base"
4
+ require "fact_checker/version"
5
+
6
+ module FactChecker
7
+ def self.included(klass)
8
+ klass.extend ClassMethods
9
+ end
10
+
11
+ module ClassMethods
12
+ def inherited(child)
13
+ child.instance_variable_set('@fact_checker', fact_checker.dup)
14
+ end
15
+
16
+ def def_fact(*opts)
17
+ fact_name = fact_checker.def_fact(*opts)
18
+ define_method(fact_name.to_s << '?') { fact_accomplished?(fact_name) }
19
+ end
20
+
21
+ def fact_checker
22
+ @fact_checker ||= FactChecker::Base.new
23
+ end
24
+ end
25
+
26
+ # Delegate methods to self.class.fact_checker
27
+ [:fact_accomplished?, :fact_possible?, :accomplished_facts, :possible_facts].each do |name|
28
+ define_method(name) { |*opts| self.class.fact_checker.send(name, self, *opts) }
29
+ end
30
+ def facts; self.class.fact_checker.facts; end
31
+ end
@@ -0,0 +1,180 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FactChecker::Base do
6
+ describe "constructor" do
7
+ it "should accept facts, dependencies and requirements as arguments" do
8
+ fc = FactChecker::Base.new([:a, :b], {:a => :b}, {:b => :nil?})
9
+ fc.facts.should == [:a, :b]
10
+ fc.dependencies.should == {:a => :b}
11
+ fc.requirements.should == {:b => :nil?}
12
+ end
13
+ it "should use empty hash as a default for requirements" do
14
+ fc = FactChecker::Base.new([:a, :b], {:a => :b})
15
+ fc.requirements.should == {}
16
+ end
17
+ it "should use empty hash as a default for dependencies" do
18
+ fc = FactChecker::Base.new([:a, :b])
19
+ fc.dependencies.should == {}
20
+ end
21
+ it "should use empty array as a default for facts" do
22
+ fc = FactChecker::Base.new()
23
+ fc.facts.should == []
24
+ end
25
+ end
26
+
27
+ describe "#facts" do
28
+ it "should return all facts" do
29
+ fc = FactChecker::Base.new([:f1, :f2])
30
+ fc.facts.should == [:f1, :f2]
31
+ end
32
+ end
33
+
34
+ describe "#accomplished_facts" do
35
+ it "should return accomplished facts" do
36
+ fc = FactChecker::Base.new([:f1, :f2], nil, {:f2 => lambda{ false }})
37
+ fc.accomplished_facts("context").should == [:f1]
38
+ end
39
+ end
40
+
41
+ describe "#possible_facts" do
42
+ it "should return possible facts" do
43
+ fc = FactChecker::Base.new([:f1, :f2], {:f1 => :f2}, {:f2 => lambda{ false }})
44
+ fc.possible_facts("context").should == [:f2]
45
+ end
46
+ end
47
+
48
+ describe "#requirement_satisfied_for?" do
49
+ it "should return true if no requerment defined for the step" do
50
+ fc = FactChecker::Base.new([:f1])
51
+ fc.requirement_satisfied_for?(1, :f1).should be_true
52
+ end
53
+ it "should return false if fact is unknown" do
54
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => :nil?})
55
+ fc.requirement_satisfied_for?(1, :f2).should be_false
56
+ end
57
+ it "should return false if requirement is :symbol and context.symbol() == false" do
58
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => :nil?})
59
+ fc.requirement_satisfied_for?(1, :f1).should be_false
60
+ end
61
+ it "should return true if requirement is :symbol and context.symbol() == true" do
62
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => :nil?})
63
+ fc.requirement_satisfied_for?(nil, :f1).should be_true
64
+ end
65
+ it "should return false if requirement is Proc and proc(context) == false" do
66
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => lambda{|t| t.nil?}})
67
+ fc.requirement_satisfied_for?(1, :f1).should be_false
68
+ end
69
+ it "should return true if requirement is Proc and proc(context) == true" do
70
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => lambda{|t| t.nil?}})
71
+ fc.requirement_satisfied_for?(nil, :f1).should be_true
72
+ end
73
+ it "should return false if requirement is Proc with arity < 1 and proc() == false" do
74
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => lambda{false}})
75
+ fc.requirement_satisfied_for?(nil, :f1).should be_false
76
+ end
77
+ it "should return true if requirement is Proc with arity < 1 and proc() == true" do
78
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => lambda{true}})
79
+ fc.requirement_satisfied_for?(nil, :f1).should be_true
80
+ end
81
+ it "should raise RuntimeError if requirement has wrong type" do
82
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => "wrong"})
83
+ lambda{fc.requirement_satisfied_for?(nil, :f1)}.should raise_error(RuntimeError)
84
+ end
85
+ end
86
+
87
+ describe "#fact_accomplished?" do
88
+ it "should return false if fact is unknown" do
89
+ fc = FactChecker::Base.new([:f2], nil, {:f1 => :nil?})
90
+ fc.fact_accomplished?(nil, :f1).should be_false
91
+ end
92
+ it "should return true if requirement satisfied and fact has no dependencies" do
93
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => lambda{|o| o.size > 2}})
94
+ fc.fact_accomplished?("name", :f1).should be_true
95
+ end
96
+ it "should return false if requirement not satisfied (fact has no dependencies)" do
97
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => :nil?})
98
+ fc.fact_accomplished?("something", :f1).should be_false
99
+ end
100
+ it "should return false if fact has unsatisfied dependencies" do
101
+ fc = FactChecker::Base.new([:f1, :f2], {:f1 => :f2}, {:f2 => :nil?})
102
+ fc.fact_accomplished?("something", :f1).should be_false
103
+ end
104
+ it "should return false if fact has both satisfied and unsatisfied dependencies" do
105
+ fc = FactChecker::Base.new([:f1, :f2, :f3, :f4], {:f1 => [:f2, :f3], :f3 => :f4}, {:f2 => :size, :f3 => :size, :f4 => :nil?})
106
+ fc.fact_accomplished?("something", :f1).should be_false
107
+ end
108
+ it "should return true if all dependencies are satisfied and fact has no requirements" do
109
+ fc = FactChecker::Base.new([:f1, :f2, :f3, :f4], {:f1 => [:f2, :f3], :f3 => :f4}, {:f2 => :size, :f3 => :size, :f4 => :size})
110
+ fc.fact_accomplished?("something", :f1).should be_true
111
+ end
112
+ it "should return false if requirements not satisfied (all dependencies are satisfied)" do
113
+ fc = FactChecker::Base.new([:f1, :f2, :f3, :f4], {:f1 => [:f2, :f3], :f3 => :f4}, {:f1 => :nil?, :f2 => :size, :f3 => :size, :f4 => :size})
114
+ fc.fact_accomplished?("something", :f1).should be_false
115
+ end
116
+ end
117
+
118
+ describe "#fact_possible?" do
119
+ it "should return true if fact is unknown" do
120
+ fc = FactChecker::Base.new([:f2], nil, {:f1 => :nil?})
121
+ fc.fact_possible?(nil, :f1).should be_true
122
+ end
123
+ it "should return true if dependencies satisfied (even if requirement is not satisfied)" do
124
+ fc = FactChecker::Base.new([:f1], nil, {:f1 => :nil?})
125
+ fc.fact_possible?(1, :f1).should be_true
126
+ end
127
+ it "should return false if dependencies unsatisfied (even if requirement is satisfied)" do
128
+ fc = FactChecker::Base.new([:f1], {:f1 => :f2}, {:f2 => :nil?})
129
+ fc.fact_possible?(1, :f1).should be_false
130
+ end
131
+ end
132
+
133
+ describe "#def_fact" do
134
+ let(:fc) { FactChecker::Base.new }
135
+
136
+ it "should add argument to facts when called with (:fact) and return (:fact)" do
137
+ fc.def_fact(:f1).should be :f1
138
+ fc.def_fact(:f2).should be :f2
139
+ fc.facts.should == [:f1, :f2]
140
+ end
141
+
142
+ it "should define fact correctly when called with (:fact, :if => :requirement)" do
143
+ fc.def_fact(:f1)
144
+ fc.def_fact(:f2, :if => :nil?)
145
+ fc.facts.should == [:f1, :f2]
146
+ fc.requirements[:f2].should == :nil?
147
+ end
148
+
149
+ it "should define fact correctly when called with (:fact => :dependency)" do
150
+ fc.def_fact(:f1)
151
+ fc.def_fact(:f2 => :f1)
152
+ fc.facts.should == [:f1, :f2]
153
+ fc.dependencies[:f2].should == :f1
154
+ end
155
+
156
+ it "should define fact correctly when called with (:fact => :dependency, :if => :requirement)" do
157
+ fc.def_fact(:f1)
158
+ fc.def_fact(:f2 => :f1, :if => :nil?)
159
+ fc.facts.should == [:f1, :f2]
160
+ fc.dependencies[:f2].should == :f1
161
+ fc.requirements[:f2].should == :nil?
162
+ end
163
+
164
+ it "should redefine fact if a fact with a given name already exists" do
165
+ fc.def_fact(:f1 => :f2, :if => :nil?)
166
+ fc.def_fact(:f1)
167
+ fc.facts.should == [:f1]
168
+ fc.requirements[:f1].should be_nil
169
+ fc.dependencies[:f1].should be_nil
170
+ end
171
+
172
+ it "should raise ArgumentError exception when called with wrong arguments" do
173
+ expect { fc.def_fact() }.to raise_error ArgumentError
174
+ expect { fc.def_fact(:f1, {:if => :nil?}, true) }.to raise_error ArgumentError
175
+ expect { fc.def_fact(:f1, :f2) }.to raise_error ArgumentError
176
+ expect { fc.def_fact({:if => :nil?}, :f1) }.to raise_error ArgumentError
177
+ expect { fc.def_fact(:f1 => :f2, :if => :nil?, :something_else => true) }.to raise_error ArgumentError
178
+ end
179
+ end
180
+ end
@@ -0,0 +1,7 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe FactChecker::VERSION do
6
+ it { should =~ /\A\d+\.\d+\.\d+\z/ }
7
+ end
@@ -0,0 +1,63 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'FactCheckerInheritance' do
6
+ describe ChildOfClassWithFacts do
7
+ subject { ChildOfClassWithFacts }
8
+
9
+ it { should respond_to :def_fact }
10
+ its(:fact_checker) { should be_kind_of FactChecker::Base }
11
+
12
+ describe 'context for inherited facts' do
13
+ let(:target) { ChildOfClassWithFacts.new }
14
+
15
+ context 'inherited bare fact', :fact => :bare_fact do
16
+ it_behaves_like 'an accomplished fact', true
17
+ it_behaves_like 'a possible fact', true
18
+ end
19
+
20
+ context 'inherited true fact with no dependencies', :fact => :true_fact_with_no_dependencies do
21
+ it_behaves_like 'an accomplished fact', true
22
+ it_behaves_like 'a possible fact', true
23
+ end
24
+
25
+ context 'inherited true fact with true dependencies', :fact => :true_fact_with_true_dependencies do
26
+ it_behaves_like 'an accomplished fact', true
27
+ it_behaves_like 'a possible fact', true
28
+ end
29
+
30
+ context 'inherited true fact with false dependencies', :fact => :true_fact_with_false_dependencies do
31
+ it_behaves_like 'an accomplished fact', false
32
+ it_behaves_like 'a possible fact', false
33
+ end
34
+
35
+ context 'inherited false fact with no dependencies', :fact => :false_fact_with_no_dependencies do
36
+ it_behaves_like 'an accomplished fact', false
37
+ it_behaves_like 'a possible fact', true
38
+ end
39
+
40
+ context 'inherited false fact with true dependencies', :fact => :false_fact_with_true_dependencies do
41
+ it_behaves_like 'an accomplished fact', false
42
+ it_behaves_like 'a possible fact', true
43
+ end
44
+
45
+ context 'inherited false fact with false dependencies', :fact => :false_fact_with_false_dependencies do
46
+ it_behaves_like 'an accomplished fact', false
47
+ it_behaves_like 'a possible fact', false
48
+ end
49
+
50
+ specify '#facts' do
51
+ target.facts.size.should == 7
52
+ end
53
+
54
+ specify '#accomplished_facts' do
55
+ target.accomplished_facts.should == [ :bare_fact, :true_fact_with_no_dependencies, :true_fact_with_true_dependencies ]
56
+ end
57
+
58
+ specify '#possible_facts' do
59
+ target.possible_facts.should == target.facts - [ :true_fact_with_false_dependencies, :false_fact_with_false_dependencies ]
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,74 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ describe 'FactChecker' do
6
+ describe ClassWithNoFacts do
7
+ its(:facts) { should == [] }
8
+ its(:possible_facts) { should == [] }
9
+ its(:accomplished_facts) { should == [] }
10
+
11
+ specify '#fact_possible? and #fact_accomplished?' do
12
+ subject.fact_possible?(:unknown_fact).should be_true
13
+ subject.fact_accomplished?(:unknown_fact).should be_false
14
+ end
15
+ end
16
+
17
+ describe ClassWithFacts do
18
+ subject { ClassWithFacts }
19
+
20
+ it { should respond_to :def_fact }
21
+ its(:fact_checker) { should be_kind_of FactChecker::Base }
22
+
23
+ describe 'context for facts' do
24
+ let(:target) { ClassWithFacts.new }
25
+
26
+ context 'given bare fact', :fact => :bare_fact do
27
+ it_behaves_like 'an accomplished fact', true
28
+ it_behaves_like 'a possible fact', true
29
+ end
30
+
31
+ context 'given true fact with no dependencies', :fact => :true_fact_with_no_dependencies do
32
+ it_behaves_like 'an accomplished fact', true
33
+ it_behaves_like 'a possible fact', true
34
+ end
35
+
36
+ context 'given true fact with true dependencies', :fact => :true_fact_with_true_dependencies do
37
+ it_behaves_like 'an accomplished fact', true
38
+ it_behaves_like 'a possible fact', true
39
+ end
40
+
41
+ context 'given true fact with false dependencies', :fact => :true_fact_with_false_dependencies do
42
+ it_behaves_like 'an accomplished fact', false
43
+ it_behaves_like 'a possible fact', false
44
+ end
45
+
46
+ context 'given false fact with no dependencies', :fact => :false_fact_with_no_dependencies do
47
+ it_behaves_like 'an accomplished fact', false
48
+ it_behaves_like 'a possible fact', true
49
+ end
50
+
51
+ context 'given false fact with true dependencies', :fact => :false_fact_with_true_dependencies do
52
+ it_behaves_like 'an accomplished fact', false
53
+ it_behaves_like 'a possible fact', true
54
+ end
55
+
56
+ context 'given false fact with false dependencies', :fact => :false_fact_with_false_dependencies do
57
+ it_behaves_like 'an accomplished fact', false
58
+ it_behaves_like 'a possible fact', false
59
+ end
60
+
61
+ specify '#facts' do
62
+ target.facts.size.should == 7
63
+ end
64
+
65
+ specify '#accomplished_facts' do
66
+ target.accomplished_facts.should == [ :bare_fact, :true_fact_with_no_dependencies, :true_fact_with_true_dependencies ]
67
+ end
68
+
69
+ specify '#possible_facts' do
70
+ target.possible_facts.should == target.facts - [ :true_fact_with_false_dependencies, :false_fact_with_false_dependencies ]
71
+ end
72
+ end
73
+ end
74
+ end
data/spec/spec.rake ADDED
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ require 'rspec/core/rake_task'
4
+
5
+ desc 'Run complete application spec suite'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ spec_tasks = Dir['spec/*/'].map { |d| File.basename(d) }
9
+
10
+ spec_tasks.each do |folder|
11
+ RSpec::Core::RakeTask.new("spec:#{folder}") do |t|
12
+ t.pattern = "./spec/#{folder}/**/*_spec.rb"
13
+ t.rspec_opts = %w(--color)
14
+ end
15
+ end
16
+
17
+ # task 'spec' => spec_tasks.map { |f| "spec:#{f}" }
@@ -0,0 +1,18 @@
1
+ # encoding: utf-8
2
+
3
+ $:.unshift File.expand_path('../lib', __FILE__)
4
+ require 'fact_checker'
5
+ Dir['./spec/support/**/*.rb'].each { |f| require f }
6
+
7
+ RSpec.configure do |conf|
8
+ conf.color_enabled = true
9
+ conf.treat_symbols_as_metadata_keys_with_true_values = true
10
+
11
+ conf.expect_with :rspec, :stdlib
12
+ conf.mock_with :rspec
13
+
14
+ conf.fail_fast = true
15
+ conf.filter_run :focus => true
16
+ conf.filter_run_excluding :broken => true
17
+ conf.run_all_when_everything_filtered = true
18
+ end
@@ -0,0 +1,27 @@
1
+ # encoding: utf-8
2
+
3
+ require 'spec_helper'
4
+
5
+ class ClassWithNoFacts
6
+ include FactChecker
7
+ end
8
+
9
+ class ClassWithFacts
10
+ include FactChecker
11
+
12
+ def_fact :bare_fact
13
+ def_fact :true_fact_with_no_dependencies, :if => lambda { true }
14
+ def_fact :true_fact_with_true_dependencies => :bare_fact, :if => lambda { true }
15
+ def_fact :true_fact_with_false_dependencies => :false_fact_with_no_dependencies, :if => lambda { true }
16
+ def_fact :false_fact_with_no_dependencies, :if => lambda { false }
17
+ def_fact :false_fact_with_true_dependencies => :bare_fact , :if => lambda { false }
18
+ def_fact :false_fact_with_false_dependencies => :false_fact_with_no_dependencies , :if => lambda { false }
19
+ end
20
+
21
+ class ChildOfClassWithFacts < ClassWithFacts
22
+ end
23
+
24
+ # :another_fact should not creep back to parent classes
25
+ class GrandChildOfClassWithFacts < ChildOfClassWithFacts
26
+ def_fact :another_fact
27
+ end
@@ -0,0 +1,17 @@
1
+ # encoding: utf-8
2
+
3
+ shared_examples 'an accomplished fact' do |true_or_false|
4
+ specify '#fact_accomplished?' do
5
+ target.fact_accomplished?(example.metadata[:fact]).should be true_or_false
6
+ end
7
+
8
+ specify '#(:fact)? predicate' do
9
+ target.send("#{example.metadata[:fact]}?").should be true_or_false
10
+ end
11
+ end
12
+
13
+ shared_examples 'a possible fact' do |true_or_false|
14
+ specify '#fact_possible?' do
15
+ target.fact_possible?(example.metadata[:fact]).should be true_or_false
16
+ end
17
+ end
metadata ADDED
@@ -0,0 +1,100 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fact_checker
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Alexey Smolianinov
9
+ - Ivan Povalyukhin
10
+ autorequire:
11
+ bindir: bin
12
+ cert_chain: []
13
+ date: 2011-10-31 00:00:00.000000000 +04:00
14
+ default_executable:
15
+ dependencies:
16
+ - !ruby/object:Gem::Dependency
17
+ name: rspec
18
+ requirement: &84896850 !ruby/object:Gem::Requirement
19
+ none: false
20
+ requirements:
21
+ - - ~>
22
+ - !ruby/object:Gem::Version
23
+ version: '2.6'
24
+ type: :development
25
+ prerelease: false
26
+ version_requirements: *84896850
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: &84896660 !ruby/object:Gem::Requirement
30
+ none: false
31
+ requirements:
32
+ - - ! '>='
33
+ - !ruby/object:Gem::Version
34
+ version: '0'
35
+ type: :development
36
+ prerelease: false
37
+ version_requirements: *84896660
38
+ - !ruby/object:Gem::Dependency
39
+ name: bundler
40
+ requirement: &84896430 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ type: :development
47
+ prerelease: false
48
+ version_requirements: *84896430
49
+ description: Simple gem to check hierarchically dependent "facts" about objects
50
+ email:
51
+ - alexisowl+fact_checker@gmail.com
52
+ executables: []
53
+ extensions: []
54
+ extra_rdoc_files: []
55
+ files:
56
+ - .gitignore
57
+ - .rvmrc
58
+ - Gemfile
59
+ - README
60
+ - Rakefile
61
+ - examples/README.md
62
+ - examples/basic.rb
63
+ - fact_checker.gemspec
64
+ - lib/fact_checker.rb
65
+ - lib/fact_checker/base.rb
66
+ - lib/fact_checker/version.rb
67
+ - spec/fact_checker/base_spec.rb
68
+ - spec/fact_checker/version_spec.rb
69
+ - spec/fact_checker_inheritance_spec.rb
70
+ - spec/fact_checker_spec.rb
71
+ - spec/spec.rake
72
+ - spec/spec_helper.rb
73
+ - spec/support/classes_with_facts.rb
74
+ - spec/support/shared_facts_behaviour.rb
75
+ has_rdoc: true
76
+ homepage: https://github.com/alexis/fact_checker
77
+ licenses: []
78
+ post_install_message:
79
+ rdoc_options: []
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ! '>='
86
+ - !ruby/object:Gem::Version
87
+ version: 1.8.7
88
+ required_rubygems_version: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: 1.3.5
94
+ requirements: []
95
+ rubyforge_project: fact_checker
96
+ rubygems_version: 1.6.2
97
+ signing_key:
98
+ specification_version: 3
99
+ summary: Checks facts which may depend on other facts
100
+ test_files: []