so_far_so_good 0.0.1 → 0.0.2

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 9521b2d0cb4777d080a409ff1631f60c70bff35e
4
- data.tar.gz: 248816b662685c753f72d37e0ee42be875f7af8b
3
+ metadata.gz: c0ca888a79d1abea3f16bac6d5fa7706cc1b2c10
4
+ data.tar.gz: fa8aa37486a39179474fdbef201352217ae3f596
5
5
  SHA512:
6
- metadata.gz: ef818c8d2c48bad1bd567654aa5f0e16b91063575d414afd63153d019239801ef160181b890072c84c5eeed87a89ef1fa26adf849fd72e054d266052a2f35f41
7
- data.tar.gz: 1cdf454823ef2468c531c86d06e9e3a7a4e2e5e6b58e5bafb81a828f0aa9309b6c2ec38271e9b0da355aa3cea0308f5e16ad54606c11349aa96e39ba54a530e2
6
+ metadata.gz: 2f54bb0f2a247aaeb8a2b4199f5c98d573e815494634821f1f6c7c8a9c2c4d33b40519723b8bc1a56767d8d4d0a31bfff7c9ef1388d7da2053596dfadeadd545
7
+ data.tar.gz: 42aa3e271d119b52e5ed3a646838e82f5a8c5a830a246ff1f5bab5dfbde384c03d61a11d0ccf7b3b35d8e8ffa396b3fb9f2f17d79d698d06937a5b11342945d0
data/.travis.yml ADDED
@@ -0,0 +1,2 @@
1
+ langauage: ruby
2
+ script: "script/cibuild"
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
- Right now, it simply gives you a hash of FAR 52.2x clauses and their description, but soon, much, much more!
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
- SoFarSoGood.clauses
13
- > {"52.200"=>"Scope of subpart.",
14
- "52.201"=>"[Reserved]",
15
- "52.202-1"=>"Definitions.",
16
- "52.203-1"=>"[Reserved]",...
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:
@@ -7,12 +7,12 @@ require_relative "so_far_so_good/clause"
7
7
 
8
8
  module SoFarSoGood
9
9
  class << self
10
- def vendor_directory
11
- File.expand_path "../vendor", File.dirname(__FILE__)
10
+ def clauses(options = {})
11
+ SoFarSoGood::Clauses.clauses(options)
12
12
  end
13
13
 
14
- def clauses
15
- SoFarSoGood::Clauses.clauses
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 ||= sections.to_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.reject { |c| c.reserved }.map { |c| [c.number, c.subject]}
55
+ def rows(options={})
56
+ @rows ||= clauses(options).map { |c| [c.number, c.subject]}
47
57
  end
48
58
  end
49
59
  end
@@ -1,3 +1,3 @@
1
1
  module SoFarSoGood
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  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 567, SoFarSoGood::Clauses.send(:rows).count
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
@@ -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.1
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