so_far_so_good 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -0
- data/README.md +82 -7
- data/lib/so_far_so_good.rb +4 -4
- data/lib/so_far_so_good/clause.rb +8 -0
- data/lib/so_far_so_good/clauses.rb +18 -8
- data/lib/so_far_so_good/version.rb +1 -1
- data/test/so_far_so_good_clause_test.rb +27 -0
- data/test/so_far_so_good_clauses_test.rb +13 -1
- data/test/so_far_so_good_test.rb +4 -0
- metadata +4 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c0ca888a79d1abea3f16bac6d5fa7706cc1b2c10
|
4
|
+
data.tar.gz: fa8aa37486a39179474fdbef201352217ae3f596
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f54bb0f2a247aaeb8a2b4199f5c98d573e815494634821f1f6c7c8a9c2c4d33b40519723b8bc1a56767d8d4d0a31bfff7c9ef1388d7da2053596dfadeadd545
|
7
|
+
data.tar.gz: 42aa3e271d119b52e5ed3a646838e82f5a8c5a830a246ff1f5bab5dfbde384c03d61a11d0ccf7b3b35d8e8ffa396b3fb9f2f17d79d698d06937a5b11342945d0
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -2,21 +2,96 @@
|
|
2
2
|
|
3
3
|
A Ruby Gem to parse and manipulate the Federal Acquisition Regulation
|
4
4
|
|
5
|
+
[![Gem Version](https://badge.fury.io/rb/so_far_so_good.svg)](http://badge.fury.io/rb/so_far_so_good) [![Build Status](https://travis-ci.org/benbalter/so_far_so_good.svg)](https://travis-ci.org/benbalter/so_far_so_good)
|
6
|
+
|
5
7
|
## What it does
|
6
8
|
|
7
|
-
|
9
|
+
So FAR so Good is a Ruby Gem to interact with the Federal Acquisition Regulation. Right now, it only supports section 52.20x, the FAR standard contracting clause templates.
|
10
|
+
|
11
|
+
For any contract clause, it will provide:
|
12
|
+
|
13
|
+
* The section number
|
14
|
+
* The subject
|
15
|
+
* Whether it's a reserved section
|
16
|
+
* The formal citation
|
17
|
+
* The body (full clause text)
|
18
|
+
* The extract (what's inserted into the contract)
|
19
|
+
|
20
|
+
It will give you access to this information in object-oriented Ruby, as JSON, or as a markdown table for use elsewhere.
|
8
21
|
|
9
22
|
## Usage
|
10
23
|
|
24
|
+
### Basic usage
|
25
|
+
|
11
26
|
```ruby
|
12
|
-
|
13
|
-
|
14
|
-
"52.
|
15
|
-
"52.202-1"
|
16
|
-
"52.203-1"
|
17
|
-
|
27
|
+
# Get all clauses
|
28
|
+
clauses = SoFarSoGood.clauses
|
29
|
+
=> [#<SoFarSoGood::Clause @number="52.200" @subject="Scope of subpart." @reserved="false",
|
30
|
+
#<SoFarSoGood::Clause @number="52.202-1" @subject="Definitions." @reserved="false",
|
31
|
+
#<SoFarSoGood::Clause @number="52.203-1" @subject="[Reserved]" @reserved="true",
|
32
|
+
#<SoFarSoGood::Clause @number="52.203-2" @subject="Certificate of Independent Price Determination." @reserved="false",
|
33
|
+
#<SoFarSoGood::Clause @number="52.203-3" @subject="Gratuities." @reserved="false", ... ]
|
34
|
+
|
35
|
+
# Get a list of clause numbers
|
36
|
+
SoFarSoGood::Clauses.numbers
|
37
|
+
=> ["52.200", "52.202-1", "52.203-1", "52.203-2", "52.203-3", "52.203-4", "52.203-5", ... ]
|
38
|
+
|
39
|
+
# Get a list of clause numbers, excluding reserved clauses
|
40
|
+
SoFarSoGood::Clauses.numbers(:exclude_reserved => true)
|
41
|
+
=> ["52.200", "52.202-1", "52.203-1", "52.203-2", "52.203-3", "52.203-4", "52.203-5", ... ]
|
42
|
+
|
43
|
+
# Get a list of clause subjects
|
44
|
+
SoFarSoGood::Clauses.subjects
|
45
|
+
=> ["Scope of subpart.", "Definitions.", "[Reserved]", "Certificate of Independent Price Determination.", ... ]
|
18
46
|
```
|
19
47
|
|
48
|
+
### Working with individual clauses
|
49
|
+
|
50
|
+
```ruby
|
51
|
+
# Get a specific clause
|
52
|
+
clause = SoFarSoGood::Clauses["52.202-1"]
|
53
|
+
=> #<SoFarSoGood::Clause @number="52.202-1" @subject="Definitions." @reserved="false"
|
54
|
+
|
55
|
+
clause.number
|
56
|
+
=> "52.202-1"
|
57
|
+
|
58
|
+
clause.subject
|
59
|
+
=> "Definitions"
|
60
|
+
|
61
|
+
clause.reserved?
|
62
|
+
=> false
|
63
|
+
|
64
|
+
clause.citation
|
65
|
+
=> "[69 FR 34228, June 18, 2004]"
|
66
|
+
|
67
|
+
# The full clause body
|
68
|
+
clause.body
|
69
|
+
=> "As prescribed in 2.201, insert the following clause:..."
|
70
|
+
|
71
|
+
# The actual clause text to be inserted in the contract
|
72
|
+
clause.extract
|
73
|
+
=> "Definitions (JUL 2004)(a) When a solicitation provision or contract clause uses a word..."
|
74
|
+
```
|
75
|
+
|
76
|
+
### Using clause data elsewhere
|
77
|
+
|
78
|
+
```ruby
|
79
|
+
|
80
|
+
SoFarSoGood::Clauses.list.to_json
|
81
|
+
=> "[{\"number\":\"52.200\",\"subject\":\"Scope of subpart.\",\"reserverd\":false,\"citation\":..."
|
82
|
+
|
83
|
+
puts SoFarSoGood::Clauses.to_md
|
84
|
+
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
85
|
+
| Clause | Description |
|
86
|
+
|-----------|---------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
87
|
+
| 52.200 | Scope of subpart. |
|
88
|
+
| 52.202-1 | Definitions. |
|
89
|
+
| 52.203-2 | Certificate of Independent Price Determination. |
|
90
|
+
| 52.203-3 | Gratuities. |
|
91
|
+
| 52.203-5 | Covenant Against Contingent Fees. |
|
92
|
+
```
|
93
|
+
|
94
|
+
|
20
95
|
## Installation
|
21
96
|
|
22
97
|
Add this line to your application's Gemfile:
|
data/lib/so_far_so_good.rb
CHANGED
@@ -7,12 +7,12 @@ require_relative "so_far_so_good/clause"
|
|
7
7
|
|
8
8
|
module SoFarSoGood
|
9
9
|
class << self
|
10
|
-
def
|
11
|
-
|
10
|
+
def clauses(options = {})
|
11
|
+
SoFarSoGood::Clauses.clauses(options)
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
15
|
-
|
14
|
+
def vendor_directory
|
15
|
+
File.expand_path "../vendor", File.dirname(__FILE__)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
end
|
@@ -17,6 +17,10 @@ module SoFarSoGood
|
|
17
17
|
@body = node.children.css("P").text.strip
|
18
18
|
end
|
19
19
|
|
20
|
+
def reserved?
|
21
|
+
!!@reserved
|
22
|
+
end
|
23
|
+
|
20
24
|
def to_hash
|
21
25
|
{
|
22
26
|
:number => @number,
|
@@ -31,5 +35,9 @@ module SoFarSoGood
|
|
31
35
|
def to_json(options = {})
|
32
36
|
to_hash.to_json(options)
|
33
37
|
end
|
38
|
+
|
39
|
+
def inspect
|
40
|
+
"#<SoFarSoGood::Clause @number=\"#{@number}\" @subject=\"#{@subject}\" @reserved=\"#{@reserved}\""
|
41
|
+
end
|
34
42
|
end
|
35
43
|
end
|
@@ -4,17 +4,23 @@ module SoFarSoGood
|
|
4
4
|
|
5
5
|
HEADINGS = ["Clause", "Description"]
|
6
6
|
|
7
|
-
def numbers
|
8
|
-
@numbers ||= clauses.map { |c| c.number }
|
7
|
+
def numbers(options = {})
|
8
|
+
@numbers ||= clauses(options).map { |c| c.number }
|
9
9
|
end
|
10
10
|
|
11
|
-
def subjects
|
12
|
-
@subjects ||= clauses.map { |c| c.subject }
|
11
|
+
def subjects(options = {})
|
12
|
+
@subjects ||= clauses(options).map { |c| c.subject }
|
13
13
|
end
|
14
14
|
alias_method :descriptions, :subjects
|
15
15
|
|
16
|
-
def clauses
|
16
|
+
def clauses(options = {})
|
17
|
+
options = {:exclude_reserved => false}.merge(options)
|
17
18
|
@clauses ||= sections.map { |node| SoFarSoGood::Clause.new(node) }
|
19
|
+
if options[:exclude_reserved]
|
20
|
+
@clauses.reject { |c| c.reserved }
|
21
|
+
else
|
22
|
+
@clauses
|
23
|
+
end
|
18
24
|
end
|
19
25
|
alias_method :list, :clauses
|
20
26
|
|
@@ -23,7 +29,11 @@ module SoFarSoGood
|
|
23
29
|
end
|
24
30
|
|
25
31
|
def to_json
|
26
|
-
@json ||=
|
32
|
+
@json ||= clauses.to_json
|
33
|
+
end
|
34
|
+
|
35
|
+
def [](number)
|
36
|
+
clauses.find { |c| c.number == number }
|
27
37
|
end
|
28
38
|
|
29
39
|
private
|
@@ -42,8 +52,8 @@ module SoFarSoGood
|
|
42
52
|
@subpart ||= doc.css("PART SUBPART")[4].children.css("SECTION")
|
43
53
|
end
|
44
54
|
|
45
|
-
def rows
|
46
|
-
@rows ||= clauses.
|
55
|
+
def rows(options={})
|
56
|
+
@rows ||= clauses(options).map { |c| [c.number, c.subject]}
|
47
57
|
end
|
48
58
|
end
|
49
59
|
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestSoFarSoGoodClause < Minitest::Test
|
4
|
+
|
5
|
+
def setup
|
6
|
+
@nodes = SoFarSoGood::Clauses.send(:sections)
|
7
|
+
end
|
8
|
+
|
9
|
+
should "parse a section node" do
|
10
|
+
clause = SoFarSoGood::Clause.new(@nodes[6])
|
11
|
+
assert_equal "52.203-5", clause.number
|
12
|
+
assert_equal "Covenant Against Contingent Fees.", clause.subject
|
13
|
+
refute clause.reserved
|
14
|
+
assert_includes clause.citation, "48 FR 42478"
|
15
|
+
assert_includes clause.body, "As prescribed in 3.404,"
|
16
|
+
assert_includes clause.extract, "The Contractor warrants that no person or agency"
|
17
|
+
end
|
18
|
+
|
19
|
+
should "know if its reserved" do
|
20
|
+
refute SoFarSoGood::Clauses["52.203-5"].reserved?
|
21
|
+
assert SoFarSoGood::Clauses["52.203-1"].reserved?
|
22
|
+
end
|
23
|
+
|
24
|
+
should "put out valid json" do
|
25
|
+
assert JSON.parse SoFarSoGood::Clauses["52.203-5"].to_json
|
26
|
+
end
|
27
|
+
end
|
@@ -10,7 +10,7 @@ class TestSoFarSoGoodClauses < Minitest::Test
|
|
10
10
|
end
|
11
11
|
|
12
12
|
should "parse the rows" do
|
13
|
-
assert_equal
|
13
|
+
assert_equal 616, SoFarSoGood::Clauses.send(:rows).count
|
14
14
|
assert_equal ["52.200", "Scope of subpart."], SoFarSoGood::Clauses.send(:rows).first
|
15
15
|
end
|
16
16
|
|
@@ -27,4 +27,16 @@ class TestSoFarSoGoodClauses < Minitest::Test
|
|
27
27
|
should "put out valid JSON" do
|
28
28
|
assert !!JSON.parse(SoFarSoGood::Clauses.list.to_json)
|
29
29
|
end
|
30
|
+
|
31
|
+
should "return a particular clause" do
|
32
|
+
assert_equal "52.202-1", SoFarSoGood::Clauses["52.202-1"].number
|
33
|
+
end
|
34
|
+
|
35
|
+
should "return all clauses" do
|
36
|
+
assert_equal 616, SoFarSoGood::Clauses.list.count
|
37
|
+
end
|
38
|
+
|
39
|
+
should "filter reserved clauses" do
|
40
|
+
assert_equal 567, SoFarSoGood::Clauses.list(:exclude_reserved => true).count
|
41
|
+
end
|
30
42
|
end
|
data/test/so_far_so_good_test.rb
CHANGED
@@ -9,4 +9,8 @@ class TestSoFarSoGood < Minitest::Test
|
|
9
9
|
assert_equal Array, SoFarSoGood.clauses.class
|
10
10
|
assert_equal 616, SoFarSoGood.clauses.count
|
11
11
|
end
|
12
|
+
|
13
|
+
should "accept clause options" do
|
14
|
+
assert_equal 567, SoFarSoGood.clauses(:exclude_reserved => true).count
|
15
|
+
end
|
12
16
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: so_far_so_good
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ben Balter
|
@@ -102,6 +102,7 @@ extensions: []
|
|
102
102
|
extra_rdoc_files: []
|
103
103
|
files:
|
104
104
|
- ".gitignore"
|
105
|
+
- ".travis.yml"
|
105
106
|
- Gemfile
|
106
107
|
- LICENSE.md
|
107
108
|
- README.md
|
@@ -118,6 +119,7 @@ files:
|
|
118
119
|
- script/vendor
|
119
120
|
- so_far_so_good.gemspec
|
120
121
|
- test/helper.rb
|
122
|
+
- test/so_far_so_good_clause_test.rb
|
121
123
|
- test/so_far_so_good_clauses_test.rb
|
122
124
|
- test/so_far_so_good_test.rb
|
123
125
|
- vendor/CFR-2010-title48-vol2-chap1-subchapH.xml
|
@@ -147,5 +149,6 @@ specification_version: 4
|
|
147
149
|
summary: ''
|
148
150
|
test_files:
|
149
151
|
- test/helper.rb
|
152
|
+
- test/so_far_so_good_clause_test.rb
|
150
153
|
- test/so_far_so_good_clauses_test.rb
|
151
154
|
- test/so_far_so_good_test.rb
|