Commit 291179ed2e407c287e1359c1add0a9900164fa69
Committed by
GitHub
Merge pull request #2 from wildland/query
Query Endpoint
Showing
46 changed files
with
1499 additions
and
255 deletions
Show diff stats
| 1 | +# Changelog | |
| 2 | +All notable changes to this project will be documented in this file. | |
| 3 | + | |
| 4 | +The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/) | |
| 5 | +and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html). | |
| 6 | + | |
| 7 | +## [Unreleased] | |
| 8 | +### Added | |
| 9 | +### Changed | |
| 10 | +### Deprecated | |
| 11 | +### Removed | |
| 12 | +### Fixed | |
| 13 | +### Security | |
| 14 | + | |
| 15 | +## 0.1.0 - 2018-04-06 | |
| 16 | +### Added | |
| 17 | +- CHANGELOG file | |
| 18 | +- `rubocop` gem | |
| 19 | +- `vcr` gem | |
| 20 | +- Query Endpoint | ... | ... |
Gemfile
Gemfile.lock
| 1 | 1 | PATH |
| 2 | 2 | remote: . |
| 3 | 3 | specs: |
| 4 | - syspro (0.1.0) | |
| 4 | + syspro-ruby (1.0.0.alpha.1) | |
| 5 | 5 | faraday (~> 0.10) |
| 6 | + nokogiri (~> 1.8.2) | |
| 6 | 7 | |
| 7 | 8 | GEM |
| 8 | 9 | remote: https://rubygems.org/ |
| 9 | 10 | specs: |
| 11 | + addressable (2.5.2) | |
| 12 | + public_suffix (>= 2.0.2, < 4.0) | |
| 13 | + ast (2.4.0) | |
| 10 | 14 | coderay (1.1.2) |
| 15 | + crack (0.4.3) | |
| 16 | + safe_yaml (~> 1.0.0) | |
| 11 | 17 | faraday (0.14.0) |
| 12 | 18 | multipart-post (>= 1.2, < 3) |
| 19 | + hashdiff (0.3.7) | |
| 13 | 20 | method_source (0.9.0) |
| 21 | + mini_portile2 (2.3.0) | |
| 22 | + minispec-metadata (2.0.0) | |
| 23 | + minitest | |
| 14 | 24 | minitest (5.11.3) |
| 25 | + minitest-vcr (1.4.0) | |
| 26 | + minispec-metadata (~> 2.0) | |
| 27 | + minitest (>= 4.7.5) | |
| 28 | + vcr (>= 2.9) | |
| 15 | 29 | multipart-post (2.0.0) |
| 30 | + nokogiri (1.8.2) | |
| 31 | + mini_portile2 (~> 2.3.0) | |
| 32 | + parallel (1.12.1) | |
| 33 | + parser (2.5.0.5) | |
| 34 | + ast (~> 2.4.0) | |
| 35 | + powerpack (0.1.1) | |
| 16 | 36 | pry (0.11.3) |
| 17 | 37 | coderay (~> 1.1.0) |
| 18 | 38 | method_source (~> 0.9.0) |
| 39 | + public_suffix (3.0.2) | |
| 40 | + rainbow (3.0.0) | |
| 19 | 41 | rake (10.5.0) |
| 42 | + rubocop (0.54.0) | |
| 43 | + parallel (~> 1.10) | |
| 44 | + parser (>= 2.5) | |
| 45 | + powerpack (~> 0.1) | |
| 46 | + rainbow (>= 2.2.2, < 4.0) | |
| 47 | + ruby-progressbar (~> 1.7) | |
| 48 | + unicode-display_width (~> 1.0, >= 1.0.1) | |
| 49 | + ruby-progressbar (1.9.0) | |
| 50 | + safe_yaml (1.0.4) | |
| 51 | + unicode-display_width (1.3.0) | |
| 52 | + vcr (4.0.0) | |
| 53 | + webmock (3.3.0) | |
| 54 | + addressable (>= 2.3.6) | |
| 55 | + crack (>= 0.3.2) | |
| 56 | + hashdiff | |
| 20 | 57 | |
| 21 | 58 | PLATFORMS |
| 22 | 59 | ruby |
| ... | ... | @@ -24,9 +61,12 @@ PLATFORMS |
| 24 | 61 | DEPENDENCIES |
| 25 | 62 | bundler (~> 1.16) |
| 26 | 63 | minitest (~> 5.0) |
| 64 | + minitest-vcr (~> 1.4.0) | |
| 27 | 65 | pry (~> 0.11) |
| 28 | 66 | rake (~> 10.0) |
| 29 | - syspro! | |
| 67 | + rubocop (~> 0.54.0) | |
| 68 | + syspro-ruby! | |
| 69 | + webmock (~> 3.3.0) | |
| 30 | 70 | |
| 31 | 71 | BUNDLED WITH |
| 32 | 72 | 1.16.1 | ... | ... |
README.md
| ... | ... | @@ -72,6 +72,103 @@ logged_off = Syspro::Logoff.logoff(guid) |
| 72 | 72 | ``` |
| 73 | 73 | `logged_off` will be `true` if the user has been successfully logged off, and will contain an error string if an error has occured. |
| 74 | 74 | |
| 75 | +### Query | |
| 76 | + | |
| 77 | +#### Browse | |
| 78 | +Browse returns a paginated view of a particular table. | |
| 79 | + | |
| 80 | +This is an example using the generic Browse Business Object, `COMBRW`. | |
| 81 | +```rb | |
| 82 | +combrw = Syspro::BusinessObject::ComBrw.new | |
| 83 | +combrw.browse_name = "InvMaster" | |
| 84 | +combrw.start_condition = "" | |
| 85 | +combrw.return_rows = 5 | |
| 86 | +combrw.filters = [] | |
| 87 | +combrw.table_name = "InvMaster" | |
| 88 | +combrw.title = "StockCodes" | |
| 89 | +combrw.columns = [ | |
| 90 | + {name: "StockCode"} | |
| 91 | +] | |
| 92 | + | |
| 93 | +browse_result = combrw.call(user_id.guid) | |
| 94 | +``` | |
| 95 | + | |
| 96 | +`browse_result` will be a BrowseObject, which has the following structure: | |
| 97 | + | |
| 98 | +```rb | |
| 99 | +{ | |
| 100 | + title: "Title", | |
| 101 | + rows: [ { name: "", value: "", data_type: "" } ], | |
| 102 | + next_prev_key: { name: "", text: "" }, | |
| 103 | + header_details: { name: "", text: "" } | |
| 104 | +} | |
| 105 | +``` | |
| 106 | + | |
| 107 | +#### Query | |
| 108 | + | |
| 109 | +Query gives control over joins between multiple tables over a single Business Object. | |
| 110 | + | |
| 111 | +This is an example using the generic Query Business Object, `COMFND`. | |
| 112 | + | |
| 113 | +```rb | |
| 114 | +comfnd = Syspro::BusinessObjects::ComFnd.new | |
| 115 | +comfnd.table_name = "InvMaster" | |
| 116 | +comfnd.return_rows = 5 | |
| 117 | +comfnd.columns = [ | |
| 118 | + { | |
| 119 | + name: "StockCode" | |
| 120 | + } | |
| 121 | +] | |
| 122 | +comfnd.expressions = [ | |
| 123 | + { | |
| 124 | + andor: "And", | |
| 125 | + column: "StockCode", | |
| 126 | + condition: "EQ", | |
| 127 | + value: "02" | |
| 128 | + } | |
| 129 | +] | |
| 130 | +comfnd.order_by = "StockCode" | |
| 131 | + | |
| 132 | +query_result = comfnd.call(user_id.guid) | |
| 133 | +``` | |
| 134 | + | |
| 135 | +This will return a QueryObject, which looks like this: | |
| 136 | + | |
| 137 | +```rb | |
| 138 | +{ | |
| 139 | + header_details: { name: "", text: "" }, | |
| 140 | + rows: [ { name: "", value: "" } ], | |
| 141 | + row_count: 1 | |
| 142 | +} | |
| 143 | +``` | |
| 144 | + | |
| 145 | +#### Fetch | |
| 146 | + | |
| 147 | +Fetch selects the `TOP 1` of the query. | |
| 148 | + | |
| 149 | +This is an example using the generic Fetch Business Object, `COMFCH`. | |
| 150 | + | |
| 151 | +```rb | |
| 152 | +comfch = Syspro::BusinessObjects::ComFch.new | |
| 153 | +comfch.table_name = "InvMaster" | |
| 154 | +comfch.key = "02" | |
| 155 | +comfch.optional_keys = [] | |
| 156 | +comfch.full_key_provided = false | |
| 157 | +comfch.default_type = "" | |
| 158 | +comfch.espresso_fetch = true | |
| 159 | + | |
| 160 | +fetch_result = comfch.call(user_id.guid) | |
| 161 | +``` | |
| 162 | + | |
| 163 | +This will return a FetchObject, with the following structure: | |
| 164 | + | |
| 165 | +```rb | |
| 166 | +{ | |
| 167 | + table_name: "", | |
| 168 | + columns: [ { name: "", value: "" } ] | |
| 169 | +} | |
| 170 | +``` | |
| 171 | + | |
| 75 | 172 | ## Development |
| 76 | 173 | |
| 77 | 174 | After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. |
| ... | ... | @@ -80,6 +177,8 @@ To install this gem onto your local machine, run `bundle exec rake install`. To |
| 80 | 177 | |
| 81 | 178 | ## Contributing |
| 82 | 179 | |
| 180 | +Run `bundle exec rake` and ensure everything looks good. | |
| 181 | + | |
| 83 | 182 | Bug reports and pull requests are welcome on GitHub at https://github.com/ike/syspro-ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct. |
| 84 | 183 | |
| 85 | 184 | ## License |
| ... | ... | @@ -88,4 +187,4 @@ The gem is available as open source under the terms of the [MIT License](https:/ |
| 88 | 187 | |
| 89 | 188 | ## Code of Conduct |
| 90 | 189 | |
| 91 | -Everyone interacting in the Syspro projectโs codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/ike/syspro-ruby/blob/master/CODE_OF_CONDUCT.md). | |
| 190 | +Everyone interacting in the Syspro projectโs codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/wildland/code-of-conduct). | ... | ... |
Rakefile
| 1 | -require "bundler/gem_tasks" | |
| 2 | -require "rake/testtask" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'bundler/gem_tasks' | |
| 4 | +require 'rake/testtask' | |
| 5 | +require 'rubocop/rake_task' | |
| 3 | 6 | |
| 4 | 7 | Rake::TestTask.new(:test) do |t| |
| 5 | - t.libs << "test" | |
| 6 | - t.libs << "lib" | |
| 7 | - t.test_files = FileList["test/**/*_test.rb"] | |
| 8 | + t.libs << 'test' | |
| 9 | + t.libs << 'lib' | |
| 10 | + t.test_files = FileList['test/**/*_test.rb'] | |
| 8 | 11 | end |
| 9 | 12 | |
| 10 | -task :default => :test | |
| 13 | +task default: %i[test rubocop] | |
| 14 | + | |
| 15 | +RuboCop::RakeTask.new(:rubocop) do |t| | |
| 16 | + t.options = ['--display-cop-names'] | |
| 17 | +end | ... | ... |
bin/console
lib/syspro.rb
| 1 | -require "cgi" | |
| 2 | -require "faraday" | |
| 3 | -require "json" | |
| 4 | -require "logger" | |
| 5 | -require "openssl" | |
| 6 | - | |
| 7 | -require "syspro/api_resource" | |
| 8 | -require "syspro/errors" | |
| 9 | -require "syspro/get_logon_profile" | |
| 10 | -require "syspro/get_version" | |
| 11 | -require "syspro/logoff" | |
| 12 | -require "syspro/logon" | |
| 13 | -require "syspro/syspro_client" | |
| 14 | -require "syspro/singleton_api_resource" | |
| 15 | -require "syspro/syspro_object" | |
| 16 | -require "syspro/syspro_response" | |
| 17 | -require "syspro/util" | |
| 18 | -require "syspro/version" | |
| 19 | - | |
| 20 | -require "syspro/api_operations/request" | |
| 21 | - | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'cgi' | |
| 4 | +require 'faraday' | |
| 5 | +require 'json' | |
| 6 | +require 'logger' | |
| 7 | +require 'openssl' | |
| 8 | + | |
| 9 | +require 'syspro/api_resource' | |
| 10 | +require 'syspro/errors' | |
| 11 | +require 'syspro/get_logon_profile' | |
| 12 | +require 'syspro/get_version' | |
| 13 | +require 'syspro/logoff' | |
| 14 | +require 'syspro/logon' | |
| 15 | +require 'syspro/syspro_client' | |
| 16 | +require 'syspro/singleton_api_resource' | |
| 17 | +require 'syspro/syspro_object' | |
| 18 | +require 'syspro/syspro_response' | |
| 19 | +require 'syspro/util' | |
| 20 | +require 'syspro/version' | |
| 21 | + | |
| 22 | +require 'syspro/api_operations/request' | |
| 23 | +require 'syspro/api_operations/query' | |
| 24 | + | |
| 25 | +require 'syspro/business_objects/combrw' | |
| 26 | +require 'syspro/business_objects/comfch' | |
| 27 | +require 'syspro/business_objects/comfnd' | |
| 28 | + | |
| 29 | +require 'syspro/business_objects/parsers/combrw_parser' | |
| 30 | +require 'syspro/business_objects/parsers/comfch_parser' | |
| 31 | +require 'syspro/business_objects/parsers/comfnd_parser' | |
| 32 | + | |
| 33 | +# Main Module | |
| 22 | 34 | module Syspro |
| 23 | - @api_base = "http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest" | |
| 35 | + @api_base = 'http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest' | |
| 24 | 36 | |
| 25 | 37 | @open_timeout = 30 |
| 26 | 38 | @read_timeout = 80 |
| ... | ... | @@ -60,14 +72,13 @@ module Syspro |
| 60 | 72 | |
| 61 | 73 | def self.log_level=(val) |
| 62 | 74 | # Backwards compatibility for values that we briefly allowed |
| 63 | - if val == "debug" | |
| 64 | - val = LEVEL_DEBUG | |
| 65 | - elsif val == "info" | |
| 66 | - val = LEVEL_INFO | |
| 67 | - end | |
| 68 | - | |
| 75 | + val = LEVEL_DEBUG if val == 'debug' | |
| 76 | + val = LEVEL_INFO if val == 'info' | |
| 69 | 77 | if !val.nil? && ![LEVEL_DEBUG, LEVEL_ERROR, LEVEL_INFO].include?(val) |
| 70 | - raise ArgumentError, "log_level should only be set to `nil`, `debug` or `info`" | |
| 78 | + raise( | |
| 79 | + ArgumentError, | |
| 80 | + 'log_level should only be set to `nil`, `debug` or `info`' | |
| 81 | + ) | |
| 71 | 82 | end |
| 72 | 83 | @log_level = val |
| 73 | 84 | end |
| ... | ... | @@ -95,5 +106,5 @@ module Syspro |
| 95 | 106 | @max_network_retries = val.to_i |
| 96 | 107 | end |
| 97 | 108 | |
| 98 | - Syspro.log_level = ENV["SYSPRO_LOG"] unless ENV["SYSPRO_LOG"].nil? | |
| 109 | + Syspro.log_level = ENV['SYSPRO_LOG'] unless ENV['SYSPRO_LOG'].nil? | |
| 99 | 110 | end | ... | ... |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +module Syspro | |
| 4 | + module ApiOperations | |
| 5 | + module Query | |
| 6 | + module ClassMethods | |
| 7 | + def browse(params) | |
| 8 | + request(:get, '/Query/Browse', params) | |
| 9 | + end | |
| 10 | + | |
| 11 | + def fetch(params) | |
| 12 | + request(:get, '/Query/Fetch', params) | |
| 13 | + end | |
| 14 | + | |
| 15 | + def query(params) | |
| 16 | + request(:get, '/Query/Query', params) | |
| 17 | + end | |
| 18 | + | |
| 19 | + def find; end | |
| 20 | + | |
| 21 | + private | |
| 22 | + | |
| 23 | + def warn_on_opts_in_params(params) | |
| 24 | + Util::OPTS_USER_SPECIFIED.each do |opt| | |
| 25 | + if params.key?(opt) | |
| 26 | + warn("WARNING: #{opt} should be in opts instead of params.") | |
| 27 | + end | |
| 28 | + end | |
| 29 | + end | |
| 30 | + end # ClassMethods | |
| 31 | + | |
| 32 | + def self.included(base) | |
| 33 | + base.extend(ClassMethods) | |
| 34 | + end | |
| 35 | + | |
| 36 | + protected | |
| 37 | + | |
| 38 | + def request(method, url, params = {}, opts = {}) | |
| 39 | + opts = @opts.merge(Util.normalize_opts(opts)) | |
| 40 | + Request.request(method, url, params, opts) | |
| 41 | + end | |
| 42 | + end | |
| 43 | + end | |
| 44 | +end | ... | ... |
lib/syspro/api_operations/request.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | 4 | module ApiOperations |
| 3 | 5 | module Request |
| ... | ... | @@ -28,7 +30,7 @@ module Syspro |
| 28 | 30 | def warn_on_opts_in_params(params) |
| 29 | 31 | Util::OPTS_USER_SPECIFIED.each do |opt| |
| 30 | 32 | if params.key?(opt) |
| 31 | - $stderr.puts("WARNING: #{opt} should be in opts instead of params.") | |
| 33 | + warn("WARNING: #{opt} should be in opts instead of params.") | |
| 32 | 34 | end |
| 33 | 35 | end |
| 34 | 36 | end |
| ... | ... | @@ -37,14 +39,6 @@ module Syspro |
| 37 | 39 | def self.included(base) |
| 38 | 40 | base.extend(ClassMethods) |
| 39 | 41 | end |
| 40 | - | |
| 41 | - protected | |
| 42 | - | |
| 43 | - def request(method, url, params = {}, opts = {}) | |
| 44 | - opts = @opts.merge(Util.normalize_opts(opts)) | |
| 45 | - self.class.request(method, url, params, opts) | |
| 46 | - end | |
| 47 | 42 | end |
| 48 | 43 | end |
| 49 | 44 | end |
| 50 | - | ... | ... |
lib/syspro/api_resource.rb
| 1 | -require "syspro/syspro_object" | |
| 2 | -require "syspro/api_operations/request" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'syspro/syspro_object' | |
| 4 | +require 'syspro/api_operations/request' | |
| 3 | 5 | |
| 4 | 6 | module Syspro |
| 5 | 7 | class ApiResource < SysproObject |
| 6 | 8 | include Syspro::ApiOperations::Request |
| 7 | 9 | |
| 8 | 10 | def self.class_name |
| 9 | - name.split("::")[-1] | |
| 11 | + name.split('::')[-1] | |
| 10 | 12 | end |
| 11 | 13 | |
| 12 | 14 | def self.resource_url |
| 13 | 15 | if self == ApiResource |
| 14 | - raise NotImplementedError, "APIResource is an abstract class. You should perform actions on its subclasses (Charge, Customer, etc.)" | |
| 16 | + raise NotImplementedError, 'APIResource is an abstract class. You should perform actions on its subclasses (Charge, Customer, etc.)' | |
| 15 | 17 | end |
| 16 | 18 | "/#{CGI.escape(class_name.downcase)}" |
| 17 | 19 | end | ... | ... |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'syspro/business_objects/parsers/combrw_parser' | |
| 4 | +require 'erb' | |
| 5 | + | |
| 6 | +module Syspro | |
| 7 | + module BusinessObjects | |
| 8 | + class ComBrw < ApiResource | |
| 9 | + include Syspro::ApiOperations::Query | |
| 10 | + include Syspro::BusinessObjects::Parsers | |
| 11 | + | |
| 12 | + attr_accessor :browse_name, :start_condition, :return_rows, :filters, | |
| 13 | + :table_name, :title, :columns | |
| 14 | + | |
| 15 | + def call(user_id) | |
| 16 | + xml_in = template.result(binding) | |
| 17 | + params = { 'UserId' => user_id, 'XmlIn' => xml_in } | |
| 18 | + resp = ComBrw.browse(params) | |
| 19 | + parse_response(resp) | |
| 20 | + end | |
| 21 | + | |
| 22 | + def template | |
| 23 | + ERB.new( | |
| 24 | + File.read( | |
| 25 | + File.expand_path('schemas/combrw.xml.erb', File.dirname(__FILE__)) | |
| 26 | + ), | |
| 27 | + nil, | |
| 28 | + '%' | |
| 29 | + ) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def parse_response(resp) | |
| 33 | + handle_errors(resp) | |
| 34 | + parser = ComBrwParser.new(resp[0].data) | |
| 35 | + parser.parse | |
| 36 | + end | |
| 37 | + | |
| 38 | + def handle_errors(resp) | |
| 39 | + body = resp[0].http_body | |
| 40 | + raise SysproError, body if body =~ /^(ERROR)/ | |
| 41 | + end | |
| 42 | + end | |
| 43 | + end | |
| 44 | +end | ... | ... |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'syspro/business_objects/parsers/comfch_parser' | |
| 4 | +require 'erb' | |
| 5 | + | |
| 6 | +module Syspro | |
| 7 | + module BusinessObjects | |
| 8 | + class ComFch < ApiResource | |
| 9 | + include Syspro::ApiOperations::Query | |
| 10 | + include Syspro::BusinessObjects::Parsers | |
| 11 | + | |
| 12 | + attr_accessor :table_name, :key, :optional_keys, :full_key_provided, | |
| 13 | + :default_type, :espresso_fetch | |
| 14 | + | |
| 15 | + def call(user_id) | |
| 16 | + xml_in = template.result(binding) | |
| 17 | + params = { 'UserId' => user_id, 'XmlIn' => xml_in } | |
| 18 | + resp = ComFch.fetch(params) | |
| 19 | + parse_response(resp) | |
| 20 | + end | |
| 21 | + | |
| 22 | + def template | |
| 23 | + ERB.new( | |
| 24 | + File.read( | |
| 25 | + File.expand_path('schemas/comfch.xml.erb', File.dirname(__FILE__)) | |
| 26 | + ), | |
| 27 | + nil, | |
| 28 | + '%' | |
| 29 | + ) | |
| 30 | + end | |
| 31 | + | |
| 32 | + def parse_response(resp) | |
| 33 | + handle_errors(resp) | |
| 34 | + parser = ComFchParser.new(resp[0].data) | |
| 35 | + parser.parse | |
| 36 | + end | |
| 37 | + | |
| 38 | + def handle_errors(resp) | |
| 39 | + body = resp[0].http_body | |
| 40 | + raise SysproError, body if body =~ /^(ERROR)/ | |
| 41 | + end | |
| 42 | + end | |
| 43 | + end | |
| 44 | +end | ... | ... |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'syspro/business_objects/parsers/comfnd_parser' | |
| 4 | +require 'erb' | |
| 5 | + | |
| 6 | +module Syspro | |
| 7 | + module BusinessObjects | |
| 8 | + class ComFnd < ApiResource | |
| 9 | + include Syspro::ApiOperations::Query | |
| 10 | + include Syspro::BusinessObjects::Parsers | |
| 11 | + | |
| 12 | + attr_accessor :table_name, :return_rows, :columns, :expressions, | |
| 13 | + :order_by | |
| 14 | + | |
| 15 | + def call(user_id) | |
| 16 | + xml_in = template.result(binding) | |
| 17 | + business_object = 'COMFND' | |
| 18 | + params = { 'UserId' => user_id, 'BusinessObject' => business_object, 'XmlIn' => xml_in } | |
| 19 | + resp = ComFnd.query(params) | |
| 20 | + parse_response(resp) | |
| 21 | + end | |
| 22 | + | |
| 23 | + def template | |
| 24 | + ERB.new File.read(File.expand_path('schemas/comfnd.xml.erb', File.dirname(__FILE__))), nil, '%' | |
| 25 | + end | |
| 26 | + | |
| 27 | + def parse_response(resp) | |
| 28 | + handle_errors(resp) | |
| 29 | + parser = ComFndParser.new(resp[0].data) | |
| 30 | + parser.parse | |
| 31 | + end | |
| 32 | + | |
| 33 | + def handle_errors(resp) | |
| 34 | + body = resp[0].http_body | |
| 35 | + raise SysproError, body if body =~ /^(ERROR)/ | |
| 36 | + end | |
| 37 | + end | |
| 38 | + end | |
| 39 | +end | ... | ... |
lib/syspro/business_objects/parsers/combrw_parser.rb
0 โ 100644
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +module Syspro | |
| 4 | + module BusinessObjects | |
| 5 | + module Parsers | |
| 6 | + class ComBrwParser | |
| 7 | + attr_reader :doc | |
| 8 | + | |
| 9 | + def initialize(doc) | |
| 10 | + @doc = doc | |
| 11 | + end | |
| 12 | + | |
| 13 | + def parse | |
| 14 | + next_prev_key = doc.first_element_child.xpath('NextPrevKey') | |
| 15 | + next_prev_key_obj = next_prev_key.children.map do |el| | |
| 16 | + next if el.name == 'text' | |
| 17 | + { | |
| 18 | + name: el.name, | |
| 19 | + text: el.text | |
| 20 | + } | |
| 21 | + end.compact | |
| 22 | + | |
| 23 | + header_details = doc.first_element_child.xpath('HeaderDetails') | |
| 24 | + header_details_obj = header_details.children.map do |el| | |
| 25 | + next if el.name == 'text' | |
| 26 | + { | |
| 27 | + name: el.name, | |
| 28 | + text: el.text | |
| 29 | + } | |
| 30 | + end.compact | |
| 31 | + | |
| 32 | + rows = doc.first_element_child.xpath('Row') | |
| 33 | + rows_obj = rows.flat_map do |el| | |
| 34 | + el.elements.map do |inner| | |
| 35 | + { | |
| 36 | + name: inner.name, | |
| 37 | + value: inner.xpath('Value').text, | |
| 38 | + data_type: inner.xpath('DataType').text | |
| 39 | + } | |
| 40 | + end | |
| 41 | + end.compact | |
| 42 | + | |
| 43 | + BrowseObject.new( | |
| 44 | + doc.first_element_child.xpath('Title').text, | |
| 45 | + rows_obj, | |
| 46 | + next_prev_key_obj, | |
| 47 | + header_details_obj | |
| 48 | + ) | |
| 49 | + end | |
| 50 | + | |
| 51 | + BrowseObject = Struct.new(:title, :rows, :next_prev_key, :header_details) | |
| 52 | + end | |
| 53 | + end | |
| 54 | + end | |
| 55 | +end | ... | ... |
lib/syspro/business_objects/parsers/comfch_parser.rb
0 โ 100644
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +module Syspro | |
| 4 | + module BusinessObjects | |
| 5 | + module Parsers | |
| 6 | + class ComFchParser | |
| 7 | + attr_reader :doc | |
| 8 | + | |
| 9 | + def initialize(doc) | |
| 10 | + @doc = doc | |
| 11 | + end | |
| 12 | + | |
| 13 | + def parse | |
| 14 | + table_name = doc.first_element_child.name | |
| 15 | + columns = doc.first_element_child.elements | |
| 16 | + columns_obj = columns.map do |el| | |
| 17 | + { name: el.name, value: el.children.text } | |
| 18 | + end.compact | |
| 19 | + | |
| 20 | + FetchObject.new( | |
| 21 | + table_name, | |
| 22 | + columns_obj | |
| 23 | + ) | |
| 24 | + end | |
| 25 | + | |
| 26 | + FetchObject = Struct.new(:table_name, :columns) | |
| 27 | + end | |
| 28 | + end | |
| 29 | + end | |
| 30 | +end | ... | ... |
lib/syspro/business_objects/parsers/comfnd_parser.rb
0 โ 100644
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +module Syspro | |
| 4 | + module BusinessObjects | |
| 5 | + module Parsers | |
| 6 | + class ComFndParser | |
| 7 | + attr_reader :doc | |
| 8 | + | |
| 9 | + def initialize(doc) | |
| 10 | + @doc = doc | |
| 11 | + end | |
| 12 | + | |
| 13 | + def parse | |
| 14 | + header_details = doc.first_element_child.xpath('HeaderDetails') | |
| 15 | + header_details_obj = header_details.children.map do |el| | |
| 16 | + next if el.name == 'text' | |
| 17 | + { | |
| 18 | + name: el.name, | |
| 19 | + text: el.text | |
| 20 | + } | |
| 21 | + end.compact | |
| 22 | + | |
| 23 | + rows = doc.first_element_child.xpath('Row') | |
| 24 | + rows_obj = rows.flat_map do |el| | |
| 25 | + el.elements.map do |inner| | |
| 26 | + { | |
| 27 | + name: inner.name, | |
| 28 | + value: inner.children.text | |
| 29 | + } | |
| 30 | + end | |
| 31 | + end.compact | |
| 32 | + | |
| 33 | + QueryObject.new( | |
| 34 | + header_details_obj, | |
| 35 | + rows_obj, | |
| 36 | + doc.first_element_child.xpath('//RowsReturned').text.to_i | |
| 37 | + ) | |
| 38 | + end | |
| 39 | + | |
| 40 | + QueryObject = Struct.new(:header_details, :rows, :row_count) | |
| 41 | + end | |
| 42 | + end | |
| 43 | + end | |
| 44 | +end | ... | ... |
lib/syspro/business_objects/schemas/combrw.xml.erb
0 โ 100644
| 1 | +<?xml version="1.0" encoding="Windows-1252"?> | |
| 2 | +<Browse xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="COMBRW.XSD"> | |
| 3 | + <BrowseName><%= @browse_name %></BrowseName> | |
| 4 | + <StartAtKey/> | |
| 5 | + <StartCondition><%= @start_condition %></StartCondition> | |
| 6 | + <ReturnRows><%= @return_rows %></ReturnRows> | |
| 7 | + <% for @filter in @filters %> | |
| 8 | + <Filter> | |
| 9 | + <ColumnFilterName><%= @filter[:name] %></ColumnFilterName> | |
| 10 | + <ColumnFilterValue><%= @filter[:value] %></ColumnFilterValue> | |
| 11 | + </Filter> | |
| 12 | + <% end %> | |
| 13 | + <BrowseDetails> | |
| 14 | + <TableName><%= @table_name %></TableName> | |
| 15 | + <Title><%= @title %></Title> | |
| 16 | + <% for @column in @columns %> | |
| 17 | + <Column> | |
| 18 | + <% unless @column[:name].nil? %><ColumnName><%= @column[:name] %></ColumnName><% end %> | |
| 19 | + <% unless @column[:description].nil? %><ColumnDescription><%= @column[:description] %></ColumnDescription><% end %> | |
| 20 | + <% unless @column[:key].nil? %><ColumnKey><%= @column[:key] %></ColumnKey><% end %> | |
| 21 | + </Column> | |
| 22 | + <% end %> | |
| 23 | + </BrowseDetails> | |
| 24 | +</Browse> | |
| 25 | + | ... | ... |
lib/syspro/business_objects/schemas/comfch.xml.erb
0 โ 100644
| 1 | +<?xml version="1.0" encoding="Windows-1252"?> | |
| 2 | +<Fetch xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="COMFCH.XSD"> | |
| 3 | + <TableName><%= @table_name %></TableName> | |
| 4 | + <Key><%= @key %></Key> | |
| 5 | + <% unless @optional_keys.empty? %> | |
| 6 | + <% @optional_keys.each_with_index do |key, i| %> | |
| 7 | + <<%= "OptionalKey#{ i + 1 }" %>><%= key[:value] %></<%= "OptionalKey#{ i + 1 }" %>> | |
| 8 | + <% end %> | |
| 9 | + <% end %> | |
| 10 | + <FullKeyProvided><%= @full_key_provided ? "N" : "Y" %></FullKeyProvided> | |
| 11 | + <DefaultType><%= @default_type %></DefaultType> | |
| 12 | + <EspressoFetch><%= @espresso_fetch ? "N" : "Y" %></EspressoFetch> | |
| 13 | +</Fetch> | |
| 14 | + | ... | ... |
lib/syspro/business_objects/schemas/comfnd.xml.erb
0 โ 100644
| 1 | +<?xml version="1.0" encoding="Windows-1252"?> | |
| 2 | +<Query xmlns:xsd="http://www.w3.org/2001/XMLSchema-instance" xsd:noNamespaceSchemaLocation="COMFND.XSD"> | |
| 3 | + <TableName><%= @table_name %></TableName> | |
| 4 | + <ReturnRows><%= @return_rows %></ReturnRows> | |
| 5 | + <Columns> | |
| 6 | + <% for column in @columns %> | |
| 7 | + <Column><%= column[:name] %></Column> | |
| 8 | + <% end %> | |
| 9 | + </Columns> | |
| 10 | + <% unless @expressions.empty? %> | |
| 11 | + <Where> | |
| 12 | + <% for expression in @expressions %> | |
| 13 | + <Expression> | |
| 14 | + <OpenBracket>(</OpenBracket> | |
| 15 | + <% unless expression[:andor].nil? %> | |
| 16 | + <AndOr><%= expression[:andor] %></AndOr> | |
| 17 | + <% end %> | |
| 18 | + <Column><%= expression[:column] %></Column> | |
| 19 | + <Condition><%= expression[:condition] %></Condition> | |
| 20 | + <Value><%= expression[:value] %></Value> | |
| 21 | + <CloseBracket>)</CloseBracket> | |
| 22 | + </Expression> | |
| 23 | + <% end %> | |
| 24 | + </Where> | |
| 25 | + <% end %> | |
| 26 | + <OrderBy> | |
| 27 | + <Column><%= @order_by %></Column> | |
| 28 | + </OrderBy> | |
| 29 | +</Query> | ... | ... |
lib/syspro/errors.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | 4 | class SysproError < StandardError |
| 3 | 5 | attr_reader :message, :response, :code, :http_body, :http_headers, |
| ... | ... | @@ -16,8 +18,8 @@ module Syspro |
| 16 | 18 | end |
| 17 | 19 | |
| 18 | 20 | def to_s |
| 19 | - status_string = @http_status.nil? ? "" : "(Status #{@http_status}) " | |
| 20 | - id_string = @request_id.nil? ? "" : "(Request #{@request_id}) " | |
| 21 | + status_string = @http_status.nil? ? '' : "(Status #{@http_status}) " | |
| 22 | + id_string = @request_id.nil? ? '' : "(Request #{@request_id}) " | |
| 21 | 23 | "#{status_string}#{id_string}#{@message}" |
| 22 | 24 | end |
| 23 | 25 | end |
| ... | ... | @@ -30,5 +32,4 @@ module Syspro |
| 30 | 32 | |
| 31 | 33 | class ApiError < SysproError |
| 32 | 34 | end |
| 33 | - | |
| 34 | 35 | end | ... | ... |
lib/syspro/get_logon_profile.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | 4 | class GetLogonProfile < ApiResource |
| 3 | 5 | def self.get_logon_profile(user_id) |
| 4 | - params = { "UserId" => user_id } | |
| 5 | - resp = self.request(:get, resource_url, params) | |
| 6 | + params = { 'UserId' => user_id } | |
| 7 | + resp = request(:get, resource_url, params) | |
| 6 | 8 | parse_response(resp[0]) |
| 7 | 9 | end |
| 8 | 10 | |
| 9 | 11 | def resource_url |
| 10 | - "/GetLogonProfile" | |
| 12 | + '/GetLogonProfile' | |
| 11 | 13 | end |
| 12 | 14 | |
| 13 | - def self.parse_response(resp) | |
| 15 | + def self.parse_response(resp) # rubocop:disable Metrics/MethodLength | |
| 14 | 16 | doc = resp.data |
| 15 | 17 | |
| 16 | - UserProfile.new( | |
| 17 | - doc.xpath("//CompanyName").text, | |
| 18 | - doc.xpath("//OperatorCode").text, | |
| 19 | - doc.xpath("//OperatorGroup").text, | |
| 20 | - doc.xpath("//OperatorEmailAddress").text, | |
| 21 | - doc.xpath("//OperatorLocation").text, | |
| 22 | - doc.xpath("//OperatorLanguageCode").text, | |
| 23 | - doc.xpath("//SystemLanguage").text, | |
| 24 | - doc.xpath("//AccountingDate").text, | |
| 25 | - doc.xpath("//CompanyDate").text, | |
| 26 | - doc.xpath("//DefaultArBranch").text, | |
| 27 | - doc.xpath("//DefaultApBranch").text, | |
| 28 | - doc.xpath("//DefaultBank").text, | |
| 29 | - doc.xpath("//DefaultWarehouse").text, | |
| 30 | - doc.xpath("//DefaultCustomer").text, | |
| 31 | - doc.xpath("//SystemSiteId").text, | |
| 32 | - doc.xpath("//SystemNationalityCode").text, | |
| 33 | - doc.xpath("//LocalCurrencyCode").text, | |
| 34 | - doc.xpath("//CurrencyDescription").text, | |
| 35 | - doc.xpath("//DefaultRequisitionUser").text, | |
| 36 | - doc.xpath("//XMLToHTMLTransform").text, | |
| 37 | - doc.xpath("//CssStyle").text, | |
| 38 | - doc.xpath("//CssSuffix").text, | |
| 39 | - doc.xpath("//DecimalFormat").text, | |
| 40 | - doc.xpath("//DateFormat").text, | |
| 41 | - doc.xpath("//FunctionalRole").text, | |
| 42 | - doc.xpath("//DatabaseType").text, | |
| 43 | - doc.xpath("//SysproVersion").text, | |
| 44 | - doc.xpath("//EnetVersion").text, | |
| 45 | - doc.xpath("//SysproServerBitWidth").text, | |
| 18 | + OpenStruct.new( | |
| 19 | + company_name: doc.xpath('//CompanyName').text, | |
| 20 | + operator_code: doc.xpath('//OperatorCode').text, | |
| 21 | + operator_code: doc.xpath('//OperatorGroup').text, | |
| 22 | + operator_email_address: doc.xpath('//OperatorEmailAddress').text, | |
| 23 | + operator_location: doc.xpath('//OperatorLocation').text, | |
| 24 | + operator_language_code: doc.xpath('//OperatorLanguageCode').text, | |
| 25 | + system_language: doc.xpath('//SystemLanguage').text, | |
| 26 | + accounting_date: doc.xpath('//AccountingDate').text, | |
| 27 | + company_date: doc.xpath('//CompanyDate').text, | |
| 28 | + default_ar_branch: doc.xpath('//DefaultArBranch').text, | |
| 29 | + default_ap_branch: doc.xpath('//DefaultApBranch').text, | |
| 30 | + default_bank: doc.xpath('//DefaultBank').text, | |
| 31 | + default_warehouse: doc.xpath('//DefaultWarehouse').text, | |
| 32 | + default_customer: doc.xpath('//DefaultCustomer').text, | |
| 33 | + system_site_id: doc.xpath('//SystemSiteId').text, | |
| 34 | + system_nationality_code: doc.xpath('//SystemNationalityCode').text, | |
| 35 | + local_currency_code: doc.xpath('//LocalCurrencyCode').text, | |
| 36 | + currency_description: doc.xpath('//CurrencyDescription').text, | |
| 37 | + default_requisition_user: doc.xpath('//DefaultRequisitionUser').text, | |
| 38 | + xml_to_html_transform: doc.xpath('//XMLToHTMLTransform').text, | |
| 39 | + css_style: doc.xpath('//CssStyle').text, | |
| 40 | + css_suffix: doc.xpath('//CssSuffix').text, | |
| 41 | + decimal_format: doc.xpath('//DecimalFormat').text, | |
| 42 | + date_format: doc.xpath('//DateFormat').text, | |
| 43 | + functional_role: doc.xpath('//FunctionalRole').text, | |
| 44 | + database_type: doc.xpath('//DatabaseType').text, | |
| 45 | + syspro_version: doc.xpath('//SysproVersion').text, | |
| 46 | + enet_version: doc.xpath('//EnetVersion').text, | |
| 47 | + syspro_server_bit_width: doc.xpath('//SysproServerBitWidth').text | |
| 46 | 48 | ) |
| 47 | 49 | end |
| 48 | 50 | private_class_method :parse_response |
| 49 | - | |
| 50 | - UserProfile = Struct.new(:company_name, :operator_code, :operator_group, :operator_email_address, | |
| 51 | - :operator_location, :operator_language_code, :system_language, :accounting_date, | |
| 52 | - :company_date, :default_ar_branch, :default_ap_branch, :default_bank, :default_warehouse, | |
| 53 | - :default_customer, :system_site_id, :system_nationality_code, :local_currency_code, | |
| 54 | - :currency_description, :default_requisition_user, :xml_to_html_transform, :css_style, | |
| 55 | - :css_suffix, :decimal_format, :date_format, :functional_role, :database_type, :syspro_version, | |
| 56 | - :enet_version, :syspro_server_bit_width) | |
| 57 | 51 | end |
| 58 | 52 | end |
| 59 | - | ... | ... |
lib/syspro/get_version.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | 4 | class GetVersion < ApiResource |
| 3 | 5 | def self.get_version |
| 4 | - resp = self.request(:get, resource_url) | |
| 6 | + resp = request(:get, resource_url) | |
| 5 | 7 | VersionObject.new(resp[0].http_body) |
| 6 | 8 | end |
| 7 | 9 | |
| 8 | 10 | def resource_url |
| 9 | - "/GetVersion" | |
| 11 | + '/GetVersion' | |
| 10 | 12 | end |
| 11 | 13 | |
| 12 | 14 | VersionObject = Struct.new(:version) |
| 13 | 15 | end |
| 14 | 16 | end |
| 15 | - | ... | ... |
lib/syspro/logoff.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | 4 | class Logoff < ApiResource |
| 3 | 5 | def self.logoff(user_id) |
| 4 | - params = { "UserId" => user_id } | |
| 5 | - resp = self.request(:get, resource_url, params) | |
| 6 | + params = { 'UserId' => user_id } | |
| 7 | + resp = request(:get, resource_url, params) | |
| 6 | 8 | |
| 7 | - if resp[0].http_body == "0" | |
| 9 | + if resp[0].http_body == '0' | |
| 8 | 10 | true |
| 9 | 11 | else |
| 10 | 12 | resp[0].http_body |
| ... | ... | @@ -12,7 +14,7 @@ module Syspro |
| 12 | 14 | end |
| 13 | 15 | |
| 14 | 16 | def resource_url |
| 15 | - "/Logoff" | |
| 17 | + '/Logoff' | |
| 16 | 18 | end |
| 17 | 19 | end |
| 18 | 20 | end | ... | ... |
lib/syspro/logon.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | 4 | class Logon < ApiResource |
| 3 | 5 | def self.logon(username, password, company_id, company_password = nil) |
| 4 | 6 | params = { |
| 5 | - "Operator" => username, | |
| 6 | - "OperatorPassword" => password, | |
| 7 | - "CompanyId" => company_id, | |
| 8 | - "CompanyPassword" => company_password | |
| 7 | + 'Operator' => username, | |
| 8 | + 'OperatorPassword' => password, | |
| 9 | + 'CompanyId' => company_id, | |
| 10 | + 'CompanyPassword' => company_password | |
| 9 | 11 | } |
| 10 | - resp = self.request(:get, resource_url, params) | |
| 12 | + resp = request(:get, resource_url, params) | |
| 11 | 13 | UserIdObject.new(resp[0].http_body) |
| 12 | 14 | end |
| 13 | 15 | |
| 14 | 16 | def resource_url |
| 15 | - "/Logon" | |
| 17 | + '/Logon' | |
| 16 | 18 | end |
| 17 | 19 | |
| 18 | 20 | UserIdObject = Struct.new(:guid) |
| 19 | 21 | end |
| 20 | 22 | end |
| 21 | - | ... | ... |
lib/syspro/singleton_api_resource.rb
| 1 | -require_relative "api_resource" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require_relative 'api_resource' | |
| 2 | 4 | |
| 3 | 5 | module Syspro |
| 4 | 6 | class SingletonAPIResource < ApiResource |
| 5 | 7 | def self.resource_url |
| 6 | 8 | if self == SingletonAPIResource |
| 7 | - raise NotImplementedError, "SingletonAPIResource is an abstract class. You should perform actions on its subclasses (Customer, etc.)" | |
| 9 | + raise( | |
| 10 | + NotImplementedError, | |
| 11 | + 'SingletonAPIResource is an abstract class. You should perform actions on its subclasses (Customer, etc.)' # rubocop:disable Metrics/LineLength | |
| 12 | + ) | |
| 8 | 13 | end |
| 9 | 14 | "/#{CGI.escape(class_name.downcase)}" |
| 10 | 15 | end | ... | ... |
lib/syspro/syspro_client.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | - class SysproClient | |
| 4 | + # This class is the main syspro client | |
| 5 | + class SysproClient # rubocop:disable Metrics/ClassLength | |
| 3 | 6 | attr_accessor :conn, :api_base |
| 4 | 7 | |
| 5 | 8 | @verify_ssl_warned = false |
| ... | ... | @@ -13,7 +16,7 @@ module Syspro |
| 13 | 16 | Syspro::Logon.logon(username, password, company_id, company_password) |
| 14 | 17 | end |
| 15 | 18 | |
| 16 | - def get_syspro_version | |
| 19 | + def get_syspro_version # rubocop:disable Naming/AccessorMethodName | |
| 17 | 20 | Syspro::GetVersion.get_version |
| 18 | 21 | end |
| 19 | 22 | |
| ... | ... | @@ -22,13 +25,13 @@ module Syspro |
| 22 | 25 | end |
| 23 | 26 | |
| 24 | 27 | def self.default_client |
| 25 | - Thread.current[:syspro_client_default_client] ||= SysproClient.new(default_conn) | |
| 28 | + Thread.current[:syspro_client_default_client] ||= SysproClient.new(default_conn) # rubocop:disable Metrics/LineLength | |
| 26 | 29 | end |
| 27 | 30 | |
| 28 | 31 | # A default Faraday connection to be used when one isn't configured. This |
| 29 | 32 | # object should never be mutated, and instead instantiating your own |
| 30 | 33 | # connection and wrapping it in a SysproClient object should be preferred. |
| 31 | - def self.default_conn | |
| 34 | + def self.default_conn # rubocop:disable Metrics/MethodLength | |
| 32 | 35 | # We're going to keep connections around so that we can take advantage |
| 33 | 36 | # of connection re-use, so make sure that we have a separate connection |
| 34 | 37 | # object per thread. |
| ... | ... | @@ -40,20 +43,21 @@ module Syspro |
| 40 | 43 | c.adapter Faraday.default_adapter |
| 41 | 44 | end |
| 42 | 45 | |
| 43 | - # For now, we're not verifying SSL certificates. The warning will appear. | |
| 44 | - #if Syspro.verify_ssl_certs | |
| 45 | - #conn.ssl.verify = true | |
| 46 | - #conn.ssl.cert_store = Syspro.ca_store | |
| 47 | - #else | |
| 46 | + # For now, we're not verifying SSL certificates. | |
| 47 | + # The warning will appear. | |
| 48 | + # if Syspro.verify_ssl_certs | |
| 49 | + # conn.ssl.verify = true | |
| 50 | + # conn.ssl.cert_store = Syspro.ca_store | |
| 51 | + # else | |
| 48 | 52 | conn.ssl.verify = false |
| 49 | 53 | |
| 50 | 54 | unless @verify_ssl_warned |
| 51 | 55 | @verify_ssl_warned = true |
| 52 | - $stderr.puts("WARNING: Running without SSL cert verification. " \ | |
| 53 | - "You should never do this in production. " \ | |
| 56 | + warn('WARNING: Running without SSL cert verification. ' \ | |
| 57 | + 'You should never do this in production. ' \ | |
| 54 | 58 | "Execute 'Syspro.verify_ssl_certs = true' to enable verification.") |
| 55 | 59 | end |
| 56 | - #end | |
| 60 | + # end | |
| 57 | 61 | |
| 58 | 62 | conn |
| 59 | 63 | end |
| ... | ... | @@ -77,9 +81,9 @@ module Syspro |
| 77 | 81 | end |
| 78 | 82 | end |
| 79 | 83 | |
| 80 | - def execute_request(method, path, user_id: nil, api_base: nil, headers: {}, params: {}) | |
| 84 | + def execute_request(method, path, user_id: nil, api_base: nil, headers: {}, params: {}) # rubocop:disable Metrics/LineLength, Metrics/MethodLength | |
| 81 | 85 | api_base ||= Syspro.api_base |
| 82 | - user_id ||= "" | |
| 86 | + user_id ||= '' | |
| 83 | 87 | |
| 84 | 88 | params = Util.objects_to_ids(params) |
| 85 | 89 | url = api_url(path, api_base) |
| ... | ... | @@ -91,7 +95,7 @@ module Syspro |
| 91 | 95 | when :get, :head, :delete |
| 92 | 96 | query_params = params |
| 93 | 97 | else |
| 94 | - body = if headers[:content_type] && headers[:content_type] == "multipart/form-data" | |
| 98 | + body = if headers[:content_type] && headers[:content_type] == 'multipart/form-data' # rubocop:disable Metrics/LineLength | |
| 95 | 99 | params |
| 96 | 100 | else |
| 97 | 101 | Util.encode_parameters(params) |
| ... | ... | @@ -108,7 +112,7 @@ module Syspro |
| 108 | 112 | context.method = method |
| 109 | 113 | context.path = path |
| 110 | 114 | context.user_id = user_id |
| 111 | - context.query_params = query_params ? Util.encode_parameters(query_params) : nil | |
| 115 | + context.query_params = query_params ? Util.encode_parameters(query_params) : nil # rubocop:disable Metrics/LineLength | |
| 112 | 116 | |
| 113 | 117 | http_resp = execute_request_with_rescues(api_base, context) do |
| 114 | 118 | conn.run_request(method, url, body, headers) do |req| |
| ... | ... | @@ -135,22 +139,22 @@ module Syspro |
| 135 | 139 | http_status: status, http_body: body) |
| 136 | 140 | end |
| 137 | 141 | |
| 138 | - def api_url(url = "", api_base = nil) | |
| 142 | + def api_url(url = '', api_base = nil) | |
| 139 | 143 | (api_base || Syspro.api_base) + url |
| 140 | 144 | end |
| 141 | 145 | |
| 142 | - def request_headers(method) | |
| 146 | + def request_headers(_method) | |
| 143 | 147 | user_agent = "Syspro/7 RubyBindings/#{Syspro::VERSION}" |
| 144 | 148 | |
| 145 | 149 | headers = { |
| 146 | - "User-Agent" => user_agent, | |
| 147 | - "Content-Type" => "application/x-www-form-urlencoded", | |
| 150 | + 'User-Agent' => user_agent, | |
| 151 | + 'Content-Type' => 'application/x-www-form-urlencoded' | |
| 148 | 152 | } |
| 149 | 153 | |
| 150 | 154 | headers |
| 151 | 155 | end |
| 152 | 156 | |
| 153 | - def execute_request_with_rescues(api_base, context) | |
| 157 | + def execute_request_with_rescues(api_base, context) # rubocop:disable Metrics/LineLength, Metrics/MethodLength | |
| 154 | 158 | num_retries = 0 |
| 155 | 159 | begin |
| 156 | 160 | request_start = Time.now |
| ... | ... | @@ -159,8 +163,8 @@ module Syspro |
| 159 | 163 | log_response(context, request_start, resp.status, resp.body) |
| 160 | 164 | |
| 161 | 165 | # We rescue all exceptions from a request so that we have an easy spot to |
| 162 | - # implement our retry logic across the board. We'll re-raise if it's a type | |
| 163 | - # of exception that we didn't expect to handle. | |
| 166 | + # implement our retry logic across the board. We'll re-raise if it's a | |
| 167 | + # type of exception that we didn't expect to handle. | |
| 164 | 168 | rescue StandardError => e |
| 165 | 169 | if e.respond_to?(:response) && e.response |
| 166 | 170 | log_response(context, request_start, |
| ... | ... | @@ -178,9 +182,9 @@ module Syspro |
| 178 | 182 | case e |
| 179 | 183 | when Faraday::ClientError |
| 180 | 184 | if e.response |
| 181 | - handle_error_response(e.response, error_context) | |
| 185 | + handle_error_response(e.response, context) | |
| 182 | 186 | else |
| 183 | - handle_network_error(e, error_context, num_retries, api_base) | |
| 187 | + handle_network_error(e, context, num_retries, api_base) | |
| 184 | 188 | end |
| 185 | 189 | |
| 186 | 190 | # Only handle errors when we know we can do so, and re-raise otherwise. |
| ... | ... | @@ -193,7 +197,36 @@ module Syspro |
| 193 | 197 | resp |
| 194 | 198 | end |
| 195 | 199 | |
| 196 | - def self.should_retry?(e, num_retries) | |
| 200 | + def handle_network_error(e, context, num_retries, api_base = nil) # rubocop:disable Metrics/LineLength, Metrics/MethodLength, Naming/UncommunicativeMethodParamName | |
| 201 | + Util.log_error('Syspro network error', | |
| 202 | + error_message: e.message, | |
| 203 | + request_id: context.request_id) | |
| 204 | + | |
| 205 | + case e | |
| 206 | + when Faraday::ConnectionFailed | |
| 207 | + message = 'Unexpected error communicating when trying to connect to Syspro.' # rubocop:disable Metrics/LineLength | |
| 208 | + | |
| 209 | + when Faraday::SSLError | |
| 210 | + message = 'Could not establish a secure connection to Syspro.' | |
| 211 | + | |
| 212 | + when Faraday::TimeoutError | |
| 213 | + api_base ||= Syspro.api_base | |
| 214 | + message = "Could not connect to Syspro (#{api_base}). " \ | |
| 215 | + 'Please check your internet connection and try again. ' \ | |
| 216 | + 'If this problem persists, you should check your Syspro service status.' # rubocop:disable Metrics/LineLength | |
| 217 | + | |
| 218 | + else | |
| 219 | + message = 'Unexpected error communicating with Syspro. ' \ | |
| 220 | + 'If this problem persists, talk to your Syspro implementation team.' | |
| 221 | + | |
| 222 | + end | |
| 223 | + | |
| 224 | + message += " Request was retried #{num_retries} times." if num_retries.positive? # rubocop:disable Metrics/LineLength | |
| 225 | + | |
| 226 | + raise ApiConnectionError, message + "\n\n(Network error: #{e.message})" | |
| 227 | + end | |
| 228 | + | |
| 229 | + def self.should_retry?(e, num_retries) # rubocop:disable Metrics/LineLength, Naming/UncommunicativeMethodParamName | |
| 197 | 230 | return false if num_retries >= Syspro.max_network_retries |
| 198 | 231 | |
| 199 | 232 | # Retry on timeout-related problems (either on open or read). |
| ... | ... | @@ -213,20 +246,20 @@ module Syspro |
| 213 | 246 | end |
| 214 | 247 | |
| 215 | 248 | def log_request(context, num_retries) |
| 216 | - Util.log_info("Request to Syspro API", | |
| 249 | + Util.log_info('Request to Syspro API', | |
| 217 | 250 | account: context.account, |
| 218 | 251 | api_version: context.api_version, |
| 219 | 252 | method: context.method, |
| 220 | 253 | num_retries: num_retries, |
| 221 | 254 | path: context.path) |
| 222 | - Util.log_debug("Request details", | |
| 255 | + Util.log_debug('Request details', | |
| 223 | 256 | body: context.body, |
| 224 | 257 | query_params: context.query_params) |
| 225 | 258 | end |
| 226 | 259 | private :log_request |
| 227 | 260 | |
| 228 | - def log_response(context, request_start, status, body) | |
| 229 | - Util.log_info("Response from Syspro API", | |
| 261 | + def log_response(context, request_start, status, body) # rubocop:disable Metrics/LineLength, Metrics/MethodLength | |
| 262 | + Util.log_info('Response from Syspro API', | |
| 230 | 263 | account: context.account, |
| 231 | 264 | api_version: context.api_version, |
| 232 | 265 | elapsed: Time.now - request_start, |
| ... | ... | @@ -234,14 +267,14 @@ module Syspro |
| 234 | 267 | path: context.path, |
| 235 | 268 | request_id: context.request_id, |
| 236 | 269 | status: status) |
| 237 | - Util.log_debug("Response details", | |
| 270 | + Util.log_debug('Response details', | |
| 238 | 271 | body: body, |
| 239 | 272 | request_id: context.request_id) |
| 240 | 273 | end |
| 241 | 274 | private :log_response |
| 242 | 275 | |
| 243 | - def log_response_error(context, request_start, e) | |
| 244 | - Util.log_error("Request error", | |
| 276 | + def log_response_error(context, request_start, e) # rubocop:disable Metrics/LineLength, Naming/UncommunicativeMethodParamName | |
| 277 | + Util.log_error('Request error', | |
| 245 | 278 | elapsed: Time.now - request_start, |
| 246 | 279 | error_message: e.message, |
| 247 | 280 | method: context.method, |
| ... | ... | @@ -249,6 +282,26 @@ module Syspro |
| 249 | 282 | end |
| 250 | 283 | private :log_response_error |
| 251 | 284 | |
| 285 | + def handle_error_response(http_resp, context) # rubocop:disable Metrics/LineLength, Metrics/MethodLength | |
| 286 | + begin | |
| 287 | + resp = SysproResponse.from_faraday_hash(http_resp) | |
| 288 | + error_data = resp.data[:error] | |
| 289 | + | |
| 290 | + raise SysproError, 'Indeterminate error' unless error_data | |
| 291 | + rescue Nokogiri::XML::SyntaxError, SysproError | |
| 292 | + raise general_api_error(http_resp[:status], http_resp[:body]) | |
| 293 | + end | |
| 294 | + | |
| 295 | + error = if error_data.is_a?(String) | |
| 296 | + specific_oauth_error(resp, error_data, context) | |
| 297 | + else | |
| 298 | + specific_api_error(resp, error_data, context) | |
| 299 | + end | |
| 300 | + | |
| 301 | + error.response = resp | |
| 302 | + raise(error) | |
| 303 | + end | |
| 304 | + | |
| 252 | 305 | # RequestLogContext stores information about a request that's begin made so |
| 253 | 306 | # that we can log certain information. It's useful because it means that we |
| 254 | 307 | # don't have to pass around as many parameters. |
| ... | ... | @@ -267,56 +320,55 @@ module Syspro |
| 267 | 320 | # in so that we can generate a rich user agent header to help debug |
| 268 | 321 | # integrations. |
| 269 | 322 | class SystemProfiler |
| 270 | - def self.uname | |
| 271 | - if File.exist?("/proc/version") | |
| 272 | - File.read("/proc/version").strip | |
| 323 | + def self.uname # rubocop:disable Metrics/MethodLength | |
| 324 | + if File.exist?('/proc/version') | |
| 325 | + File.read('/proc/version').strip | |
| 273 | 326 | else |
| 274 | - case RbConfig::CONFIG["host_os"] | |
| 327 | + case RbConfig::CONFIG['host_os'] | |
| 275 | 328 | when /linux|darwin|bsd|sunos|solaris|cygwin/i |
| 276 | 329 | uname_from_system |
| 277 | 330 | when /mswin|mingw/i |
| 278 | 331 | uname_from_system_ver |
| 279 | 332 | else |
| 280 | - "unknown platform" | |
| 333 | + 'unknown platform' | |
| 281 | 334 | end |
| 282 | 335 | end |
| 283 | 336 | end |
| 284 | 337 | |
| 285 | 338 | def self.uname_from_system |
| 286 | - (`uname -a 2>/dev/null` || "").strip | |
| 339 | + (`uname -a 2>/dev/null` || '').strip | |
| 287 | 340 | rescue Errno::ENOENT |
| 288 | - "uname executable not found" | |
| 341 | + 'uname executable not found' | |
| 289 | 342 | rescue Errno::ENOMEM # couldn't create subprocess |
| 290 | - "uname lookup failed" | |
| 343 | + 'uname lookup failed' | |
| 291 | 344 | end |
| 292 | 345 | |
| 293 | 346 | def self.uname_from_system_ver |
| 294 | - (`ver` || "").strip | |
| 347 | + (`ver` || '').strip | |
| 295 | 348 | rescue Errno::ENOENT |
| 296 | - "ver executable not found" | |
| 349 | + 'ver executable not found' | |
| 297 | 350 | rescue Errno::ENOMEM # couldn't create subprocess |
| 298 | - "uname lookup failed" | |
| 351 | + 'uname lookup failed' | |
| 299 | 352 | end |
| 300 | 353 | |
| 301 | 354 | def initialize |
| 302 | 355 | @uname = self.class.uname |
| 303 | 356 | end |
| 304 | 357 | |
| 305 | - def user_agent | |
| 306 | - lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})" | |
| 358 | + def user_agent # rubocop:disable Metrics/MethodLength | |
| 359 | + lang_version = "#{RUBY_VERSION} p#{RUBY_PATCHLEVEL} (#{RUBY_RELEASE_DATE})" # rubocop:disable Metrics/LineLength | |
| 307 | 360 | |
| 308 | 361 | { |
| 309 | 362 | application: Syspro.app_info, |
| 310 | 363 | bindings_version: Syspro::VERSION, |
| 311 | - lang: "ruby", | |
| 364 | + lang: 'ruby', | |
| 312 | 365 | lang_version: lang_version, |
| 313 | 366 | platform: RUBY_PLATFORM, |
| 314 | - engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : "", | |
| 367 | + engine: defined?(RUBY_ENGINE) ? RUBY_ENGINE : '', | |
| 315 | 368 | uname: @uname, |
| 316 | - hostname: Socket.gethostname, | |
| 369 | + hostname: Socket.gethostname | |
| 317 | 370 | }.delete_if { |_k, v| v.nil? } |
| 318 | 371 | end |
| 319 | 372 | end |
| 320 | 373 | end |
| 321 | 374 | end |
| 322 | - | ... | ... |
lib/syspro/syspro_object.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 4 | + # This class represents a syspro response | |
| 2 | 5 | class SysproObject |
| 3 | 6 | include Enumerable |
| 4 | 7 | |
| ... | ... | @@ -18,7 +21,8 @@ module Syspro |
| 18 | 21 | # considered to be equal if they have the same set of values and each one |
| 19 | 22 | # of those values is the same. |
| 20 | 23 | def ==(other) |
| 21 | - other.is_a?(SysproObject) && @values == other.instance_variable_get(:@values) | |
| 24 | + other.is_a?(SysproObject) && | |
| 25 | + @values == other.instance_variable_get(:@values) | |
| 22 | 26 | end |
| 23 | 27 | |
| 24 | 28 | def to_s(*_args) |
| ... | ... | @@ -26,8 +30,8 @@ module Syspro |
| 26 | 30 | end |
| 27 | 31 | |
| 28 | 32 | def inspect |
| 29 | - id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : "" | |
| 30 | - "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values) | |
| 33 | + id_string = respond_to?(:id) && !id.nil? ? " id=#{id}" : '' | |
| 34 | + "#<#{self.class}:0x#{object_id.to_s(16)}#{id_string}> JSON: " + JSON.pretty_generate(@values) # rubocop:disable Metrics/LineLength | |
| 31 | 35 | end |
| 32 | 36 | |
| 33 | 37 | def keys |
| ... | ... | @@ -38,9 +42,9 @@ module Syspro |
| 38 | 42 | @values.values |
| 39 | 43 | end |
| 40 | 44 | |
| 41 | - def to_hash | |
| 45 | + def to_hash # rubocop:disable Metrics/MethodLength | |
| 42 | 46 | maybe_to_hash = lambda do |value| |
| 43 | - value && value.respond_to?(:to_hash) ? value.to_hash : value | |
| 47 | + value&.respond_to?(:to_hash) ? value.to_hash : value | |
| 44 | 48 | end |
| 45 | 49 | |
| 46 | 50 | @values.each_with_object({}) do |(key, value), acc| |
| ... | ... | @@ -57,11 +61,9 @@ module Syspro |
| 57 | 61 | @values.each(&blk) |
| 58 | 62 | end |
| 59 | 63 | |
| 60 | - private | |
| 61 | - | |
| 62 | 64 | # Produces a deep copy of the given object including support for arrays, |
| 63 | 65 | # hashes, and SysproObjects. |
| 64 | - def self.deep_copy(obj) | |
| 66 | + def self.deep_copy(obj) # rubocop:disable Metrics/MethodLength | |
| 65 | 67 | case obj |
| 66 | 68 | when Array |
| 67 | 69 | obj.map { |e| deep_copy(e) } |
| ... | ... | @@ -82,6 +84,5 @@ module Syspro |
| 82 | 84 | end |
| 83 | 85 | end |
| 84 | 86 | private_class_method :deep_copy |
| 85 | - | |
| 86 | 87 | end |
| 87 | 88 | end | ... | ... |
lib/syspro/syspro_response.rb
| 1 | -require "nokogiri" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'nokogiri' | |
| 2 | 4 | |
| 3 | 5 | module Syspro |
| 6 | + # This class represents a syspro response | |
| 4 | 7 | class SysproResponse |
| 5 | 8 | attr_accessor :data, :http_body, :http_headers, :http_status, :request_id |
| 6 | 9 | |
| ... | ... | @@ -12,7 +15,7 @@ module Syspro |
| 12 | 15 | resp.data = Nokogiri::XML(resp.http_body) |
| 13 | 16 | resp.http_headers = http_resp[:headers] |
| 14 | 17 | resp.http_status = http_resp[:status] |
| 15 | - resp.request_id = http_resp[:headers]["Request-Id"] | |
| 18 | + resp.request_id = http_resp[:headers]['Request-Id'] | |
| 16 | 19 | resp |
| 17 | 20 | end |
| 18 | 21 | |
| ... | ... | @@ -23,7 +26,7 @@ module Syspro |
| 23 | 26 | resp.data = Nokogiri::XML(resp.http_body) |
| 24 | 27 | resp.http_headers = http_resp.headers |
| 25 | 28 | resp.http_status = http_resp.status |
| 26 | - resp.request_id = http_resp.headers["Request-Id"] | |
| 29 | + resp.request_id = http_resp.headers['Request-Id'] | |
| 27 | 30 | resp |
| 28 | 31 | end |
| 29 | 32 | end | ... | ... |
lib/syspro/util.rb
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 1 | 3 | module Syspro |
| 2 | - class Util | |
| 4 | + # Utillity class | |
| 5 | + class Util # rubocop:disable Metrics/ClassLength | |
| 3 | 6 | # Options that a user is allowed to specify. |
| 4 | 7 | OPTS_USER_SPECIFIED = Set[ |
| 5 | 8 | :user_id |
| ... | ... | @@ -17,8 +20,7 @@ module Syspro |
| 17 | 20 | OPTS_USER_SPECIFIED + Set[:client] |
| 18 | 21 | ).freeze |
| 19 | 22 | |
| 20 | - | |
| 21 | - def self.objects_to_ids(h) | |
| 23 | + def self.objects_to_ids(h) # rubocop:disable Metrics/MethodLength, Metrics/LineLength, Naming/UncommunicativeMethodParamName | |
| 22 | 24 | case h |
| 23 | 25 | when ApiResource |
| 24 | 26 | h.id |
| ... | ... | @@ -45,13 +47,17 @@ module Syspro |
| 45 | 47 | # * +data+ - Hash of fields and values to be converted into a SysproObject. |
| 46 | 48 | # * +opts+ - Options for +SysproObject+ like an API key that will be reused |
| 47 | 49 | # on subsequent API calls. |
| 48 | - def self.convert_to_syspro_object(data, opts = {}) | |
| 50 | + def self.convert_to_syspro_object(data, opts = {}) # rubocop:disable Metrics/LineLength, Metrics/MethodLength | |
| 49 | 51 | case data |
| 50 | 52 | when Array |
| 51 | 53 | data.map { |i| convert_to_syspro_object(i, opts) } |
| 52 | 54 | when Hash |
| 53 | - # Try converting to a known object class. If none available, fall back to generic SysproObject | |
| 54 | - object_classes.fetch(data[:object], SysproObject).construct_from(data, opts) | |
| 55 | + # Try converting to a known object class. | |
| 56 | + # If none available, fall back to generic SysproObject | |
| 57 | + object_classes.fetch( | |
| 58 | + data[:object], | |
| 59 | + SysproObject | |
| 60 | + ).construct_from(data, opts) | |
| 55 | 61 | else |
| 56 | 62 | data |
| 57 | 63 | end |
| ... | ... | @@ -66,7 +72,7 @@ module Syspro |
| 66 | 72 | when Hash |
| 67 | 73 | opts.clone |
| 68 | 74 | else |
| 69 | - raise TypeError, "normalize_opts expects a string or a hash" | |
| 75 | + raise TypeError, 'normalize_opts expects a string or a hash' | |
| 70 | 76 | end |
| 71 | 77 | end |
| 72 | 78 | |
| ... | ... | @@ -78,7 +84,7 @@ module Syspro |
| 78 | 84 | def self.normalize_headers(headers) |
| 79 | 85 | headers.each_with_object({}) do |(k, v), new_headers| |
| 80 | 86 | if k.is_a?(Symbol) |
| 81 | - k = titlecase_parts(k.to_s.tr("_", "-")) | |
| 87 | + k = titlecase_parts(k.to_s.tr('_', '-')) | |
| 82 | 88 | elsif k.is_a?(String) |
| 83 | 89 | k = titlecase_parts(k) |
| 84 | 90 | end |
| ... | ... | @@ -89,10 +95,10 @@ module Syspro |
| 89 | 95 | |
| 90 | 96 | def self.encode_parameters(params) |
| 91 | 97 | Util.flatten_params(params) |
| 92 | - .map { |k, v| "#{url_encode(k)}=#{url_encode(v)}" }.join("&") | |
| 98 | + .map { |k, v| "#{url_encode(k)}=#{url_encode(v)}" }.join('&') | |
| 93 | 99 | end |
| 94 | 100 | |
| 95 | - def self.flatten_params(params, parent_key = nil) | |
| 101 | + def self.flatten_params(params, parent_key = nil) # rubocop:disable Metrics/LineLength, Metrics/MethodLength | |
| 96 | 102 | result = [] |
| 97 | 103 | |
| 98 | 104 | # do not sort the final output because arrays (and arrays of hashes |
| ... | ... | @@ -113,26 +119,41 @@ module Syspro |
| 113 | 119 | end |
| 114 | 120 | |
| 115 | 121 | def self.log_error(message, data = {}) |
| 116 | - if !Syspro.logger.nil? || | |
| 117 | - !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_ERROR | |
| 118 | - log_internal(message, data, color: :cyan, | |
| 119 | - level: Syspro::LEVEL_ERROR, logger: Syspro.logger, out: $stderr) | |
| 122 | + if !Syspro.logger.nil? || !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_ERROR # rubocop:disable Style/GuardClause, Metrics/LineLength | |
| 123 | + log_internal( | |
| 124 | + message, | |
| 125 | + data, | |
| 126 | + color: :cyan, | |
| 127 | + level: Syspro::LEVEL_ERROR, | |
| 128 | + logger: Syspro.logger, | |
| 129 | + out: $stderr | |
| 130 | + ) | |
| 120 | 131 | end |
| 121 | 132 | end |
| 122 | 133 | |
| 123 | 134 | def self.log_info(message, data = {}) |
| 124 | - if !Syspro.logger.nil? || | |
| 125 | - !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_INFO | |
| 126 | - log_internal(message, data, color: :cyan, | |
| 127 | - level: Syspro::LEVEL_INFO, logger: Syspro.logger, out: $stdout) | |
| 135 | + if !Syspro.logger.nil? || !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_INFO # rubocop:disable Style/GuardClause, Metrics/LineLength | |
| 136 | + log_internal( | |
| 137 | + message, | |
| 138 | + data, | |
| 139 | + color: :cyan, | |
| 140 | + level: Syspro::LEVEL_INFO, | |
| 141 | + logger: Syspro.logger, | |
| 142 | + out: $stdout | |
| 143 | + ) | |
| 128 | 144 | end |
| 129 | 145 | end |
| 130 | 146 | |
| 131 | 147 | def self.log_debug(message, data = {}) |
| 132 | - if !Syspro.logger.nil? || | |
| 133 | - !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_DEBUG | |
| 134 | - log_internal(message, data, color: :blue, | |
| 135 | - level: Syspro::LEVEL_DEBUG, logger: Syspro.logger, out: $stdout) | |
| 148 | + if !Syspro.logger.nil? || !Syspro.log_level.nil? && Syspro.log_level <= Syspro::LEVEL_DEBUG # rubocop:disable Style/GuardClause, Metrics/LineLength | |
| 149 | + log_internal( | |
| 150 | + message, | |
| 151 | + data, | |
| 152 | + color: :blue, | |
| 153 | + level: Syspro::LEVEL_DEBUG, | |
| 154 | + logger: Syspro.logger, | |
| 155 | + out: $stdout | |
| 156 | + ) | |
| 136 | 157 | end |
| 137 | 158 | end |
| 138 | 159 | |
| ... | ... | @@ -141,8 +162,47 @@ module Syspro |
| 141 | 162 | # Don't use strict form encoding by changing the square bracket control |
| 142 | 163 | # characters back to their literals. This is fine by the server, and |
| 143 | 164 | # makes these parameter strings easier to read. |
| 144 | - gsub("%5B", "[").gsub("%5D", "]") | |
| 165 | + gsub('%5B', '[').gsub('%5D', ']') | |
| 145 | 166 | end |
| 167 | + | |
| 168 | + # TODO: Make these named required arguments when we drop support for Ruby | |
| 169 | + # 2.0. | |
| 170 | + def self.log_internal(message, data = {}, color: nil, level: nil, logger: nil, out: nil) # rubocop:disable Metrics/LineLength, Metrics/AbcSize, Metrics/MethodLength, Metrics/ParameterLists | |
| 171 | + data_str = data.reject { |_k, v| v.nil? }.map do |(k, v)| | |
| 172 | + format( | |
| 173 | + '%s=%s', # rubocop:disable Style/FormatStringToken | |
| 174 | + colorize(k, color, !out.nil? && out.isatty), | |
| 175 | + wrap_logfmt_value(v) | |
| 176 | + ) | |
| 177 | + end.join(' ') | |
| 178 | + | |
| 179 | + if !logger.nil? | |
| 180 | + # the library's log levels are mapped to the same values as the | |
| 181 | + # standard library's logger | |
| 182 | + logger.log( | |
| 183 | + level, | |
| 184 | + format( | |
| 185 | + 'message=%s %s', # rubocop:disable Style/FormatStringToken | |
| 186 | + wrap_logfmt_value(message), | |
| 187 | + data_str | |
| 188 | + ) | |
| 189 | + ) | |
| 190 | + elsif out.isatty | |
| 191 | + out.puts format( | |
| 192 | + '%s %s %s', # rubocop:disable Style/FormatStringToken | |
| 193 | + colorize(level_name(level)[0, 4].upcase, color, out.isatty), | |
| 194 | + message, | |
| 195 | + data_str | |
| 196 | + ) | |
| 197 | + else | |
| 198 | + out.puts format( | |
| 199 | + 'message=%s level=%s %s', # rubocop:disable Style/FormatStringToken | |
| 200 | + wrap_logfmt_value(message), | |
| 201 | + level_name(level), | |
| 202 | + data_str | |
| 203 | + ) | |
| 204 | + end | |
| 205 | + end | |
| 206 | + private_class_method :log_internal | |
| 146 | 207 | end |
| 147 | 208 | end |
| 148 | - | ... | ... |
lib/syspro/version.rb
syspro-ruby.gemspec
| 1 | -lib = File.expand_path("../lib", __FILE__) | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +lib = File.expand_path('lib', __dir__) | |
| 2 | 4 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) |
| 3 | -require "syspro/version" | |
| 5 | +require 'syspro/version' | |
| 4 | 6 | |
| 5 | 7 | Gem::Specification.new do |spec| |
| 6 | - spec.name = "syspro-ruby" | |
| 8 | + spec.name = 'syspro-ruby' | |
| 7 | 9 | spec.version = Syspro::VERSION |
| 8 | - spec.authors = ["Isaac Lewis"] | |
| 9 | - spec.email = ["isaac@ike.io"] | |
| 10 | + spec.authors = ['Isaac Lewis'] | |
| 11 | + spec.email = ['isaac@ike.io'] | |
| 10 | 12 | |
| 11 | - spec.summary = %q{SYSPRO 7 Api Ruby adapter} | |
| 12 | - spec.license = "MIT" | |
| 13 | + spec.summary = 'SYSPRO 7 Api Ruby adapter' | |
| 14 | + spec.license = 'MIT' | |
| 13 | 15 | |
| 14 | 16 | # Prevent pushing this gem to RubyGems.org. To allow pushes either set the 'allowed_push_host' |
| 15 | 17 | # to allow pushing to a single host or delete this section to allow pushing to any host. |
| 16 | 18 | if spec.respond_to?(:metadata) |
| 17 | - spec.metadata["allowed_push_host"] = "http://rubygems.org" | |
| 19 | + spec.metadata['allowed_push_host'] = 'http://rubygems.org' | |
| 18 | 20 | else |
| 19 | - raise "RubyGems 2.0 or newer is required to protect against " \ | |
| 20 | - "public gem pushes." | |
| 21 | + raise 'RubyGems 2.0 or newer is required to protect against ' \ | |
| 22 | + 'public gem pushes.' | |
| 21 | 23 | end |
| 24 | + spec.required_ruby_version = '>= 1.9.0' | |
| 22 | 25 | |
| 23 | - spec.files = `git ls-files -z`.split("\x0").reject do |f| | |
| 26 | + spec.files = `git ls-files -z`.split("\x0").reject do |f| | |
| 24 | 27 | f.match(%r{^(test|spec|features)/}) |
| 25 | 28 | end |
| 26 | - spec.bindir = "exe" | |
| 29 | + spec.bindir = 'exe' | |
| 27 | 30 | spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } |
| 28 | - spec.require_paths = ["lib"] | |
| 31 | + spec.require_paths = ['lib'] | |
| 29 | 32 | |
| 30 | - spec.add_dependency("faraday", "~> 0.10") | |
| 33 | + spec.add_dependency('faraday', '~> 0.10') | |
| 34 | + spec.add_dependency('nokogiri', '~> 1.8.2') | |
| 31 | 35 | |
| 32 | - spec.add_development_dependency "bundler", "~> 1.16" | |
| 33 | - spec.add_development_dependency "pry", "~> 0.11" | |
| 34 | - spec.add_development_dependency "rake", "~> 10.0" | |
| 35 | - spec.add_development_dependency "minitest", "~> 5.0" | |
| 36 | + spec.add_development_dependency 'bundler', '~> 1.16' | |
| 37 | + spec.add_development_dependency 'minitest', '~> 5.0' | |
| 38 | + spec.add_development_dependency 'pry', '~> 0.11' | |
| 39 | + spec.add_development_dependency 'rake', '~> 10.0' | |
| 40 | + spec.add_development_dependency 'rubocop', '~> 0.54.0' | |
| 41 | + spec.add_development_dependency 'webmock', '~> 3.3.0' | |
| 42 | + spec.add_development_dependency 'minitest-vcr', '~> 1.4.0' | |
| 36 | 43 | end | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/getversion | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '7' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:23:43 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: 7.0.0.6 | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:23:42 GMT | |
| 36 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/getversion | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '7' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:23:43 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: 7.0.0.6 | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:23:42 GMT | |
| 36 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logoff?UserId=1BB5B3050954BB459A5D034DB5CC386980 | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '72' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:22:53 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: 'ERROR: Unable to read the SYSPRO base directory registry string BaseDir8' | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:22:52 GMT | |
| 36 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logon?CompanyId=L&CompanyPassword=&Operator=wland&OperatorPassword=piperita2016 | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '36' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:23:52 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: 'EC3098D6E284FB44ADF10671B3F06FCA00 ' | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:23:51 GMT | |
| 36 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logon?CompanyId=L&CompanyPassword=&Operator=wland&OperatorPassword=piperita2016 | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '36' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:23:03 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: '64C41E1DEB73024CA660211DE643705700 ' | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:23:01 GMT | |
| 36 | +- request: | |
| 37 | + method: get | |
| 38 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/Query/Browse?UserId=64C41E1DEB73024CA660211DE643705700%20%20&XmlIn=%3C?xml%20version=%221.0%22%20encoding=%22Windows-1252%22?%3E%0A%3CBrowse%20xmlns:xsd=%22http://www.w3.org/2001/XMLSchema-instance%22%20xsd:noNamespaceSchemaLocation=%22COMBRW.XSD%22%3E%0A%20%20%3CBrowseName%3EInvMaster%3C/BrowseName%3E%0A%20%20%3CStartAtKey/%3E%0A%20%20%3CStartCondition%3E%3C/StartCondition%3E%0A%20%20%3CReturnRows%3E5%3C/ReturnRows%3E%0A%20%20%0A%20%20%3CBrowseDetails%3E%0A%20%20%20%20%3CTableName%3EInvMaster%3C/TableName%3E%0A%20%20%20%20%3CTitle%3EStockCodes%3C/Title%3E%0A%20%20%20%20%0A%20%20%20%20%20%20%3CColumn%3E%0A%20%20%20%20%20%20%20%20%3CColumnName%3EStockCode%3C/ColumnName%3E%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%3C/Column%3E%0A%20%20%20%20%0A%20%20%3C/BrowseDetails%3E%0A%3C/Browse%3E%0A%0A | |
| 39 | + body: | |
| 40 | + encoding: US-ASCII | |
| 41 | + string: '' | |
| 42 | + headers: | |
| 43 | + User-Agent: | |
| 44 | + - Syspro/7 RubyBindings/0.1.0 | |
| 45 | + Content-Type: | |
| 46 | + - application/x-www-form-urlencoded | |
| 47 | + Accept-Encoding: | |
| 48 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 49 | + Accept: | |
| 50 | + - "*/*" | |
| 51 | + response: | |
| 52 | + status: | |
| 53 | + code: 200 | |
| 54 | + message: OK | |
| 55 | + headers: | |
| 56 | + Content-Length: | |
| 57 | + - '944' | |
| 58 | + Content-Type: | |
| 59 | + - application/octet-stream | |
| 60 | + Server: | |
| 61 | + - Microsoft-HTTPAPI/2.0 | |
| 62 | + Date: | |
| 63 | + - Fri, 06 Apr 2018 19:23:07 GMT | |
| 64 | + body: | |
| 65 | + encoding: UTF-8 | |
| 66 | + string: "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<InvMaster Language='05' | |
| 67 | + Language2='EN' CssStyle='' DecFormat='1' DateFormat='01' Role='01' Version='7.0.036' | |
| 68 | + OperatorPrimaryRole=' '>\n<Title>StockCodes</Title>\n<Row>\n<StockCode>\n<Value>02</Value>\n<DataType>AlphaNumeric</DataType>\n</StockCode>\n</Row>\n<Row>\n<StockCode>\n<Value>021</Value>\n<DataType>AlphaNumeric</DataType>\n</StockCode>\n</Row>\n<Row>\n<StockCode>\n<Value>0214011IFF</Value>\n<DataType>AlphaNumeric</DataType>\n</StockCode>\n</Row>\n<Row>\n<StockCode>\n<Value>022</Value>\n<DataType>AlphaNumeric</DataType>\n</StockCode>\n</Row>\n<Row>\n<StockCode>\n<Value>023</Value>\n<DataType>AlphaNumeric</DataType>\n</StockCode>\n</Row>\n<NextPrevKey>\n<PrevKey>02</PrevKey>\n<NextKey>023</NextKey>\n<Fwd>True</Fwd>\n<Back>False</Back>\n</NextPrevKey>\n<HeaderDetails>\n<Header>Stock | |
| 69 | + code</Header>\n<Key>StockCode</Key>\n<KeyDescription>Stock code</KeyDescription>\n<Table>InvMaster</Table>\n</HeaderDetails>\n</InvMaster>\n " | |
| 70 | + http_version: | |
| 71 | + recorded_at: Fri, 06 Apr 2018 19:23:06 GMT | |
| 72 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logon?CompanyId=L&CompanyPassword=&Operator=wland&OperatorPassword=piperita2016 | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '36' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:23:16 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: '5B21680F424424498B7CE7CCDA98B41700 ' | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:23:15 GMT | |
| 36 | +- request: | |
| 37 | + method: get | |
| 38 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/Query/Fetch?UserId=5B21680F424424498B7CE7CCDA98B41700%20%20&XmlIn=%3C?xml%20version=%221.0%22%20encoding=%22Windows-1252%22?%3E%0A%3CFetch%20xmlns:xsd=%22http://www.w3.org/2001/XMLSchema-instance%22%20xsd:noNamespaceSchemaLocation=%22COMFCH.XSD%22%3E%0A%20%20%3CTableName%3EInvMaster%3C/TableName%3E%0A%20%20%3CKey%3E02%3C/Key%3E%0A%20%20%0A%20%20%3CFullKeyProvided%3EY%3C/FullKeyProvided%3E%0A%20%20%3CDefaultType%3E%3C/DefaultType%3E%0A%20%20%3CEspressoFetch%3EN%3C/EspressoFetch%3E%0A%3C/Fetch%3E%0A%0A | |
| 39 | + body: | |
| 40 | + encoding: US-ASCII | |
| 41 | + string: '' | |
| 42 | + headers: | |
| 43 | + User-Agent: | |
| 44 | + - Syspro/7 RubyBindings/0.1.0 | |
| 45 | + Content-Type: | |
| 46 | + - application/x-www-form-urlencoded | |
| 47 | + Accept-Encoding: | |
| 48 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 49 | + Accept: | |
| 50 | + - "*/*" | |
| 51 | + response: | |
| 52 | + status: | |
| 53 | + code: 200 | |
| 54 | + message: OK | |
| 55 | + headers: | |
| 56 | + Content-Length: | |
| 57 | + - '3911' | |
| 58 | + Content-Type: | |
| 59 | + - application/octet-stream | |
| 60 | + Server: | |
| 61 | + - Microsoft-HTTPAPI/2.0 | |
| 62 | + Date: | |
| 63 | + - Fri, 06 Apr 2018 19:23:26 GMT | |
| 64 | + body: | |
| 65 | + encoding: UTF-8 | |
| 66 | + string: "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<InvMaster Language='05' | |
| 67 | + Language2='EN' CssStyle='' DecFormat='1' DateFormat='01' Role='01' Version='7.0.035' | |
| 68 | + OperatorPrimaryRole=' '>\n<StockCode>02</StockCode>\n<Description>STR</Description>\n<LongDesc>SPEARMINT | |
| 69 | + TERPENES</LongDesc>\n<AlternateKey1/>\n<AlternateKey2/>\n<EccUser/>\n<StockUom>LB</StockUom>\n<AlternateUom>KG</AlternateUom>\n<OtherUom>DR</OtherUom>\n<ConvFactAltUom> | |
| 70 | + \ 2.204620</ConvFactAltUom>\n<ConvMulDiv>M</ConvMulDiv>\n<ConvFactOthUom> | |
| 71 | + \ 400.000000</ConvFactOthUom>\n<MulDiv>M</MulDiv>\n<Mass> 1.000000</Mass>\n<Volume> | |
| 72 | + \ 0.000000</Volume>\n<Decimals>3</Decimals>\n<PriceCategory>A</PriceCategory>\n<PriceMethod>C</PriceMethod>\n<Supplier/>\n<CycleCount> | |
| 73 | + 0</CycleCount>\n<ProductClass>STRP</ProductClass>\n<TaxCode>A</TaxCode>\n<OtherTaxCode/>\n<ListPriceCode>A</ListPriceCode>\n<SerialMethod>N</SerialMethod>\n<InterfaceFlag>Y</InterfaceFlag>\n<KitType>N</KitType>\n<LowLevelCode> | |
| 74 | + 0</LowLevelCode>\n<Buyer/>\n<Planner/>\n<TraceableType>T</TraceableType>\n<MpsFlag>N</MpsFlag>\n<BulkIssueFlag>N</BulkIssueFlag>\n<AbcClass/>\n<LeadTime> | |
| 75 | + \ 0</LeadTime>\n<StockMovementReq>Y</StockMovementReq>\n<ClearingFlag>N</ClearingFlag>\n<SupercessionDate>0000-00-00</SupercessionDate>\n<AbcAnalysisReq>Y</AbcAnalysisReq>\n<AbcCostingReq>N</AbcCostingReq>\n<CostUom>LB</CostUom>\n<MinPricePct> | |
| 76 | + \ 0.00</MinPricePct>\n<LabourCost> 0.00000</LabourCost>\n<MaterialCost> | |
| 77 | + \ 0.00000</MaterialCost>\n<FixOverhead> 0.00000</FixOverhead>\n<VariableOverhead> | |
| 78 | + \ 0.00000</VariableOverhead>\n<PartCategory>B</PartCategory>\n<DrawOfficeNum/>\n<WarehouseToUse>H1</WarehouseToUse>\n<BuyingRule>A</BuyingRule>\n<SpecificGravity> | |
| 79 | + 0.0000</SpecificGravity>\n<ImplosionNum> 0</ImplosionNum>\n<Ebq> 400.000000</Ebq>\n<ComponentCount> | |
| 80 | + \ 0</ComponentCount>\n<FixTimePeriod> 1</FixTimePeriod>\n<PanSize> 0.000000</PanSize>\n<DockToStock> | |
| 81 | + \ 0</DockToStock>\n<OutputMassFlag>F</OutputMassFlag>\n<ShelfLife> | |
| 82 | + \ 0</ShelfLife>\n<Version/>\n<Release/>\n<DemandTimeFence> 0</DemandTimeFence>\n<MakeToOrderFlag>N</MakeToOrderFlag>\n<ManufLeadTime> | |
| 83 | + \ 0</ManufLeadTime>\n<GrossReqRule>I</GrossReqRule>\n<PercentageYield>100</PercentageYield>\n<AbcPreProd> | |
| 84 | + \ 0.00000</AbcPreProd>\n<AbcManufacturing> 0.00000</AbcManufacturing>\n<AbcSales> | |
| 85 | + \ 0.00000</AbcSales>\n<AbcCumPreProd> 0.00000</AbcCumPreProd>\n<AbcCumManuf> | |
| 86 | + \ 0.00000</AbcCumManuf>\n<WipCtlGlCode/>\n<ResourceCode/>\n<GstTaxCode>A</GstTaxCode>\n<PrcInclGst>N</PrcInclGst>\n<SerEntryAtSale/>\n<StpSelection/>\n<UserField1/>\n<UserField2> | |
| 87 | + \ 0.00000</UserField2>\n<UserField3/>\n<UserField4/>\n<UserField5/>\n<TariffCode/>\n<SupplementaryUnit>N</SupplementaryUnit>\n<EbqPan>E</EbqPan>\n<StdLandedCost> | |
| 88 | + \ 0.00000</StdLandedCost>\n<LctRequired>N</LctRequired>\n<StdLctRoute/>\n<IssMultLotsFlag>Y</IssMultLotsFlag>\n<InclInStrValid>Y</InclInStrValid>\n<StdLabCostsBill> | |
| 89 | + \ 0.00000</StdLabCostsBill>\n<PhantomIfComp/>\n<CountryOfOrigin/>\n<StockOnHold/>\n<StockOnHoldReason/>\n<EccFlag>N</EccFlag>\n<StockAndAltUm>N</StockAndAltUm>\n<AltUnitChar>0</AltUnitChar>\n<JobsOnHold/>\n<JobHoldAllocs/>\n<PurchOnHold/>\n<SalesOnHold/>\n<MaintOnHold/>\n<BatchBill>N</BatchBill>\n<BlanketPoExists/>\n<CallOffBpoExists/>\n<DistWarehouseToUse/>\n<JobClassification/>\n<SubContractCost> | |
| 90 | + \ 0.00000</SubContractCost>\n<DateStkAdded>2005-08-26</DateStkAdded>\n<InspectionFlag/>\n<SerialPrefix/>\n<SerialSuffix/>\n<ReturnableItem/>\n<ProductGroup/>\n<PriceType/>\n<Basis/>\n<ManualCostFlag/>\n<ManufactureUom>LB</ManufactureUom>\n<ConvFactMuM> | |
| 91 | + \ 1.000000</ConvFactMuM>\n<ManMulDiv>M</ManMulDiv>\n<LookAheadWin> 0</LookAheadWin>\n<LoadingFactor> | |
| 92 | + \ 0.000</LoadingFactor>\n<SupplUnitCode/>\n<StorageSecurity/>\n<StorageHazard/>\n<StorageCondition/>\n<ProductShelfLife> | |
| 93 | + \ 0</ProductShelfLife>\n<InternalShelfLife> 0</InternalShelfLife>\n<AltMethodFlag/>\n<AltSisoFlag/>\n<AltReductionFlag/>\n<WithTaxExpenseType/>\n</InvMaster>\n " | |
| 94 | + http_version: | |
| 95 | + recorded_at: Fri, 06 Apr 2018 19:23:24 GMT | |
| 96 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logon?CompanyId=L&CompanyPassword=&Operator=wland&OperatorPassword=piperita2016 | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '36' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:23:35 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: '5810EEA000F1F04BA915BAF98CA700EE00 ' | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:23:33 GMT | |
| 36 | +- request: | |
| 37 | + method: get | |
| 38 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/Query/Query?BusinessObject=COMFND&UserId=5810EEA000F1F04BA915BAF98CA700EE00%20%20&XmlIn=%3C?xml%20version=%221.0%22%20encoding=%22Windows-1252%22?%3E%0A%3CQuery%20xmlns:xsd=%22http://www.w3.org/2001/XMLSchema-instance%22%20xsd:noNamespaceSchemaLocation=%22COMFND.XSD%22%3E%0A%20%20%3CTableName%3EInvMaster%3C/TableName%3E%0A%20%20%3CReturnRows%3E5%3C/ReturnRows%3E%0A%20%20%3CColumns%3E%0A%20%20%20%20%0A%20%20%20%20%20%20%3CColumn%3EStockCode%3C/Column%3E%0A%20%20%20%20%0A%20%20%3C/Columns%3E%0A%20%20%0A%20%20%20%20%3CWhere%3E%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%3CExpression%3E%0A%20%20%20%20%20%20%20%20%20%20%3COpenBracket%3E(%3C/OpenBracket%3E%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%20%20%3CAndOr%3EAnd%3C/AndOr%3E%0A%20%20%20%20%20%20%20%20%20%20%0A%20%20%20%20%20%20%20%20%20%20%3CColumn%3EStockCode%3C/Column%3E%0A%20%20%20%20%20%20%20%20%20%20%3CCondition%3EEQ%3C/Condition%3E%0A%20%20%20%20%20%20%20%20%20%20%3CValue%3E02%3C/Value%3E%0A%20%20%20%20%20%20%20%20%20%20%3CCloseBracket%3E)%3C/CloseBracket%3E%0A%20%20%20%20%20%20%20%20%3C/Expression%3E%0A%20%20%20%20%20%20%0A%20%20%20%20%3C/Where%3E%0A%20%20%0A%20%20%3COrderBy%3E%0A%20%20%20%20%3CColumn%3EStockCode%3C/Column%3E%0A%20%20%3C/OrderBy%3E%0A%3C/Query%3E%0A | |
| 39 | + body: | |
| 40 | + encoding: US-ASCII | |
| 41 | + string: '' | |
| 42 | + headers: | |
| 43 | + User-Agent: | |
| 44 | + - Syspro/7 RubyBindings/0.1.0 | |
| 45 | + Content-Type: | |
| 46 | + - application/x-www-form-urlencoded | |
| 47 | + Accept-Encoding: | |
| 48 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 49 | + Accept: | |
| 50 | + - "*/*" | |
| 51 | + response: | |
| 52 | + status: | |
| 53 | + code: 200 | |
| 54 | + message: OK | |
| 55 | + headers: | |
| 56 | + Content-Length: | |
| 57 | + - '436' | |
| 58 | + Content-Type: | |
| 59 | + - application/octet-stream | |
| 60 | + Server: | |
| 61 | + - Microsoft-HTTPAPI/2.0 | |
| 62 | + Date: | |
| 63 | + - Fri, 06 Apr 2018 19:23:43 GMT | |
| 64 | + body: | |
| 65 | + encoding: UTF-8 | |
| 66 | + string: "<?xml version=\"1.0\" encoding=\"Windows-1252\"?>\n<InvMaster Language='05' | |
| 67 | + Language2='EN' CssStyle='' DecFormat='1' DateFormat='01' Role='01' Version='7.0.048' | |
| 68 | + OperatorPrimaryRole=' '>\n<HeaderDetails>\n<TableName>InvMaster</TableName>\n<Columns>\n<Column>StockCode</Column>\n</Columns>\n<OrderBy>\n<Column>StockCode</Column>\n</OrderBy>\n</HeaderDetails>\n<Row>\n<StockCode>02</StockCode>\n</Row>\n<RowsReturned> | |
| 69 | + \ 1</RowsReturned>\n</InvMaster>\n " | |
| 70 | + http_version: | |
| 71 | + recorded_at: Fri, 06 Apr 2018 19:23:41 GMT | |
| 72 | +recorded_with: VCR 4.0.0 | ... | ... |
| 1 | +--- | |
| 2 | +http_interactions: | |
| 3 | +- request: | |
| 4 | + method: get | |
| 5 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logon?CompanyId=L&CompanyPassword=&Operator=wland&OperatorPassword=piperita2016 | |
| 6 | + body: | |
| 7 | + encoding: US-ASCII | |
| 8 | + string: '' | |
| 9 | + headers: | |
| 10 | + User-Agent: | |
| 11 | + - Syspro/7 RubyBindings/0.1.0 | |
| 12 | + Content-Type: | |
| 13 | + - application/x-www-form-urlencoded | |
| 14 | + Accept-Encoding: | |
| 15 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 16 | + Accept: | |
| 17 | + - "*/*" | |
| 18 | + response: | |
| 19 | + status: | |
| 20 | + code: 200 | |
| 21 | + message: OK | |
| 22 | + headers: | |
| 23 | + Content-Length: | |
| 24 | + - '36' | |
| 25 | + Content-Type: | |
| 26 | + - application/octet-stream | |
| 27 | + Server: | |
| 28 | + - Microsoft-HTTPAPI/2.0 | |
| 29 | + Date: | |
| 30 | + - Fri, 06 Apr 2018 19:22:53 GMT | |
| 31 | + body: | |
| 32 | + encoding: UTF-8 | |
| 33 | + string: '989D81EB0B184A499E7AC2E28724EE9000 ' | |
| 34 | + http_version: | |
| 35 | + recorded_at: Fri, 06 Apr 2018 19:22:52 GMT | |
| 36 | +- request: | |
| 37 | + method: get | |
| 38 | + uri: http://syspro.wildlandlabs.com:90/SYSPROWCFService/Rest/logoff?UserId=989D81EB0B184A499E7AC2E28724EE9000%20%20 | |
| 39 | + body: | |
| 40 | + encoding: US-ASCII | |
| 41 | + string: '' | |
| 42 | + headers: | |
| 43 | + User-Agent: | |
| 44 | + - Syspro/7 RubyBindings/0.1.0 | |
| 45 | + Content-Type: | |
| 46 | + - application/x-www-form-urlencoded | |
| 47 | + Accept-Encoding: | |
| 48 | + - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 | |
| 49 | + Accept: | |
| 50 | + - "*/*" | |
| 51 | + response: | |
| 52 | + status: | |
| 53 | + code: 200 | |
| 54 | + message: OK | |
| 55 | + headers: | |
| 56 | + Content-Length: | |
| 57 | + - '1' | |
| 58 | + Content-Type: | |
| 59 | + - application/octet-stream | |
| 60 | + Server: | |
| 61 | + - Microsoft-HTTPAPI/2.0 | |
| 62 | + Date: | |
| 63 | + - Fri, 06 Apr 2018 19:22:53 GMT | |
| 64 | + body: | |
| 65 | + encoding: UTF-8 | |
| 66 | + string: '0' | |
| 67 | + http_version: | |
| 68 | + recorded_at: Fri, 06 Apr 2018 19:22:52 GMT | |
| 69 | +recorded_with: VCR 4.0.0 | ... | ... |
test/client_test.rb
| 1 | -require "test_helper" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'test_helper' | |
| 2 | 4 | |
| 3 | 5 | class SysproClientTest < Minitest::Test |
| 6 | + extend Minitest::Spec::DSL | |
| 7 | + before { VCR.insert_cassette name } | |
| 8 | + after { VCR.eject_cassette } | |
| 9 | + | |
| 10 | + let(:client) { ::Syspro::SysproClient.new } | |
| 11 | + | |
| 4 | 12 | def test_get_syspro_version |
| 5 | - client = ::Syspro::SysproClient.new | |
| 6 | - assert_match (/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/), client.get_syspro_version.version | |
| 13 | + assert_match( | |
| 14 | + /(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/, | |
| 15 | + client.get_syspro_version.version | |
| 16 | + ) | |
| 7 | 17 | end |
| 8 | 18 | |
| 9 | 19 | def test_client_block_execution |
| 10 | - client = ::Syspro::SysproClient.new | |
| 11 | - | |
| 12 | - version, resp = client.request { | |
| 20 | + version, resp = client.request do | |
| 13 | 21 | Syspro::GetVersion.get_version |
| 14 | - } | |
| 22 | + end | |
| 15 | 23 | |
| 16 | - assert_match version.version, resp.http_body | |
| 17 | - assert_match (/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/), version.version | |
| 24 | + assert_match(version.version, resp.http_body) | |
| 25 | + assert_match(/(\d+\.)?(\d+\.)?(\d+\.)?(\d+)/, version.version) | |
| 18 | 26 | end |
| 19 | 27 | end | ... | ... |
test/logoff_test.rb
| 1 | -require "test_helper" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'test_helper' | |
| 2 | 4 | |
| 3 | 5 | class LogoffTest < Minitest::Test |
| 4 | - def test_successful_logoff | |
| 5 | - username = "wland" | |
| 6 | - password = "piperita2016" | |
| 7 | - company = "L" | |
| 8 | - company_password = "" | |
| 6 | + extend Minitest::Spec::DSL | |
| 7 | + before { VCR.insert_cassette name } | |
| 8 | + after { VCR.eject_cassette } | |
| 9 | + | |
| 10 | + let(:username) { 'wland' } | |
| 11 | + let(:password) { 'piperita2016' } | |
| 12 | + let(:company) { 'L' } | |
| 13 | + let(:company_password) { '' } | |
| 9 | 14 | |
| 15 | + def test_successful_logoff | |
| 10 | 16 | uid = Syspro::Logon.logon(username, password, company, company_password) |
| 11 | 17 | assert_equal true, Syspro::Logoff.logoff(uid.guid) |
| 12 | 18 | end |
| 13 | 19 | |
| 14 | 20 | def test_logoff_error |
| 15 | - assert_kind_of String, Syspro::Logoff.logoff('1BB5B3050954BB459A5D034DB5CC386980') | |
| 21 | + assert_kind_of( | |
| 22 | + String, | |
| 23 | + Syspro::Logoff.logoff('1BB5B3050954BB459A5D034DB5CC386980') | |
| 24 | + ) | |
| 16 | 25 | end |
| 17 | 26 | end |
| 18 | - | ... | ... |
test/logon_test.rb
| 1 | -require "test_helper" | |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'test_helper' | |
| 2 | 4 | |
| 3 | 5 | class LogonTest < Minitest::Test |
| 4 | - def test_logon | |
| 5 | - username = "wland" | |
| 6 | - password = "piperita2016" | |
| 7 | - company = "L" | |
| 8 | - company_password = "" | |
| 9 | - client = ::Syspro::SysproClient.new | |
| 6 | + extend Minitest::Spec::DSL | |
| 7 | + before { VCR.insert_cassette name } | |
| 8 | + after { VCR.eject_cassette } | |
| 9 | + | |
| 10 | + let(:username) { 'wland' } | |
| 11 | + let(:password) { 'piperita2016' } | |
| 12 | + let(:company) { 'L' } | |
| 13 | + let(:company_password) { '' } | |
| 10 | 14 | |
| 11 | - assert_match (/([A-Z0-9]{33})\w/), client.logon(username, password, company, company_password).guid | |
| 15 | + def test_logon | |
| 16 | + assert_match( | |
| 17 | + /([A-Z0-9]{33})\w/, | |
| 18 | + ::Syspro::SysproClient.new.logon( | |
| 19 | + username, | |
| 20 | + password, | |
| 21 | + company, | |
| 22 | + company_password | |
| 23 | + ).guid | |
| 24 | + ) | |
| 12 | 25 | end |
| 13 | 26 | end |
| 14 | - | ... | ... |
| 1 | +# frozen_string_literal: true | |
| 2 | + | |
| 3 | +require 'test_helper' | |
| 4 | + | |
| 5 | +class QueryTest < Minitest::Test | |
| 6 | + extend Minitest::Spec::DSL | |
| 7 | + before { VCR.insert_cassette name } | |
| 8 | + after { VCR.eject_cassette } | |
| 9 | + | |
| 10 | + let(:username) { 'wland' } | |
| 11 | + let(:password) { 'piperita2016' } | |
| 12 | + let(:company) { 'L' } | |
| 13 | + let(:company_password) { '' } | |
| 14 | + let(:user_id) do | |
| 15 | + Syspro::Logon.logon(username, password, company, company_password) | |
| 16 | + end | |
| 17 | + | |
| 18 | + def test_query_browse # rubocop:disable Metrics/MethodLength | |
| 19 | + combrw = Syspro::BusinessObjects::ComBrw.new | |
| 20 | + combrw.browse_name = 'InvMaster' | |
| 21 | + combrw.start_condition = '' | |
| 22 | + combrw.return_rows = 5 | |
| 23 | + combrw.filters = [] | |
| 24 | + combrw.table_name = 'InvMaster' | |
| 25 | + combrw.title = 'StockCodes' | |
| 26 | + combrw.columns = [ | |
| 27 | + { name: 'StockCode' } | |
| 28 | + ] | |
| 29 | + | |
| 30 | + browse_result = combrw.call(user_id.guid) | |
| 31 | + | |
| 32 | + refute_nil browse_result | |
| 33 | + end | |
| 34 | + | |
| 35 | + def test_query_query # rubocop:disable Metrics/MethodLength | |
| 36 | + comfnd = Syspro::BusinessObjects::ComFnd.new | |
| 37 | + comfnd.table_name = 'InvMaster' | |
| 38 | + comfnd.return_rows = 5 | |
| 39 | + comfnd.columns = [ | |
| 40 | + { | |
| 41 | + name: 'StockCode' | |
| 42 | + } | |
| 43 | + ] | |
| 44 | + comfnd.expressions = [ | |
| 45 | + { | |
| 46 | + andor: 'And', | |
| 47 | + column: 'StockCode', | |
| 48 | + condition: 'EQ', | |
| 49 | + value: '02' | |
| 50 | + } | |
| 51 | + ] | |
| 52 | + comfnd.order_by = 'StockCode' | |
| 53 | + | |
| 54 | + query_result = comfnd.call(user_id.guid) | |
| 55 | + | |
| 56 | + refute_nil query_result | |
| 57 | + end | |
| 58 | + | |
| 59 | + def test_query_fetch | |
| 60 | + comfch = Syspro::BusinessObjects::ComFch.new | |
| 61 | + comfch.table_name = 'InvMaster' | |
| 62 | + comfch.key = '02' | |
| 63 | + comfch.optional_keys = [] | |
| 64 | + comfch.full_key_provided = false | |
| 65 | + comfch.default_type = '' | |
| 66 | + comfch.espresso_fetch = true | |
| 67 | + | |
| 68 | + fetch_result = comfch.call(user_id.guid) | |
| 69 | + | |
| 70 | + refute_nil fetch_result | |
| 71 | + end | |
| 72 | +end | ... | ... |
test/syspro_test.rb
test/test_helper.rb
| 1 | -$LOAD_PATH.unshift File.expand_path("../../lib", __FILE__) | |
| 2 | -require "syspro" | |
| 1 | +# frozen_string_literal: true | |
| 3 | 2 | |
| 4 | -require "pry" | |
| 5 | -require "minitest/autorun" | |
| 3 | +$LOAD_PATH.unshift File.expand_path('../lib', __dir__) | |
| 4 | +require 'syspro' | |
| 5 | + | |
| 6 | +require 'pry' | |
| 7 | +require 'minitest/autorun' | |
| 8 | +require 'minitest-vcr' | |
| 9 | +require 'webmock' | |
| 10 | + | |
| 11 | +VCR.configure do |c| | |
| 12 | + c.cassette_library_dir = 'test/cassettes' | |
| 13 | + c.hook_into :webmock | |
| 14 | + # TODO: change passwords and move them to ENV | |
| 15 | + # c.filter_sensitive_data() { ENV[] } | |
| 16 | +end | |
| 17 | + | |
| 18 | +MinitestVcr::Spec.configure! | ... | ... |