prontoforms 0.1.0 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 1aa48580fd863fe9681a3ba6f901415e0775c082929532bd63e8c93de86bf121
4
- data.tar.gz: 5a21dd84aef6f4da5d285fa1587aebf79fec6d279aa10048efa0f1c6a29a1f48
3
+ metadata.gz: cf9bb12142b5957e341f48804ce06b73f8842cdcbe8e2831e34823299ca73017
4
+ data.tar.gz: c3760f082616943fa75dd0fad8f4bf0554390d75bea741f448baead8ce97bdfc
5
5
  SHA512:
6
- metadata.gz: 80299aa7c0a311c26467325e425b6f9ec39c5eda4692a9d613b40a07fe267b7751a88ecdca714071292a6f827520c35781bba0202023e9fd877dd3d6e851e0d4
7
- data.tar.gz: '08f2da72649027dee6103e24b7d932047069d9e9ebabd36b1688928ec6f2359100d4d2d6a2e22eeef4e17e1b5941752b306b9351c37a86f65dc980adf1c0c15a'
6
+ metadata.gz: 4a5da5f5afda87fd00f326deba55c97169aad8918347f308df002c2525420e92d8a22983199a2bf498afa0b8a55ea32be25549a5b20ce86fb0578123100733c8
7
+ data.tar.gz: 8f0312762f55f92b0a3d5383fef1cc1558b9e65a7ba8d7c2f770c63a97d0ef695976e542459b839bf76966f05daf776c4b8aff9dad5ca4dad690448ed64c31da
@@ -0,0 +1,66 @@
1
+ name: Checks
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+
7
+ jobs:
8
+ test:
9
+ name: Run automated tests
10
+ runs-on: ubuntu-latest
11
+ steps:
12
+ - name: Checkout repository
13
+ uses: actions/checkout@v2
14
+
15
+ - name: Set up ruby
16
+ uses: actions/setup-ruby@v1
17
+ with:
18
+ ruby-version: 2.6
19
+
20
+ - name: Install dependencies
21
+ run: |
22
+ gem install bundler -v 2.1.4
23
+ bundle install
24
+
25
+ - name: Test
26
+ run: bundle exec rake
27
+
28
+ - name: Report test coverage
29
+ uses: paambaati/codeclimate-action@v2.7.4
30
+ env:
31
+ CC_TEST_REPORTER_ID: ${{ secrets.CC_TEST_REPORTER_ID }}
32
+
33
+ rubocop:
34
+ name: Rubocop
35
+ runs-on: ubuntu-latest
36
+ strategy:
37
+ fail-fast: false
38
+
39
+ steps:
40
+ - name: Checkout repository
41
+ uses: actions/checkout@v2
42
+
43
+ - name: Set up Ruby
44
+ uses: ruby/setup-ruby@v1
45
+ with:
46
+ ruby-version: 2.6
47
+
48
+ - name: Install Code Scanning integration
49
+ run: bundle add code-scanning-rubocop --version 0.3.0 --skip-install
50
+
51
+ - name: Install dependencies
52
+ run: |
53
+ gem install bundler -v 2.1.4
54
+ bundle install
55
+
56
+ - name: Rubocop run
57
+ run: |
58
+ bash -c "
59
+ bundle exec rubocop --require code_scanning --format CodeScanning::SarifFormatter -o rubocop.sarif
60
+ [[ $? -ne 2 ]]
61
+ "
62
+
63
+ - name: Upload Sarif output
64
+ uses: github/codeql-action/upload-sarif@v1
65
+ with:
66
+ sarif_file: rubocop.sarif
data/.gitignore CHANGED
@@ -7,5 +7,9 @@
7
7
  /spec/reports/
8
8
  /tmp/
9
9
 
10
+ Gemfile.lock
11
+
10
12
  # rspec failure tracking
11
13
  .rspec_status
14
+
15
+ **/.DS_Store
@@ -0,0 +1,12 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.6
3
+ NewCops: enable
4
+
5
+ Style/ClassAndModuleChildren:
6
+ Enabled: false
7
+
8
+ Style/StringLiterals:
9
+ EnforcedStyle: single_quotes
10
+
11
+ Layout/FirstHashElementIndentation:
12
+ Enabled: false
@@ -1,6 +1,16 @@
1
1
  ---
2
+ os: linux
3
+ dist: xenial
2
4
  language: ruby
3
5
  cache: bundler
4
6
  rvm:
5
7
  - 2.6.0
6
8
  before_install: gem install bundler -v 2.1.4
