schedule-dsl 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 7b47e80c9c20de3922c89fec31755c1306f5d5b008f760eea5b67e3637d7e978
4
+ data.tar.gz: 802e2a55333f9a058951d6e15e679eeeb7092286525698a2fcff66efebf52780
5
+ SHA512:
6
+ metadata.gz: adbc130c9ec66a7f5aa213a9f36e70f23a74f1e21681b3b91066fb9ae0e33fb6d48e7ee0582606c64886ce8d9ff0d6de3852f3ea5372a6538424b62f7d191163
7
+ data.tar.gz: 8f6b8a1f188bce244fb536aae111163614d02ebe3d277b814eb5af6fe9adb5b9882e38ebcb3b9087db9a18eb78ff639de1f6fd751456f53a9b32fd3694f47ebc
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source 'https://rubygems.org'
2
+
3
+ group(:spec) do
4
+ gem 'rspec'
5
+ end
@@ -0,0 +1,26 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ diff-lcs (1.4.4)
5
+ rspec (3.10.0)
6
+ rspec-core (~> 3.10.0)
7
+ rspec-expectations (~> 3.10.0)
8
+ rspec-mocks (~> 3.10.0)
9
+ rspec-core (3.10.0)
10
+ rspec-support (~> 3.10.0)
11
+ rspec-expectations (3.10.0)
12
+ diff-lcs (>= 1.2.0, < 2.0)
13
+ rspec-support (~> 3.10.0)
14
+ rspec-mocks (3.10.0)
15
+ diff-lcs (>= 1.2.0, < 2.0)
16
+ rspec-support (~> 3.10.0)
17
+ rspec-support (3.10.0)
18
+
19
+ PLATFORMS
20
+ ruby
21
+
22
+ DEPENDENCIES
23
+ rspec
24
+
25
+ BUNDLED WITH
26
+ 2.1.4
@@ -0,0 +1,68 @@
1
+ # About
2
+
3
+ _Provides a DSL for defining your schedule rules and getting results for given date._
4
+
5
+ # Examples
6
+
7
+ ## Collect returned values
8
+
9
+ ```ruby
10
+ # Your definition file.
11
+
12
+ rule Proc.new { true } do
13
+ "Go swimming"
14
+ end
15
+
16
+ rule Proc.new { false } do
17
+ "Steal things from little kids"
18
+ end
19
+
20
+ rule -> (date) { date.tuesday? } do
21
+ "Read a book"
22
+ end
23
+ ```
24
+
25
+ ```ruby
26
+ # Your script.
27
+
28
+ require 'schedule'
29
+
30
+ table = Schedule.load(definition_file_path)
31
+ table.filter(Date.today).evaluate
32
+ # => ["Go swimming", "Read a book"]
33
+ ```
34
+
35
+ ## Use a collector object
36
+
37
+ ```ruby
38
+ # Your definition file.
39
+
40
+ rule -> (date) { date.tuesday? } do |time_frames|
41
+ time_frames[:morning] << "Go swimming"
42
+ end
43
+
44
+ rule -> (date) { date.weekday? } do |time_frames|
45
+ time_frames[:evening] << "Read a book"
46
+ end
47
+ ```
48
+
49
+ ```ruby
50
+ # Your script.
51
+
52
+ require 'schedule'
53
+
54
+ table = Schedule.load(definition_file_path)
55
+ time_frames = {morning: Array.new}
56
+ table.filter(Date.today).evaluate(time_frames) # Ignore the result.
57
+ time_frames # => {morning: "Go swimming"}
58
+ ```
59
+
60
+ # API
61
+
62
+ ## Custom `Date` extensions
63
+
64
+ Date passed as an argument to the condition is extended with `Schedule::DateExts`.
65
+
66
+ - `Date#weekend?`
67
+ - `Date#weekday?`
68
+ - `Date#last_day_of_a_month?`
@@ -0,0 +1,98 @@
1
+ require 'date'
2
+ require 'forwardable'
3
+
4
+ module Schedule
5
+ # Load schedule from definition file.
6
+ def self.load(path)
7
+ context = DSL.new
8
+ context.instance_eval(File.read(path), path)
9
+ context.rules
10
+ end
11
+
12
+ class RuleList
13
+ extend Forwardable
14
+
15
+ attr_reader :rules
16
+ def initialize
17
+ @rules = Array.new
18
+ end
19
+
20
+ def_delegators :rules, :length, :first, :empty?, :<<
21
+
22
+ def filter(date)
23
+ FilteredRuleList.new(
24
+ date.extend(DateExts),
25
+ self.rules.select { |rule| rule.condition.call(date) })
26
+ end
27
+ end
28
+
29
+ class FilteredRuleList
30
+ extend Forwardable
31
+
32
+ attr_reader :date, :rules
33
+ def initialize(date, rules)
34
+ @date, @rules = date, rules
35
+ end
36
+
37
+ def_delegators :rules, :length, :first, :empty?, :<<
38
+
39
+ # This method can be used in one of two ways:
40
+ #
41
+ # Either directly collect the results or pass a collection object,
42
+ # fill it in and then use that object directly rather than using
43
+ # the output of this method.
44
+ #
45
+ # # Collecting the results directly
46
+ #
47
+ # rule -> (date) { date.tuesday? } do
48
+ # "Go swimming"
49
+ # end
50
+ #
51
+ # list.evaluate # => ["Go swimming"]
52
+ #
53
+ # # Using a collection object
54
+ #
55
+ # rule -> (date) { date.tuesday? } do |time_frames|
56
+ # time_frames[:morning] << "Go swimming"
57
+ # end
58
+ #
59
+ # time_frames = {morning: Array.new}
60
+ # list.evaluate(time_frames) # Ignore the result.
61
+ # time_frames # => {morning: "Go swimming"}
62
+ def evaluate(*args)
63
+ self.rules.map { |rule| rule.block.call(*args) }
64
+ end
65
+ end
66
+
67
+ class Rule
68
+ attr_reader :condition, :block
69
+ def initialize(condition, &block)
70
+ @condition, @block = condition, block
71
+ end
72
+ end
73
+
74
+ class DSL
75
+ attr_reader :rules
76
+ def initialize
77
+ @rules = RuleList.new
78
+ end
79
+
80
+ def rule(condition, &block)
81
+ self.rules << Rule.new(condition, &block)
82
+ end
83
+ end
84
+
85
+ module DateExts
86
+ def weekend?
87
+ self.saturday? || self.sunday?
88
+ end
89
+
90
+ def weekday?
91
+ !self.weekend?
92
+ end
93
+
94
+ def last_day_of_a_month?
95
+ self == Date.new(self.year, self.month, -1)
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,11 @@
1
+ Gem::Specification.new do |spec|
2
+ spec.name = 'schedule-dsl'
3
+ spec.version = '0.0.1'
4
+ spec.license = 'MIT' # Just so gem build would shut up. Use it however you like.
5
+
6
+ spec.summary = "Provides a DSL for defining your schedule rules and getting results for given date."
7
+ spec.author = "Jakub Šťastný"
8
+ spec.homepage = 'https://github.com/jakub-stastny/schedule-dsl'
9
+
10
+ spec.files = Dir["{lib,spec}/**/*.rb"] + ['Gemfile', 'Gemfile.lock', 'README.md', 'schedule-dsl.gemspec']
11
+ end
@@ -0,0 +1,11 @@
1
+ rule Proc.new { true } do
2
+ "Go swimming"
3
+ end
4
+
5
+ rule Proc.new { false } do
6
+ "Steal things from little kids"
7
+ end
8
+
9
+ rule -> (date) { date.tuesday? } do
10
+ "Read a book"
11
+ end
File without changes
@@ -0,0 +1,9 @@
1
+ rule -> (date) { date.tuesday? } do |time_frames|
2
+ time_frames[:morning] << "Go swimming"
3
+ end
4
+
5
+ # Date#weekday? is one of the custom date extensions
6
+ # defined in Schedule::DateExts.
7
+ rule -> (date) { date.weekday? } do |time_frames|
8
+ time_frames[:evening] << "Read a book"
9
+ end
@@ -0,0 +1,63 @@
1
+ require 'schedule'
2
+
3
+ describe Schedule do
4
+ describe '.load(path)' do
5
+ it "loads an empty file and returns an empty definition table" do
6
+ expect(described_class.load('spec/data/empty.rb')).to be_empty
7
+ end
8
+
9
+ it "loads definitions from a file and returns the definition table" do
10
+ expect(described_class.load('spec/data/basic.rb')).not_to be_empty
11
+ end
12
+ end
13
+
14
+ let(:date) do
15
+ Date.new(2020, 12, 1)
16
+ end
17
+
18
+ context "basic rule list" do
19
+ let(:table) do
20
+ described_class.load('spec/data/basic.rb')
21
+ end
22
+
23
+ describe '#filter' do
24
+ it "returns a filtered list of rules which evaluated true for given date" do
25
+ expect(table.filter(date).length).to eql(2)
26
+ end
27
+ end
28
+
29
+ describe '#evaluate' do
30
+ subject { table.filter(date) }
31
+
32
+ it "returns a list of outputs that were evaluated from each rule's block" do
33
+ expect(subject.evaluate).to eql(["Go swimming", "Read a book"])
34
+ end
35
+ end
36
+ end
37
+
38
+ context "standard rule list" do
39
+ let(:time_frames) {{
40
+ morning: Array.new,
41
+ evening: Array.new
42
+ }}
43
+
44
+ let(:table) do
45
+ described_class.load('spec/data/standard.rb')
46
+ end
47
+
48
+ describe '#filter' do
49
+ it "returns a filtered list of rules which evaluated true for given date" do
50
+ expect(table.filter(date).length).to eql(2)
51
+ end
52
+ end
53
+
54
+ describe '#evaluate' do
55
+ subject { table.filter(date) }
56
+
57
+ it "returns a list of outputs that were evaluated from each rule's block" do
58
+ subject.evaluate(time_frames)
59
+ expect(time_frames).to eql(morning: ["Go swimming"], evening: ["Read a book"])
60
+ end
61
+ end
62
+ end
63
+ end
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: schedule-dsl
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Jakub Šťastný
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-03 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description:
14
+ email:
15
+ executables: []
16
+ extensions: []
17
+ extra_rdoc_files: []
18
+ files:
19
+ - Gemfile
20
+ - Gemfile.lock
21
+ - README.md
22
+ - lib/schedule.rb
23
+ - schedule-dsl.gemspec
24
+ - spec/data/basic.rb
25
+ - spec/data/empty.rb
26
+ - spec/data/standard.rb
27
+ - spec/schedule_spec.rb
28
+ homepage: https://github.com/jakub-stastny/schedule-dsl
29
+ licenses:
30
+ - MIT
31
+ metadata: {}
32
+ post_install_message:
33
+ rdoc_options: []
34
+ require_paths:
35
+ - lib
36
+ required_ruby_version: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ required_rubygems_version: !ruby/object:Gem::Requirement
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubygems_version: 3.1.4
48
+ signing_key:
49
+ specification_version: 4
50
+ summary: Provides a DSL for defining your schedule rules and getting results for given
51
+ date.
52
+ test_files: []