9
+ before_script:
10
+ - curl -L https://codeclimate.com/downloads/test-reporter/test-reporter-latest-linux-amd64 > ./cc-test-reporter
11
+ - chmod +x ./cc-test-reporter
12
+ - ./cc-test-reporter before-build
13
+ script:
14
+ - bundle exec rspec
15
+ after_script:
16
+ - ./cc-test-reporter after-build --exit-code $TRAVIS_TEST_RESULT
@@ -0,0 +1,31 @@
1
+ # prontoforms changelog
2
+
3
+ ## [Unreleased]
4
+ ### Added
5
+ * Added Form resource
6
+ * Can retrieve forms by form space
7
+
8
+ ## [v0.3.1] - 15 Sep 2020
9
+ ### Removed
10
+ * Unused `InvalidHttpVerb` error class
11
+
12
+ ## [v0.3.0] - 15 Sep 2020
13
+ ### Added
14
+ * Autogenerated documentation via YARD.
15
+
16
+ ### Changed
17
+ * Errors now provide a message describing the issue
18
+ * `ProntoForms::Client` now raises error on invalid resource definition.
19
+
20
+ ## [v0.2.0] - 26 Aug 2020
21
+ ### Bugfixes
22
+ * Corrected pagination of resource lists
23
+
24
+ ## [v0.1.0] - 25 Aug 2020
25
+ * Initial release
26
+
27
+ [Unreleased]: https://github.com/paulholden2/prontoforms/compare/v0.3.1...HEAD
28
+ [v0.1.0]: https://github.com/paulholden2/prontoforms/releases/tag/v0.1.0
29
+ [v0.2.0]: https://github.com/paulholden2/prontoforms/releases/tag/v0.2.0
30
+ [v0.3.0]: https://github.com/paulholden2/prontoforms/releases/tag/v0.3.0
31
+ [v0.3.1]: https://github.com/paulholden2/prontoforms/releases/tag/v0.3.1
data/Gemfile CHANGED
@@ -1,4 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in prontoforms.gemspec
4
6
  gemspec
7
+
8
+ group :development, :test do
9
+ gem 'simplecov', '~> 0.17.1'
10
+ end
data/README.md CHANGED
@@ -1,7 +1,12 @@
1
1
  # ProntoForms
2
2
 
3
+ [![Build Status](https://img.shields.io/endpoint.svg?url=https%3A%2F%2Factions-badge.atrox.dev%2Fpaulholden2%2Fprontoforms%2Fbadge%3Fref%3Dmaster&style=flat)](https://actions-badge.atrox.dev/paulholden2/prontoforms/goto?ref=master) [![Gem Version](https://badge.fury.io/rb/prontoforms.svg)](https://badge.fury.io/rb/prontoforms) [![Inline docs](http://inch-ci.org/github/paulholden2/prontoforms.svg?branch=master)](http://inch-ci.org/github/paulholden2/prontoforms) [![Maintainability](https://api.codeclimate.com/v1/badges/e47cd40058313e1c1c38/maintainability)](https://codeclimate.com/github/paulholden2/prontoforms/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/e47cd40058313e1c1c38/test_coverage)](https://codeclimate.com/github/paulholden2/prontoforms/test_coverage)
4
+
3
5
  A library for interacting with the ProntoForms REST API in Ruby applications.
4
6
 
7
+ Note: version 0.4.0 included a breaking change, and has been yanked from
8
+ RubyGems. If you are using it, please upgrade to 1.x or revert to 0.3.1.
9
+
5
10
  ## Installation
6
11
 
7
12
  Add this line to your application's Gemfile:
@@ -20,7 +25,16 @@ Or install it yourself as:
20
25
 
21
26
  ## Usage
22
27
 
23
- Check back later
28
+ To get started, first [create a ProntoForms API key] in your ProntoForms
29
+ account. Then you can begin using the API client in your Ruby application:
30
+
31
+ ```rb
32
+ client = ProntoForms::Client.new(api_key_id, api_key_secret)
33
+ client.form_spaces # Returns all FormSpaces in your account
34
+ ```
35
+
36
+ Review [the documentation](https://rubydoc.info/github/paulholden2/prontoforms)
37
+ for more information on how to use this library to interact with ProntoForms.
24
38
 
25
39
  ## Development
26
40
 
@@ -37,3 +51,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/paulho
37
51
  ## License
38
52
 
39
53
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
54
+
55
+ [create a ProntoForms API key]: https://support.prontoforms.com/hc/en-us/articles/217496468-Setup-an-API-Application-on-ProntoForms#Create
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
@@ -1,14 +1,8 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
- require "bundler/setup"
4
- require "prontoforms"
4
+ require 'bundler/setup'
5
+ require 'prontoforms'
6
+ require 'irb'
5
7
 
6
- # You can add fixtures and/or initialization code here to make experimenting
7
- # with your gem easier. You can also use a different console, if you like.
8
-
9
- # (If you use this, don't forget to add pry to your Gemfile!)
10
- # require "pry"
11
- # Pry.start
12
-
13
- require "irb"
14
8
  IRB.start(__FILE__)
data/bin/setup CHANGED
@@ -1,8 +1,8 @@
1
1
  #!/usr/bin/env bash
2
+ # frozen_string_literal: true
3
+
2
4
  set -euo pipefail
3
5
  IFS=$'\n\t'
4
6
  set -vx
5
7
 
6
8
  bundle install
7
-
8
- # Do any other automated setup that you need to do here
@@ -1,6 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'prontoforms/version'
2
4
  require 'prontoforms/client'
3
5
 
4
6
  module ProntoForms
5
- class Error < StandardError; end
7
+ # Base error class.
8
+ class Error < StandardError
9
+ attr_reader :message
10
+
11
+ def initialize(message)
12
+ @message = message
13
+ end
14
+ end
6
15
  end
@@ -1,40 +1,102 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'faraday'
2
4
  require 'json'
3
5
  require 'prontoforms/resource_list'
4
6
  require 'prontoforms/form_space'
5
7
  require 'prontoforms/form_submission'
8
+ require 'prontoforms/user'
6
9
 
7
10
  module ProntoForms
11
+ # Allows you to retrieve resources from ProntoForms and perform other
12
+ # functions with the API.
8
13
  class Client
9
- attr_reader :api_key_id, :api_key_secret
14
+ # @return [String] ProntoForms API key ID
15
+ attr_reader :api_key_id
16
+ # @return [String] ProntoForms API key secret
17
+ attr_reader :api_key_secret
10
18
 
19
+ # Create a client and use provided API credentials
20
+ # @param api_key_id Your ProntoForms REST API key
21
+ # @param api_key_secret Your ProntoForms REST API secret
11
22
  def initialize(api_key_id, api_key_secret)
12
23
  @api_key_id = api_key_id
13
24
  @api_key_secret = api_key_secret
14
25
  end
15
26
 
16
- def self.resource(method, verb: :get, resource:, url: resource.resource_name)
17
- # TODO: Raise error if verb is invalid
18
-
27
+ # Defines a resource that can be retrieved in a list
28
+ # @return [nil]
29
+ # @api private
30
+ # @!macro [attach] resource_list
31
+ # @method $1
32
+ # Retrieve a list of $2 resources
33
+ # @return [ResourceList] A ResourceList containing $2 results
34
+ def self.resource_list(method, resource, url = resource.resource_name)
19
35
  define_method(method) do |query: {}|
20
- res = connection.send(verb) do |req|
36
+ res = connection.get do |req|
21
37
  req.url url
22
38
  query.each { |k, v| req.params[k] = v }
23
39
  end
24
- if res.success?
25
- ResourceList.new(JSON.parse(res.body), 0, 20, method, resource, self)
26
- else
27
- nil
28
- end
40
+
41
+ data = JSON.parse(res.body)
42
+
43
+ return nil if data.fetch('pageData').size.zero?
44
+
45
+ ResourceList.new(data, { 'p' => 0, 's' => 100 }.merge(query), method,
46
+ resource, self)
29
47
  end
30
48
  end
31
49
 
32
- resource :form_spaces, resource: FormSpace
33
- resource :form_submissions, resource: FormSubmission
50
+ resource_list :form_spaces, FormSpace
51
+ resource_list :form_submissions, FormSubmission
52
+
53
+ # Retrieve a user by identifier
54
+ # @param id [String] The user identifier
55
+ # @return [User] A User object for the requested user
56
+ def user(id)
57
+ raise ArgumentError, 'id must be provided' if id.nil?
58
+
59
+ res = connection.get do |req|
60
+ req.url "users/#{id}"
61
+ end
62
+
63
+ User.new(JSON.parse(res.body), self)
64
+ end
65
+
66
+ # Retrieve a form space by its identifier
67
+ # @param id [String] The form space identifier
68
+ # @return [FormSpace] A FormSpace object
69
+ def form_space(id)
70
+ raise ArgumentError, 'id must be provided' if id.nil?
71
+
72
+ res = connection.get do |req|
73
+ req.url "formspaces/#{id}"
74
+ end
75
+
76
+ FormSpace.new(JSON.parse(res.body), self)
77
+ end
78
+
79
+ # Retrieve a form submission by identifier
80
+ # @param id [String] The form submission identifier
81
+ # @return [FormSubmission] A FormSubmission object
82
+ def form_submission(id)
83
+ return nil if id.nil?
84
+
85
+ res = connection.get do |req|
86
+ req.url "data/#{id}"
87
+ end
88
+
89
+ FormSubmission.new(JSON.parse(res.body), self)
90
+ end
34
91
 
92
+ # Create a connection that can be used to execute a request against the
93
+ # ProntoForms API.
94
+ # @return [Faraday::Connection]
95
+ # @api private
35
96
  def connection
36
97
  Faraday.new(url: 'https://api.prontoforms.com/api/1.1') do |conn|
37
98
  conn.basic_auth(api_key_id, api_key_secret)
99
+ conn.use Faraday::Response::RaiseError
38
100
  end
39
101
  end
40
102
  end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'prontoforms/resource'
4
+
5
+ module ProntoForms
6
+ # A Document is a configuration that generates output data or files when
7
+ # attached to a form.
8
+ class Document < Resource
9
+ def self.resource_name
10
+ 'documents'
11
+ end
12
+
13
+ # @return [String] The Document identifier
14
+ property :id, key: 'identifier'
15
+ # @return [String] Document type
16
+ property :type, key: 'type'
17
+ # @return [String] Document name
18
+ property :name, key: 'name'
19
+ # @return [String] Document descriptiojn
20
+ property :description, key: 'description'
21
+ # @return [String] Document form version
22
+ property :form_document_version, key: 'formDocumentVersion'
23
+ # @return [Boolean] Whether the document is standard (system generated)
24
+ property :standard, key: 'standard'
25
+ # @return [String] Whether the document auto-links to new forms
26
+ property :auto_link, key: 'autoLink'
27
+
28
+ alias standard? standard
29
+ alias auto_link? auto_link
30
+ end
31
+ end
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'prontoforms/resource'
4
+ require 'prontoforms/form_iteration'
5
+
6
+ module ProntoForms
7
+ # A form includes inputs, validations, logic, and other configuration that
8
+ # facilitates data capture for a specific purpose.
9
+ class Form < Resource
10
+ def self.resource_name
11
+ 'forms'
12
+ end
13
+
14
+ # @return [String] The Form identifier
15
+ property :id, key: 'identifier'
16
+ # @return [String] Form name
17
+ property :name, key: 'name'
18
+ # @return [String] Form description
19
+ property :description, key: 'description'
20
+ # @return [String] Form state
21
+ property :state, key: 'state'
22
+
23
+ # Get the Form's form space ID
24
+ # @return [String] Form space identifier
25
+ def form_space_id
26
+ parent.id
27
+ end
28
+
29
+ def active_version_id
30
+ full_data.dig('activeVersion', 'identifier')
31
+ end
32
+
33
+ def current_version
34
+ res = client.connection.get do |req|
35
+ req.url "#{url}/iterations/#{active_version_id}"
36
+ end
37
+
38
+ FormIteration.new(JSON.parse(res.body), client, self)
39
+ end
40
+
41
+ def iteration(id)
42
+ raise ArgumentError, 'id must be provided' if id.nil?
43
+
44
+ res = client.connection.get do |req|
45
+ req.url "#{url}/iterations/#{id}"
46
+ end
47
+
48
+ FormIteration.new(JSON.parse(res.body), client, self)
49
+ end
50
+
51
+ def iterations(query: {})
52
+ res = client.connection.get do |req|
53
+ req.url "#{url}/iterations"
54
+ end
55
+
56
+ ResourceList.new(JSON.parse(res.body), {
57
+ 'p' => 0,
58
+ 's' => 100
59
+ }.merge(query), :iterations, FormIteration, client, self)
60
+ end
61
+
62
+ private
63
+
64
+ def full_data
65
+ return @full_data unless @full_data.nil?
66
+
67
+ @full_data = client.form_space(form_space_id).form(id).data
68
+ @full_data
69
+ end
70
+
71
+ def url
72
+ "formspaces/#{form_space_id}/forms/#{id}"
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'prontoforms/resource'
4
+
5
+ module ProntoForms
6
+ # A form iteration is a form configuration, distinct from a form version
7
+ # in that version numbers increment when a form iteration is deployed.
8
+ class FormIteration < Resource
9
+ def self.resource_name
10
+ 'iterations'
11
+ end
12
+
13
+ # @return [String] The form iteration identifier
14
+ property :id, key: 'identifier'
15
+ # @return [Integer] Version number
16
+ property :version, key: 'version'
17
+ # @return [String] Form iteration state
18
+ property :state, key: 'state'
19
+ # @return [String] Initiation method for the form iteration
20
+ property :initiation_method, key: 'initiationMethod'
21
+ # @return [String] Can dispatched forms of this iteration be declined
22
+ property :dispatched_declinable, key: 'dispatchDeclinable'
23
+
24
+ alias can_decline_dispatch? dispatched_declinable
25
+
26
+ # @return [Array] Array of document IDs attached to this iteration
27
+ def document_ids
28
+ full_data.fetch('documentIds')
29
+ end
30
+
31
+ private
32
+
33
+ def full_data
34
+ return @full_data unless @full_data.nil?
35
+
36
+ @full_data = parent.iteration(id).data
37
+ @full_data
38
+ end
39
+ end
40
+ end
@@ -1,10 +1,57 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'prontoforms/resource'
4
+ require 'prontoforms/form'
5
+ require 'prontoforms/document'
2
6
 
3
7
  module ProntoForms
8
+ # Represents a form space resource in ProntoForms. Form spaces are the
9
+ # primary organizational unit for forms, data sources, destinations, and
10
+ # other resources.
4
11
  class FormSpace < Resource
12
+ # @return [String] The FormSpace identifier
5
13
  property :id, key: 'identifier'
14
+ # @return [String] The FormSpace name
6
15
  property :name, key: 'name'
16
+ # @return [String] The address that error emails are sent to
7
17
  property :problem_contact_email, key: 'problemContactEmail'
18
+ # @return [Boolean] Whether updates are automatically pushed to devices
8
19
  property :push_updates_to_device, key: 'pushUpdatesToDevice'
20
+
21
+ # Get all documents in the form space
22
+ # @return [ResourceList] A ResourceList containing Document objects
23
+ def documents
24
+ res = client.connection.get do |req|
25
+ req.url "formspaces/#{id}/documents"
26
+ end
27
+
28
+ ResourceList.new(JSON.parse(res.body), {
29
+ 'p' => 0,
30
+ 's' => 100
31
+ }, :documents, Document, self)
32
+ end
33
+
34
+ def form(form_id)
35
+ res = client.connection.get do |req|
36
+ req.url "formspaces/#{id}/forms/#{form_id}"
37
+ end
38
+
39
+ data = JSON.parse(res.body)
40
+ Form.new(data, client, self)
41
+ end
42
+
43
+ # Get all forms in the form space
44
+ # @return [ResourceList] A ResourceList containing Form objects
45
+ def forms(query: {})
46
+ res = client.connection.get do |req|
47
+ req.url "formspaces/#{id}/forms"
48
+ query.each { |k, v| req.params[k] = v }
49
+ end
50
+
51
+ ResourceList.new(JSON.parse(res.body), {
52
+ 'p' => 0,
53
+ 's' => 100
54
+ }.merge(query), :forms, Form, client, self)
55
+ end
9
56
  end
10
57
  end
@@ -1,36 +1,137 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'json'
2
4
  require 'prontoforms/resource'
3
5
 
4
6
  module ProntoForms
7
+ # A FormSubmission represents submitted form data in ProntoForms. It
8
+ # includes various metadata about the submission as well.
5
9
  class FormSubmission < Resource
6
- def self.resource_name() 'data'; end
10
+ def self.resource_name
11
+ 'data'
12
+ end
7
13
 
14
+ # @return [String] The FormSubmission identifier
8
15
  property :id, key: 'identifier'
16
+ # @return [String] Submission reference number
9
17
  property :reference_number, key: 'referenceNumber'
18
+ # @return [String] Submission state. One of: Complete, Processing,
19
+ # Dispatched
10
20
  property :state, key: 'state'
21
+ # @return [String] Submission data state
11
22
  property :data_state, key: 'dataState'
23
+ # @return [Boolean] Has the submission data been persisted on the server
12
24
  property :data_persisted, key: 'dataPersisted'
25
+ # @return [String] The form's version identifier
13
26
  property :form_version_id, key: 'formVersionId'
27
+ # @return [String] The form's identifier
14
28
  property :form_id, key: 'formId'
29
+ # @return [String] Submitter's user identifier
15
30
  property :user_id, key: 'userId'
31
+ # @return [String] Submitter's username
16
32
  property :username, key: 'username'
17
- # Aliases
18
- property :data_persisted?, key: 'dataPersisted'
19
- property :submitter_id, key: 'userId'
20
- property :submitter_username, key: 'username'
21
33
 
34
+ alias data_persisted? data_persisted
35
+ alias submitter_id user_id
36
+ alias submitter_username username
37
+
38
+ # @return [DateTime] Timestamp the submission was received by the server
22
39
  property :server_receive_date do
23
40
  str = data.fetch('serverReceiveDate')
24
41
  str.nil? ? nil : DateTime.strptime(str)
25
42
  end
26
43
 
44
+ # Retrieve the pages containing the form questions and answers
45
+ # @return [Hash] Hash of questions and answers for the FormSubmission
27
46
  def pages
47
+ document.fetch('pages')
48
+ end
49
+
50
+ # Retrieve the dispatching User, if the form was dispatched
51
+ # @return [User] The user that dispatched the form, or nil
52
+ def dispatcher
53
+ return nil unless dispatched?
54
+
55
+ client.user(document.dig('dispatcher', 'identifier'))
56
+ end
57
+
58
+ # Check if the form was dispatched
59
+ # @return [Boolean] True if the form was dispatched; false otherwise
60
+ def dispatched?
61
+ !document.dig('dispatcher', 'identifier').nil?
62
+ end
63
+
64
+ # Retrieve the form space for the form submission
65
+ # @return [FormSpace] Form space for the submission's form
66
+ def form_space
67
+ client.form_space(full_data.dig('form', 'formSpaceId'))
68
+ end
69
+
70
+ # Retrieve the form for the form submission
71
+ # @return [Form] Form for the submission
72
+ def form
73
+ form_space.form(full_data.dig('form', 'formId'))
74
+ end
75
+
76
+ # Retrieve the current version of the form
77
+ # @return [FormIteration] The form iteration
78
+ def form_version
79
+ form.current_version
80
+ end
81
+
82
+ # Retrieve all documents attached to this form submission
83
+ # @return [Array] Documents attached to the form submission
84
+ def documents(populate: false)
85
+ ids = form_version.document_ids
86
+ if populate
87
+ ids.map { |id| form.iteration(id) }
88
+ else
89
+ ids
90
+ end
91
+ end
92
+
93
+ # Download a specific document. The Document must have been attached to
94
+ # the form's current version at the time of submission.
95
+ # @return [IO] Data stream for the document
96
+ def download_document(document)
97
+ io = StringIO.new
98
+ client.connection.get do |req|
99
+ req.url "#{url}/documents/#{document.id}"
100
+ req.options.on_data = proc { |chunk| io << chunk }
101
+ end
102
+ io.rewind
103
+ io
104
+ end
105
+
106
+ private
107
+
108
+ def url
109
+ "#{resource_name}/#{id}"
110
+ end
111
+
112
+ def full_data
113
+ return @full_data unless @full_data.nil?
114
+
115
+ @full_data = client.form_submission(id).data
116
+ @full_data
117
+ end
118
+
119
+ # Returns additional data about the submission. Uses cached data,
120
+ # otherwise it loads and returns the data via #document!
121
+ def document
122
+ return @document unless @document.nil?
123
+
124
+ document!
125
+ end
126
+
127
+ # Force loads the submission document
128
+ def document!
28
129
  res = client.connection.get do |req|
29
130
  req.url "#{resource_name}/#{id}/document.json"
30
131
  end
31
- if res.success?
32
- JSON.parse(res.body).fetch('pages')
33
- end
132
+
133
+ @document = JSON.parse(res.body)
134
+ @document
34
135
  end
35
136
  end
36
137
  end
@@ -1,19 +1,29 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'date'
2
4
 
3
5
  module ProntoForms
6
+ # Base class for resource-related classes.
4
7
  class Resource
5
- attr_reader :data, :client, :parent
8
+ # @return [Hash] Retrieve raw JSON data associated with this resource
9
+ attr_reader :data
10
+ # @return [Client] API client
11
+ attr_reader :client
12
+ # @return [Resource] Parent object (applicable to child resources)
13
+ attr_reader :parent
6
14
 
15
+ # Defines a property of the resource
16
+ # @return [nil]
17
+ # @api private
7
18
  def self.property(name, key: nil, &block)
8
- define_method(name) {
19
+ define_method(name) do
9
20
  if block_given?
10
21
  instance_eval(&block)
11
22
  elsif !key.nil?
12
- data.fetch(key)
13
- else
14
- nil
23
+ key = [key] unless key.is_a?(Array)
24
+ key.inject(data) { |obj, k| obj.fetch(k) }
15
25
  end
16
- }
26
+ end
17
27
  end
18
28
 
19
29
  def initialize(data, client, parent = nil)
@@ -22,11 +32,13 @@ module ProntoForms
22
32
  @parent = parent
23
33
  end
24
34
 
35
+ # The resource's identifier
25
36
  def self.resource_name
26
- name = self.to_s.split("::").last
37
+ name = to_s.split('::').last
27
38
  "#{name.downcase}s"
28
39
  end
29
40
 
41
+ # The resource's identifier
30
42
  def resource_name
31
43
  self.class.resource_name
32
44
  end
@@ -1,25 +1,46 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'prontoforms/resource'
2
4
 
3
5
  module ProntoForms
6
+ # A wrapper for retrieving paged resources.
4
7
  class ResourceList < Resource
5
- attr_reader :limit, :offset, :method, :resource, :client, :parent
8
+ # @return [Hash] Query parameters for this resource list for e.g. filters
9
+ attr_reader :query
10
+ # @return [Symbol] Method to send to parent object (usually the client)
11
+ attr_reader :method
12
+ # @return [Class] Resource class
13
+ attr_reader :resource
14
+ # @return [Client] API client
15
+ attr_reader :client
16
+ # @return [Resource] Parent object (for child resources)
17
+ attr_reader :parent
6
18
 
7
- def initialize(data, offset, limit, method, resource, client, parent = nil)
19
+ # Initialize the resource list
20
+ # TODO: splat
21
+ # rubocop:disable Metrics/ParameterLists
22
+ def initialize(data, query, method, resource, client, parent = nil)
8
23
  super(data, client)
9
- @limit = limit
10
- @offset = offset
24
+ @query = query
11
25
  @method = method
12
26
  @resource = resource
27
+ @parent = parent
13
28
  end
29
+ # rubocop:enable Metrics/ParameterLists
14
30
 
31
+ # Retrieve the next page of results, using the same number of items per
32
+ # page as the original request.
33
+ # @return [ResourceList] A ResourceList with the next set of results
15
34
  def next
16
- client.send(method, limit: limit, offset: offset + limit)
35
+ client.send(method, query: query.merge({ 'p' => query['p'] + 1 }))
17
36
  end
18
37
 
38
+ # Retrieve the result set
39
+ # @return [Array] Array of resource objects
19
40
  def items
20
- @data.fetch('pageData').map { |item|
41
+ @data.fetch('pageData').map do |item|
21
42
  resource.new(item, client, parent)
22
- }
43
+ end
23
44
  end
24
45
  end
25
46
  end
@@ -0,0 +1,34 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'prontoforms/resource'
4
+
5
+ module ProntoForms
6
+ # A ProntoForms user account.
7
+ class User < Resource
8
+ def self.resource_name
9
+ 'users'
10
+ end
11
+
12
+ # @return [String] The User identifier
13
+ property :id, key: 'identifier'
14
+ # @return [String] The user's username
15
+ property :username, key: 'username'
16
+ # @return [String] The user's role
17
+ property :role, key: 'role'
18
+ # @return [String] The user's email address
19
+ property :email, key: 'email'
20
+ # @return [String] The user's first name
21
+ property :first_name, key: 'firstName'
22
+ # @return [String] The user's last name
23
+ property :last_name, key: 'lastName'
24
+ # @return [String] The user's preferred locale
25
+ property :locale, key: 'locale'
26
+
27
+ # Get a display name consisting of the first name followed by last name
28
+ # e.g. "John Doe"
29
+ # @return [String] The display name for the user
30
+ def display_name
31
+ "#{first_name} #{last_name}"
32
+ end
33
+ end
34
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module ProntoForms
2
- VERSION = '0.1.0'
4
+ VERSION = '2.0.0'
3
5
  end
@@ -1,16 +1,19 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require_relative 'lib/prontoforms/version'
2
4
 
5
+ # rubocop:disable Layout/LineLength
3
6
  Gem::Specification.new do |spec|
4
- spec.name = 'prontoforms'
5
- spec.version = ProntoForms::VERSION
6
- spec.authors = ['Paul Holden']
7
- spec.email = ['paul@holdensoftware.com']
7
+ spec.name = 'prontoforms'
8
+ spec.version = ProntoForms::VERSION
9
+ spec.authors = ['Paul Holden']
10
+ spec.email = ['paul@codelunker.com']
8
11
 
9
- spec.summary = 'A library for using the ProntoForms REST API in Ruby applications.'
10
- spec.description = 'A library for using the ProntoForms REST API in Ruby applications.'
11
- spec.homepage = 'https://github.com/paulholden2/prontoforms'
12
- spec.license = 'MIT'
13
- spec.required_ruby_version = Gem::Requirement.new('>= 2.3.0')
12
+ spec.summary = 'A library for using the ProntoForms REST API in Ruby applications.'
13
+ spec.description = 'A library for using the ProntoForms REST API in Ruby applications.'
14
+ spec.homepage = 'https://github.com/paulholden2/prontoforms'
15
+ spec.license = 'MIT'
16
+ spec.required_ruby_version = Gem::Requirement.new('>= 2.6.0')
14
17
 
15
18
  spec.metadata['allowed_push_host'] = 'https://rubygems.org'
16
19
 
@@ -19,17 +22,27 @@ Gem::Specification.new do |spec|
19
22
  spec.metadata['changelog_uri'] = 'https://github.com/paulholden2/prontoforms/blog/master/CHANGELOG.md'
20
23
 
21
24
  # Specify which files should be added to the gem when it is released.
22
- # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
23
- spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
24
- `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
25
+ # The `git ls-files -z` loads the files in the RubyGem that have been added
26
+ # into git.
27
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
28
+ `git ls-files -z`.split("\x0").reject do |f|
29
+ f.match(%r{^(test|spec|features)/})
30
+ end
25
31
  end
26
- spec.bindir = 'exe'
27
- spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
32
+
33
+ spec.bindir = 'exe'
34
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
35
  spec.require_paths = ['lib']
29
36
 
30
37
  spec.add_dependency 'faraday', '~> 1.0'
31
38
 
32
39
  spec.add_development_dependency 'bundler', '~> 2.0'
33
- spec.add_development_dependency 'rake', '~> 10.0'
40
+ spec.add_development_dependency 'rake', '>= 12.3.3'
34
41
  spec.add_development_dependency 'rspec', '~> 3.0'
42
+ spec.add_development_dependency 'rubocop', '~> 0.82.0'
43
+ spec.add_development_dependency 'sinatra', '~> 2.0'
44
+ spec.add_development_dependency 'sinatra-contrib', '~> 2.0'
45
+ spec.add_development_dependency 'webmock', '~> 3.6'
46
+ spec.add_development_dependency 'yard', '~> 0.9'
35
47
  end
48
+ # rubocop:enable Layout/LineLength
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: prontoforms
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Paul Holden
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-08-25 00:00:00.000000000 Z
11
+ date: 2020-12-14 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: rake
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: 12.3.3
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: 12.3.3
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rspec
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -66,19 +66,90 @@ dependencies:
66
66
  - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: '3.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: 0.82.0
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: 0.82.0
83
+ - !ruby/object:Gem::Dependency
84
+ name: sinatra
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '2.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '2.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sinatra-contrib
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '2.0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '2.0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: webmock
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.6'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.6'
125
+ - !ruby/object:Gem::Dependency
126
+ name: yard
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.9'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.9'
69
139
  description: A library for using the ProntoForms REST API in Ruby applications.
70
140
  email:
71
- - paul@holdensoftware.com
141
+ - paul@codelunker.com
72
142
  executables: []
73
143
  extensions: []
74
144
  extra_rdoc_files: []
75
145
  files:
146
+ - ".github/workflows/checks.yml"
76
147
  - ".gitignore"
77
148
  - ".rspec"
149
+ - ".rubocop.yml"
78
150
  - ".travis.yml"
79
151
  - CHANGELOG.md
80
152
  - Gemfile
81
- - Gemfile.lock
82
153
  - LICENSE.txt
83
154
  - README.md
84
155
  - Rakefile
@@ -86,10 +157,14 @@ files:
86
157
  - bin/setup
87
158
  - lib/prontoforms.rb
88
159
  - lib/prontoforms/client.rb
160
+ - lib/prontoforms/document.rb
161
+ - lib/prontoforms/form.rb
162
+ - lib/prontoforms/form_iteration.rb
89
163
  - lib/prontoforms/form_space.rb
90
164
  - lib/prontoforms/form_submission.rb
91
165
  - lib/prontoforms/resource.rb
92
166
  - lib/prontoforms/resource_list.rb
167
+ - lib/prontoforms/user.rb
93
168
  - lib/prontoforms/version.rb
94
169
  - prontoforms.gemspec
95
170
  homepage: https://github.com/paulholden2/prontoforms
@@ -108,14 +183,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
183
  requirements:
109
184
  - - ">="
110
185
  - !ruby/object:Gem::Version
111
- version: 2.3.0
186
+ version: 2.6.0
112
187
  required_rubygems_version: !ruby/object:Gem::Requirement
113
188
  requirements:
114
189
  - - ">="
115
190
  - !ruby/object:Gem::Version
116
191
  version: '0'
117
192
  requirements: []
118
- rubygems_version: 3.0.8
193
+ rubygems_version: 3.1.4
119
194
  signing_key:
120
195
  specification_version: 4
121
196
  summary: A library for using the ProntoForms REST API in Ruby applications.
@@ -1,39 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- prontoforms (0.1.0)
5
- faraday (~> 1.0)
6
-
7
- GEM
8
- remote: https://rubygems.org/
9
- specs:
10
- diff-lcs (1.4.4)
11
- faraday (1.0.1)
12
- multipart-post (>= 1.2, < 3)
13
- multipart-post (2.1.1)
14
- rake (10.5.0)
15
- rspec (3.9.0)
16
- rspec-core (~> 3.9.0)
17
- rspec-expectations (~> 3.9.0)
18
- rspec-mocks (~> 3.9.0)
19
- rspec-core (3.9.2)
20
- rspec-support (~> 3.9.3)
21
- rspec-expectations (3.9.2)
22
- diff-lcs (>= 1.2.0, < 2.0)
23
- rspec-support (~> 3.9.0)
24
- rspec-mocks (3.9.1)
25
- diff-lcs (>= 1.2.0, < 2.0)
26
- rspec-support (~> 3.9.0)
27
- rspec-support (3.9.3)
28
-
29
- PLATFORMS
30
- ruby
31
-
32
- DEPENDENCIES
33
- bundler (~> 2.0)
34
- prontoforms!
35
- rake (~> 10.0)
36
- rspec (~> 3.0)
37
-
38
- BUNDLED WITH
39
- 2.1.4