From caed1180b16834b87bbf58ddb04be7940de065d0 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 13:14:43 +0100 Subject: [PATCH 01/24] BX-68618: multipart request example --- examples/multipart_language_file.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 examples/multipart_language_file.rb diff --git a/examples/multipart_language_file.rb b/examples/multipart_language_file.rb new file mode 100644 index 0000000..99cbf35 --- /dev/null +++ b/examples/multipart_language_file.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +require 'rosette_api' + +api_key, url = ARGV + +rosette_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end + +begin + # Create a sample file to upload (so the example is runnable as-is). + file_path = File.expand_path('sample.txt', __dir__) + File.write(file_path, "Bonjour tout le monde.\n") + + params = DocumentParameters.new(file_path: file_path) + response = rosette_api.get_language(params) + puts JSON.pretty_generate(response) +rescue RosetteAPIError => e + printf('Rosette API Error (%s): %s', + status_code: e.status_code, + message: e.message) +end From b3300f67d08e41465dae300e29e7fbdd691f2f99 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 12:13:51 +0100 Subject: [PATCH 02/24] BX-68618: fix rubocop offenses --- lib/request_builder.rb | 25 ++++++++++++++++--------- rosette_api.gemspec | 2 -- 2 files changed, 16 insertions(+), 11 deletions(-) diff --git a/lib/request_builder.rb b/lib/request_builder.rb index 6b28366..d6173c3 100644 --- a/lib/request_builder.rb +++ b/lib/request_builder.rb @@ -91,26 +91,22 @@ def prepare_plain_request(params) # # Returns a HTTP connection and the built POST request. def prepare_multipart_request(params) - begin - file = File.open params['filePath'], 'r' - text = file.read - rescue StandardError => e - raise RosetteAPIError.new('readMultipartError', e) - end + text = read_multipart_file params['filePath'] boundary = SecureRandom.hex post_body = [] - params.delete 'filePath' - request_file = params.to_json # Add the content data post_body << "--#{boundary}\r\n" post_body << 'Content-Disposition: form-data; name="content"; ' \ - "filename=\"#{File.basename(file)}\"\r\n" + "filename=\"#{File.basename(params['filePath'])}\"\r\n" post_body << "Content-Type: text/plain\r\n\r\n" post_body << text # Add the request data + params.delete 'filePath' + request_file = params.to_json + post_body << "\r\n\r\n--#{boundary}\r\n" post_body << "Content-Disposition: form-data; name=\"request\"\r\n" post_body << "Content-Type: application/json\r\n\r\n" @@ -157,6 +153,17 @@ def prepare_multipart_request(params) [@http_client, request] end + # Reads the content of a file given its path. + # + # Returns the content of the file or raises error if encountered. + def read_multipart_file(file_path) + File.open(file_path, 'r') do |f| + return f.read + end + rescue StandardError => e + raise RosetteAPIError.new('readMultipartError', e) + end + # Sends a GET request to Rosette API. # # Returns JSON response or raises RosetteAPIError if encountered. diff --git a/rosette_api.gemspec b/rosette_api.gemspec index 3045f10..8da8bdb 100644 --- a/rosette_api.gemspec +++ b/rosette_api.gemspec @@ -29,6 +29,4 @@ Gem::Specification.new do |spec| spec.files = Dir['LICENSE', 'README.md', 'lib/**/*', 'examples/**/*'] spec.require_paths = ['lib'] - - spec.add_runtime_dependency('rubysl-securerandom', '~> 2.0') end From 219bf6a7514edef581128484e605bdec46be7b76 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 14:22:50 +0100 Subject: [PATCH 03/24] BX-68618: update package information and README --- README.md | 38 +++++++++++++++++++++++--------------- rosette_api.gemspec | 27 +++++++++++++++------------ 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/README.md b/README.md index 6bd3ba3..abafe87 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,26 @@ - - ---- + + Babel Street Logo + [![Gem Version](https://badge.fury.io/rb/rosette_api.svg)](https://badge.fury.io/rb/rosette_api) -## Rosette API -The Rosette Text Analytics Platform uses natural language processing, statistical modeling, and machine learning to -analyze unstructured and semi-structured text across 364 language-encoding-script combinations, revealing valuable -information and actionable data. Rosette provides endpoints for extracting entities and relationships, translating and -comparing the similarity of names, categorizing and adding linguistic tags to text and more. +# Analytics by Babel Street + +Our product is a full text processing pipeline from data preparation to extracting the most relevant information and +analysis utilizing precise, focused AI that has built-in human understanding. Text Analytics provides foundational +linguistic analysis for identifying languages and relating words. The result is enriched and normalized text for +high-speed search and processing without translation. + +Text Analytics extracts events and entities — people, organizations, and places — from unstructured text and adds the +structure of associating those entities into events that deliver only the necessary information for near real-time +decision making. Accompanying tools shorten the process of training AI models to recognize domain-specific events. + +The product delivers a multitude of ways to sharpen and expand search results. Semantic similarity expands search +beyond keywords to words with the same meaning, even in other languages. Sentiment analysis and topic extraction help +filter results to what’s relevant. -## Rosette API Access -- Rosette Cloud [Sign Up](https://developer.rosette.com/signup) +## Analytics API Access +- Analytics Cloud [Sign Up](https://developer.babelstreet.com/signup) ## Quick Start @@ -20,16 +29,15 @@ comparing the similarity of names, categorizing and adding linguistic tags to te `gem install rosette_api` #### Examples -View small example programs for each Rosette endpoint +View small example programs for each Analytics endpoint in the [examples](https://github.com/rosette-api/ruby/tree/develop/examples) directory. #### Documentation & Support - [Binding API](https://rosette-api.github.io/ruby/) -- [Rosette Platform API](https://developer.rosette.com/features-and-functions) +- [Analytics Platform API](https://documentation.babelstreet.com/analytics) - [Binding Release Notes](https://github.com/rosette-api/ruby/wiki/Release-Notes) -- [Rosette Platform Release Notes](https://support.rosette.com/hc/en-us/articles/360018354971-Release-Notes) -- [Binding/Rosette Platform Compatibility](https://developer.rosette.com/features-and-functions?ruby#) -- [Support](https://support.rosette.com) +- [Analytics Platform Release Notes](https://docs.babelstreet.com/r/Hosted-Services-Release-Notes) +- [Support](https://babelstreet.my.site.com/support/s/contactsupport) - [Binding License: Apache 2.0](https://github.com/rosette-api/ruby/blob/develop/LICENSE) ## Binding Developer Information diff --git a/rosette_api.gemspec b/rosette_api.gemspec index 8da8bdb..add7b68 100644 --- a/rosette_api.gemspec +++ b/rosette_api.gemspec @@ -10,22 +10,25 @@ Gem::Specification.new do |spec| } spec.name = 'rosette_api' - spec.version = '1.27.1' + spec.version = '1.37.0' spec.license = 'Apache-2.0' - spec.summary = 'A Ruby interface for Rosette Text Analytics Platform.' + spec.summary = 'A Ruby interface for Babel Street Analytics Server and Hosted Services' spec.description = - 'The Rosette Text Analytics Platform uses natural language processing, ' \ - 'statistical modeling, and machine learning to analyze unstructured and ' \ - 'semi-structured text across 364 language-encoding-script combinations, ' \ - 'revealing valuable information and actionable data. Rosette provides ' \ - 'endpoints for extracting entities and relationships, translating and ' \ - 'comparing the similarity of names, categorizing and adding linguistic ' \ - 'tags to text and more.' + 'Our product is a full text processing pipeline from data preparation to extracting the most relevant information and' \ + 'analysis utilizing precise, focused AI that has built-in human understanding. Text Analytics provides foundational' \ + 'linguistic analysis for identifying languages and relating words. The result is enriched and normalized text for' \ + 'high-speed search and processing without translation.' \ + 'Text Analytics extracts events and entities — people, organizations, and places — from unstructured text and adds the' \ + 'structure of associating those entities into events that deliver only the necessary information for near real-time' \ + 'decision making. Accompanying tools shorten the process of training AI models to recognize domain-specific events.' \ + 'The product delivers a multitude of ways to sharpen and expand search results. Semantic similarity expands search' \ + 'beyond keywords to words with the same meaning, even in other languages. Sentiment analysis and topic extraction help' \ + 'filter results to what’s relevant.' - spec.authors = ['Basis Technology Corp'] - spec.email = 'support@rosette.com' - spec.homepage = 'https://developer.rosette.com/' + spec.authors = ['Analytics by Babel Street'] + spec.email = 'analyticssupport@babelstreet.com' + spec.homepage = 'https://developer.babelstreet.com/' spec.files = Dir['LICENSE', 'README.md', 'lib/**/*', 'examples/**/*'] spec.require_paths = ['lib'] From b993e30548518aeee6eeff12b0dbdbfa98d29bc0 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 14:37:51 +0100 Subject: [PATCH 04/24] BX-68618: update rubocop spec --- .rubocop_todo.yml | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index e4e3007..546a191 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -1,6 +1,6 @@ # This configuration was generated by # `rubocop --auto-gen-config` -# on 2024-01-11 22:13:12 UTC using RuboCop version 1.59.0. +# on 2026-03-05 13:36:13 UTC using RuboCop version 1.85.1. # The point is for the user to remove these configuration records # one by one as the offenses are removed from the code base. # Note that changes in the inspected code, or installation of new @@ -9,7 +9,7 @@ # Offense count: 4 # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 45 + Max: 43 # Offense count: 10 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. @@ -20,17 +20,17 @@ Metrics/BlockLength: # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 232 + Max: 229 # Offense count: 1 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: Max: 8 -# Offense count: 11 +# Offense count: 10 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: - Max: 51 + Max: 46 # Offense count: 1 # Configuration parameters: CountKeywordArgs, MaxOptionalParameters. @@ -43,6 +43,7 @@ Metrics/ParameterLists: # AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS Naming/FileName: Exclude: + - 'Rakefile.rb' - 'examples/morphology_compound-components.rb' - 'examples/morphology_han-readings.rb' - 'examples/morphology_parts-of-speech.rb' @@ -63,15 +64,15 @@ Style/CommentedKeyword: - 'lib/rosette_api_error.rb' # Offense count: 14 -# This cop supports safe autocorrection (--autocorrect). +# This cop supports unsafe autocorrection (--autocorrect-all). # Configuration parameters: AllowedCompactTypes. # SupportedStyles: compact, exploded Style/RaiseArgs: EnforcedStyle: compact -# Offense count: 11 +# Offense count: 18 # This cop supports safe autocorrection (--autocorrect). -# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, AllowedPatterns. +# Configuration parameters: AllowHeredoc, AllowURI, AllowQualifiedName, URISchemes, AllowRBSInlineAnnotation, AllowCopDirectives, AllowedPatterns, SplitStrings. # URISchemes: http, https Layout/LineLength: Max: 772 From 2e2be408d0e38b2f21466304d5d1d38a2ee47cf3 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 15:49:57 +0100 Subject: [PATCH 05/24] BX-68618: update ruby versions to test with, add CVE check instructions, unlock dependency versions --- CI.Jenkinsfile | 2 +- DEVELOPER.md | 34 +++++++++++++++++++++++++++++----- Gemfile | 7 +++---- LICENSE | 2 +- examples/README.md | 4 ++-- 5 files changed, 36 insertions(+), 13 deletions(-) diff --git a/CI.Jenkinsfile b/CI.Jenkinsfile index 0cfa02d..980f667 100644 --- a/CI.Jenkinsfile +++ b/CI.Jenkinsfile @@ -1,6 +1,6 @@ -def versions = [3.0, 3.1, 3.2, 3.3] +def versions = [3.2, 3.3, 3.4, 4.0] def runSonnarForPythonVersion(sourceDir, ver){ mySonarOpts="-Dsonar.sources=/source -Dsonar.host.url=${env.SONAR_HOST_URL} -Dsonar.login=${env.SONAR_AUTH_TOKEN}" diff --git a/DEVELOPER.md b/DEVELOPER.md index 7551882..e574085 100644 --- a/DEVELOPER.md +++ b/DEVELOPER.md @@ -4,7 +4,7 @@ Modify `.rubocop_todo.yml` as you fix issues. Generate a new config file with `rubocop --auto-gen-config` as needed. ``` -docker run -it -v $(pwd):/source --entrypoint bash ruby:3.3-slim +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim apt-get update apt-get install -y gcc make @@ -14,12 +14,32 @@ rubocop ``` +#### Check dependencies for CVEs + +This uses `bundler-audit`, which checks your `Gemfile.lock` against the RubySec advisory DB. + +``` +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim +apt-get update +apt-get install -y gcc make git ca-certificates libyaml-dev + +cd /source +bundle install + +gem install bundler-audit +bundle audit update +bundle audit check --verbose + +``` + + + #### Run tests locally ``` -docker run -it -v $(pwd):/source --entrypoint bash ruby:3.3-slim +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim apt-get update -apt-get install -y gcc make +apt-get install -y gcc make libyaml-dev gem install rspec cd /source @@ -31,7 +51,9 @@ rspec tests #### Run a single example ``` -docker run -it -v $(pwd):/source --entrypoint bash ruby:3.3-slim +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim +apt-get update +apt-get install -y gcc make libyaml-dev cd /source bundle install @@ -47,7 +69,9 @@ ruby ping.rb ${API_KEY} #### Run all examples ``` -docker run -it -v $(pwd):/source --entrypoint bash ruby:3.3-slim +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim +apt-get update +apt-get install -y gcc make libyaml-dev cd /source bundle install diff --git a/Gemfile b/Gemfile index b65bfbe..15e4d0d 100644 --- a/Gemfile +++ b/Gemfile @@ -2,10 +2,9 @@ source 'https://rubygems.org' -gem 'rdoc', '6.6.2' -gem 'rubysl-securerandom', '2.0.0' +gem 'rdoc' -gem 'rspec', '3.12.0', group: [:test] +gem 'rspec', group: [:test] gem 'simplecov', require: false, group: :test gem 'simplecov_json_formatter', require: false, group: :test -gem 'webmock', '3.19.1', group: [:test] +gem 'webmock', group: [:test] diff --git a/LICENSE b/LICENSE index b31b71a..cc2be2e 100644 --- a/LICENSE +++ b/LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2016-2024 Basis Technology Corporation. +Copyright (c) 2016-2026 Basis Technology Corporation. Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. diff --git a/examples/README.md b/examples/README.md index 1ecfa40..ee403e3 100644 --- a/examples/README.md +++ b/examples/README.md @@ -13,7 +13,7 @@ A note on prerequisites. Rosette API only suports TLS 1.2 so ensure your toolcha ``` git clone git@github.com:rosette-api/ruby.git cd ruby -docker run -it -v $(pwd):/source --entrypoint bash ruby:3.3-slim +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim gem install rosette_api @@ -25,7 +25,7 @@ ruby ping.rb $API_KEY ``` git clone git@github.com:rosette-api/ruby.git cd ruby -docker run -it -v $(pwd):/source --entrypoint bash ruby:3.3-slim +docker run -it -v $(pwd):/source --entrypoint bash ruby:3.4-slim cd /source gem build rosette_api.gemspec From c6c44c7f1f03612b83bf5bcfa8f53457d4f40fbc Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 16:42:12 +0100 Subject: [PATCH 06/24] BX-68618: psych install/update fix --- CI.Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI.Jenkinsfile b/CI.Jenkinsfile index 980f667..fa4edb2 100644 --- a/CI.Jenkinsfile +++ b/CI.Jenkinsfile @@ -43,7 +43,7 @@ def runSonnarForPythonVersion(sourceDir, ver){ apt-get update -qq && \ echo && \ echo [INFO] Installing required OS packages. && \ - apt-get -qq install -y gcc make wget unzip > /dev/null && \ + apt-get -qq install -y gcc make wget unzip libyaml-dev > /dev/null && \ echo && \ echo [INFO] Installing gems needed for CI. && \ gem install --silent --quiet bundler rspec rubocop && \ From be2eedb2bd9c613ebbecbc6b666aed900c299b2d Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 16:45:29 +0100 Subject: [PATCH 07/24] BX-68618: use uid and gid for repermissioning --- CI.Jenkinsfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CI.Jenkinsfile b/CI.Jenkinsfile index fa4edb2..c9624d4 100644 --- a/CI.Jenkinsfile +++ b/CI.Jenkinsfile @@ -70,7 +70,7 @@ def runSonnarForPythonVersion(sourceDir, ver){ ${sonarExec} && \ echo && \ echo [INFO] Re-permission files for cleanup. && \ - chown -R jenkins:jenkins /source\"" + chown -R 9960:9960 /source\"" } node ("docker-light") { From ead28be5ad00f7d36e0b183b6c62b04694e44b40 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Thu, 5 Mar 2026 17:58:10 +0100 Subject: [PATCH 08/24] BX-68618: update sonar version --- CI.Jenkinsfile | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/CI.Jenkinsfile b/CI.Jenkinsfile index c9624d4..3a75ca3 100644 --- a/CI.Jenkinsfile +++ b/CI.Jenkinsfile @@ -15,12 +15,13 @@ def runSonnarForPythonVersion(sourceDir, ver){ // Only run Sonar once. // Check for new versions at https://binaries.sonarsource.com/?prefix=Distribution/sonar-scanner-cli/ + sonarScannerVersion = "6.2.1.4610-linux-x64" if(ver == 3.3) { sonarExec="cd /root/ && \ - wget -q https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-4.8.1.3023-linux.zip && \ - unzip -q sonar-scanner-cli-4.8.1.3023-linux.zip && \ + wget -q https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${sonarScannerVersion}.zip && \ + unzip -q sonar-scanner-cli-${sonarScannerVersion}.zip && \ cd /source && \ - /root/sonar-scanner-4.8.1.3023-linux/bin/sonar-scanner ${mySonarOpts}" + /root/sonar-scanner-${sonarScannerVersion}/bin/sonar-scanner ${mySonarOpts}" } else { sonarExec="echo Skipping Sonar for this version." } From accadc8b6f3c5107e78624c56e3ebb20fe3717bd Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 09:34:53 +0100 Subject: [PATCH 09/24] BX-68618: fixing coverage --- CI.Jenkinsfile | 2 +- README.md | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/CI.Jenkinsfile b/CI.Jenkinsfile index 3a75ca3..cc7399a 100644 --- a/CI.Jenkinsfile +++ b/CI.Jenkinsfile @@ -3,7 +3,7 @@ def versions = [3.2, 3.3, 3.4, 4.0] def runSonnarForPythonVersion(sourceDir, ver){ - mySonarOpts="-Dsonar.sources=/source -Dsonar.host.url=${env.SONAR_HOST_URL} -Dsonar.login=${env.SONAR_AUTH_TOKEN}" + mySonarOpts="-Dsonar.sources=/source -Dsonar.host.url=${env.SONAR_HOST_URL} -Dsonar.login=${env.SONAR_AUTH_TOKEN} -Dsonar.ruby.coverage.reportPaths=coverage/coverage.json" if("${env.CHANGE_ID}" != "null"){ mySonarOpts = "$mySonarOpts -Dsonar.pullrequest.key=${env.CHANGE_ID} -Dsonar.pullrequest.branch=${env.BRANCH_NAME}" } else { diff --git a/README.md b/README.md index abafe87..3e6b740 100644 --- a/README.md +++ b/README.md @@ -2,10 +2,10 @@ Babel Street Logo -[![Gem Version](https://badge.fury.io/rb/rosette_api.svg)](https://badge.fury.io/rb/rosette_api) - # Analytics by Babel Street +[![Gem Version](https://badge.fury.io/rb/rosette_api.svg)](https://badge.fury.io/rb/rosette_api) + Our product is a full text processing pipeline from data preparation to extracting the most relevant information and analysis utilizing precise, focused AI that has built-in human understanding. Text Analytics provides foundational linguistic analysis for identifying languages and relating words. The result is enriched and normalized text for From 8486d1bc801d8a5ff37dc080ba03f7464788b918 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 11:25:07 +0100 Subject: [PATCH 10/24] BX-68618: remove multipart test file at the end of the test --- examples/multipart_language_file.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/examples/multipart_language_file.rb b/examples/multipart_language_file.rb index 99cbf35..d32c519 100644 --- a/examples/multipart_language_file.rb +++ b/examples/multipart_language_file.rb @@ -1,6 +1,7 @@ # frozen_string_literal: true require 'rosette_api' +require 'fileutils' api_key, url = ARGV @@ -22,4 +23,6 @@ printf('Rosette API Error (%s): %s', status_code: e.status_code, message: e.message) +ensure + FileUtils.rm_f(file_path) end From 7fbab2c940e78ae4b1cda3c05cf75bd86edc990e Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 11:41:20 +0100 Subject: [PATCH 11/24] BX-68618: name and address similarity parameters option --- .rubocop_todo.yml | 3 + lib/address_similarity_parameters.rb | 12 +++- lib/name_similarity_parameters.rb | 21 +++--- tests/tests_spec.rb | 100 +++++++++++++++++++-------- 4 files changed, 98 insertions(+), 38 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 546a191..14f6196 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -16,6 +16,9 @@ Metrics/AbcSize: # AllowedMethods: refine Metrics/BlockLength: Max: 786 + #TODO check rubocop-rspec extension + Exclude: + - 'tests/tests_spec.rb' # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. diff --git a/lib/address_similarity_parameters.rb b/lib/address_similarity_parameters.rb index 18cf882..44dcdca 100644 --- a/lib/address_similarity_parameters.rb +++ b/lib/address_similarity_parameters.rb @@ -11,9 +11,13 @@ class AddressSimilarityParameters # Address to be compared to address1 attr_accessor :address2 - def initialize(address1, address2) # :notnew: + # Parameters map sent to the API (optional, should be a hash) + attr_accessor :parameters + + def initialize(address1, address2, address_parameters = nil) # :notnew: @address1 = address1 @address2 = address2 + @parameters = address_parameters end # Validates the parameters by checking if address1 and address2 are instances @@ -24,6 +28,9 @@ def validate_params a2_msg = 'address2 option can only be an instance of an AddressParameter or a String' raise BadRequestError.new(a2_msg) if [String, AddressParameter].none? { |clazz| @address2.is_a? clazz } + + opt_msg = 'parameters can only be an instance of a Hash' + raise BadRequestError.new(opt_msg) if @parameters && !(@parameters.is_a? Hash) end # Converts this class to Hash with its keys in lower CamelCase. @@ -42,7 +49,8 @@ def load_params def to_hash { address1: @address1.is_a?(AddressParameter) ? @address1.load_param : @address1, - address2: @address2.is_a?(AddressParameter) ? @address2.load_param : @address2 + address2: @address2.is_a?(AddressParameter) ? @address2.load_param : @address2, + parameters: @parameters } end end diff --git a/lib/name_similarity_parameters.rb b/lib/name_similarity_parameters.rb index 6efca25..74dc546 100644 --- a/lib/name_similarity_parameters.rb +++ b/lib/name_similarity_parameters.rb @@ -8,22 +8,25 @@ class NameSimilarityParameters # genre to categorize the input data attr_accessor :genre - # Rosette API options (optional, should be a hash) - attr_accessor :rosette_options + + # Parameters map sent to the API (optional, should be a hash) + attr_accessor :parameters + # Name to be compared to name2 attr_accessor :name1 # Name to be compared to name1 attr_accessor :name2 - def initialize(name1, name2, options = {}) # :notnew: + def initialize(name1, name2, match_parameters = nil, options = {}) # :notnew: options = { - genre: nil, - rosette_options: nil + genre: nil }.update options @genre = options[:genre] + @name1 = name1 @name2 = name2 - @rosette_options = options[:rosette_options] + + @parameters = match_parameters end # Validates the parameters by checking if name1 and name2 are instances of @@ -35,8 +38,8 @@ def validate_params n2_msg = 'name2 option can only be an instance of a String or NameParameter' raise BadRequestError.new(n2_msg) if [String, NameParameter].none? { |clazz| @name2.is_a? clazz } - opt_msg = 'rosette_options can only be an instance of a Hash' - raise BadRequestError.new(opt_msg) if @rosette_options && !(@rosette_options.is_a? Hash) + opt_msg = 'parameters can only be an instance of a Hash' + raise BadRequestError.new(opt_msg) if @parameters && !(@parameters.is_a? Hash) end # Converts this class to Hash with its keys in lower CamelCase. @@ -57,7 +60,7 @@ def to_hash genre: @genre, name1: @name1.is_a?(NameParameter) ? @name1.load_param : @name1, name2: @name2.is_a?(NameParameter) ? @name2.load_param : @name2, - options: @rosette_options + parameters: @parameters } end end diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index d7ce909..a8721d4 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -358,11 +358,12 @@ describe '.name_similarity' do before do - name_similarity_json = { name1: 'Michael Jackson', - name2: '迈克尔·杰克逊' }.to_json stub_request(:post, 'https://api.rosette.com/rest/v1/name-similarity') .with( - body: name_similarity_json, + body: hash_including( + name1: 'Michael Jackson', + name2: '迈克尔·杰克逊' + ), headers: { 'Accept' => 'application/json', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', @@ -383,6 +384,21 @@ expect(response).instance_of? Hash end + it 'sends parameters in the request body when provided' do + params = NameSimilarityParameters.new( + 'Michael Jackson', + '迈克尔·杰克逊', + { finalBias: '0.0003' } + ) + + RosetteAPI.new('0123456789').get_name_similarity(params) + + expect( + a_request(:post, 'https://api.rosette.com/rest/v1/name-similarity') + .with(body: hash_including(parameters: { finalBias: '0.0003' })) + ).to have_been_made.once + end + it 'badRequestFormat: name1 option can only be an instance of a String..' do params = NameSimilarityParameters.new(123, 'Michael Jackson') expect { RosetteAPI.new('0123456789').get_name_similarity(params) } @@ -769,35 +785,65 @@ describe '.address_similarity' do before do - address_similarity_json = { - address1: { - houseNumber: '1600', - road: 'Pennsylvania Ave NW', - city: 'Washington', - state: 'DC' - }, - address2: { - houseNumber: '1600', - road: 'Pennsilvana Avenue', - city: 'Washington', - state: 'D.C.' - } - }.to_json stub_request(:post, 'https://api.rosette.com/rest/v1/address-similarity') - .with(body: address_similarity_json, - headers: { - 'Accept' => 'application/json', - 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', - 'Content-Type' => 'application/json', - 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', - 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' - }) + .with( + body: hash_including( + address1: { + houseNumber: '1600', + road: 'Pennsylvania Ave NW', + city: 'Washington', + state: 'DC' + }, + address2: { + houseNumber: '1600', + road: 'Pennsilvana Avenue', + city: 'Washington', + state: 'D.C.' + } + ), + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-Rosetteapi-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.27.1' + } + ) .to_return(status: 200, body: '{"test": "address-similarity"}', headers: {}) end + + it 'sends parameters in the request body when provided' do + address1 = AddressParameter.new( + house_number: '1600', + road: 'Pennsylvania Ave NW', + city: 'Washington', + state: 'DC' + ) + address2 = AddressParameter.new( + house_number: '1600', + road: 'Pennsilvana Avenue', + city: 'Washington', + state: 'D.C.' + ) + + params = AddressSimilarityParameters.new( + address1, + address2, + { someOption: true } + ) + + RosetteAPI.new('0123456789').get_address_similarity(params) + + expect( + a_request(:post, 'https://api.rosette.com/rest/v1/address-similarity') + .with(body: hash_including(parameters: { someOption: true })) + ).to have_been_made.once + end + it 'test address similarity' do address1 = AddressParameter.new( house_number: '1600', From 8721762a1683778a350a5d893102e70e480d2ba5 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 12:19:53 +0100 Subject: [PATCH 12/24] BX-68618: add events support --- .rubocop_todo.yml | 2 +- examples/events.rb | 22 +++++++++++++++++++++ lib/rosette_api.rb | 48 ++++++++++++++++++++++++++++++++------------- tests/tests_spec.rb | 26 ++++++++++++++++++++++++ 4 files changed, 83 insertions(+), 15 deletions(-) create mode 100644 examples/events.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 14f6196..4148967 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -23,7 +23,7 @@ Metrics/BlockLength: # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 229 + Max: 239 # Offense count: 1 # Configuration parameters: AllowedMethods, AllowedPatterns. diff --git a/examples/events.rb b/examples/events.rb new file mode 100644 index 0000000..6fd8bee --- /dev/null +++ b/examples/events.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +require 'rosette_api' + +api_key, url = ARGV + +rosette_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end + +events_text_data = 'Bill Gates went to the store.' +begin + params = DocumentParameters.new(content: events_text_data) + response = rosette_api.get_events(params) + puts JSON.pretty_generate(response) +rescue RosetteAPIError => e + printf('Rosette API Error (%s): %s', + status_code: e.status_code, + message: e.message) +end diff --git a/lib/rosette_api.rb b/lib/rosette_api.rb index 81cb1a3..5115cf5 100644 --- a/lib/rosette_api.rb +++ b/lib/rosette_api.rb @@ -11,37 +11,39 @@ require_relative 'bad_request_format_error' require 'logger' -# This class allows you to access all Rosette API endpoints. +# This class allows you to access all Analytics API endpoints. class RosetteAPI # Version of Ruby binding BINDING_VERSION = '1.27.1' - # Rosette API language endpoint + # API language endpoint LANGUAGE_ENDPOINT = '/language' - # Rosette API morphology endpoint + # API morphology endpoint MORPHOLOGY_ENDPOINT = '/morphology' - # Rosette API entities endpoint + # API entities endpoint ENTITIES_ENDPOINT = '/entities' - # Rosette API categories endpoint + # API events endpoint + EVENTS_ENDPOINT = '/events' + # API categories endpoint CATEGORIES_ENDPOINT = '/categories' - # Rosette API relationships endpoint + # API relationships endpoint RELATIONSHIPS_ENDPOINT = '/relationships' - # Rosette API sentiment endpoint + # API sentiment endpoint SENTIMENT_ENDPOINT = '/sentiment' # Name Deduplication endpoint NAME_DEDUPLICATION_ENDPOINT = '/name-deduplication' - # Rosette API name-translation endpoint + # API name-translation endpoint NAME_TRANSLATION_ENDPOINT = '/name-translation' - # Rosette API name-similarity endpoint + # API name-similarity endpoint NAME_SIMILARITY_ENDPOINT = '/name-similarity' - # Rosette API address-similarity endpoint + # API address-similarity endpoint ADDRESS_SIMILARITY_ENDPOINT = '/address-similarity' - # Rosette API tokens endpoint + # API tokens endpoint TOKENS_ENDPOINT = '/tokens' - # Rosette API sentences endpoint + # API sentences endpoint SENTENCES_ENDPOINT = '/sentences' - # Rosette API info endpoint + # API info endpoint INFO = '/info' - # Rosette API ping endpoint + # API ping endpoint PING = '/ping' # Text Embedding endpoint (deprecated) TEXT_EMBEDDING = '/text-embedding' @@ -501,6 +503,24 @@ def get_similar_terms(params) .send_post_request end + # Returns the events of the input + # + # ==== Attributes + # + # * +params+ - DocumentParameters helps to build the request body in + # RequestBuilder. + # + # Returns the events of the input + def get_events(params) + check_params params + + params = params.load_params + + RequestBuilder.new(@user_key, @alternate_url + EVENTS_ENDPOINT, + @http_client, BINDING_VERSION, params, @url_parameters) + .send_post_request + end + # Gets information about the Rosette API, returns name, build number # and build time. def info diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index a8721d4..cd26a3c 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -294,6 +294,32 @@ end end + describe '.get_events' do + before do + events_json = { contentUri: 'http://google.com' }.to_json + stub_request(:post, 'https://api.rosette.com/rest/v1/events') + .with( + body: events_json, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-Rosetteapi-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.27.1' + } + ) + .to_return(status: 200, body: '{"test": "events"}', headers: {}) + end + + it 'test events' do + params = DocumentParameters.new + params.content_uri = 'http://google.com' + response = RosetteAPI.new('0123456789').get_events(params) + expect(response).instance_of? Hash + end + end describe '.get_relationships' do before do stub_request(:post, 'https://api.rosette.com/rest/v1/relationships') From 4b5f7fafc680eb16776070ffa07b12659b47a1a7 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 12:20:13 +0100 Subject: [PATCH 13/24] BX-68618: add missing test cases --- tests/tests_spec.rb | 55 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index cd26a3c..6817ce2 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -320,6 +320,61 @@ expect(response).instance_of? Hash end end + + describe '.get_sentiment' do + before do + sentiment_json = { contentUri: 'http://google.com' }.to_json + stub_request(:post, 'https://api.rosette.com/rest/v1/sentiment') + .with( + body: sentiment_json, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-Rosetteapi-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.27.1' + } + ) + .to_return(status: 200, body: '{"test": "sentiment"}', headers: {}) + end + + it 'test sentiment' do + params = DocumentParameters.new + params.content_uri = 'http://google.com' + response = RosetteAPI.new('0123456789').get_sentiment(params) + expect(response).instance_of? Hash + end + end + + describe '.get_text_embedding' do + before do + text_embedding_json = { contentUri: 'http://google.com' }.to_json + stub_request(:post, 'https://api.rosette.com/rest/v1/text-embedding') + .with( + body: text_embedding_json, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-Rosetteapi-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.27.1' + } + ) + .to_return(status: 200, body: '{"test": "text-embedding"}', headers: {}) + end + + it 'test text embedding' do + params = DocumentParameters.new + params.content_uri = 'http://google.com' + response = RosetteAPI.new('0123456789').get_text_embedding(params) + expect(response).instance_of? Hash + end + end + describe '.get_relationships' do before do stub_request(:post, 'https://api.rosette.com/rest/v1/relationships') From 638501727d2d8fe0a0f2c1072e7a5546a085c417 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 13:19:17 +0100 Subject: [PATCH 14/24] BX-68618: Do not serialize genre for requests --- lib/document_parameters.rb | 1 - lib/name_similarity_parameters.rb | 1 - lib/name_translation_parameters.rb | 1 - 3 files changed, 3 deletions(-) diff --git a/lib/document_parameters.rb b/lib/document_parameters.rb index 1bdf941..734a7b8 100644 --- a/lib/document_parameters.rb +++ b/lib/document_parameters.rb @@ -78,7 +78,6 @@ def to_hash content: @content, content_uri: @content_uri, file_path: @file_path, - genre: @genre, language: @language, options: @rosette_options, custom_headers: @custom_headers diff --git a/lib/name_similarity_parameters.rb b/lib/name_similarity_parameters.rb index 74dc546..e27353e 100644 --- a/lib/name_similarity_parameters.rb +++ b/lib/name_similarity_parameters.rb @@ -57,7 +57,6 @@ def load_params # Returns the new Hash. def to_hash { - genre: @genre, name1: @name1.is_a?(NameParameter) ? @name1.load_param : @name1, name2: @name2.is_a?(NameParameter) ? @name2.load_param : @name2, parameters: @parameters diff --git a/lib/name_translation_parameters.rb b/lib/name_translation_parameters.rb index aaeb0c1..ab5440d 100644 --- a/lib/name_translation_parameters.rb +++ b/lib/name_translation_parameters.rb @@ -73,7 +73,6 @@ def load_params def to_hash { entity_type: @entity_type, - genre: @genre, name: @name, options: @rosette_options, source_language_of_origin: @source_language_of_origin, From b50fb99d31e0548438a82f2642e7156a7ade5e3e Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 14:15:38 +0100 Subject: [PATCH 15/24] BX-68618: Add name translation maximum results --- lib/name_translation_parameters.rb | 13 ++++++++- tests/tests_spec.rb | 43 ++++++++++++++++++++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/lib/name_translation_parameters.rb b/lib/name_translation_parameters.rb index ab5440d..70e9dad 100644 --- a/lib/name_translation_parameters.rb +++ b/lib/name_translation_parameters.rb @@ -26,11 +26,14 @@ class NameTranslationParameters attr_accessor :target_scheme # ISO 15924 code of name's script (optional) attr_accessor :target_script + # Maximum number of results to return (optional) + attr_accessor :maximum_results def initialize(name, target_language, options = {}) # :notnew: options = { entity_type: nil, genre: nil, + maximum_results: nil, rosette_options: nil, source_language_of_origin: nil, source_language_of_use: nil, @@ -41,6 +44,7 @@ def initialize(name, target_language, options = {}) # :notnew: @name = name @entity_type = options[:entity_type] @genre = options[:genre] + @maximum_results = options[:maximum_results] @rosette_options = options[:rosette_options] @source_language_of_origin = options[:source_language_of_origin] @source_language_of_use = options[:source_language_of_use] @@ -55,6 +59,12 @@ def initialize(name, target_language, options = {}) # :notnew: def validate_params msg = 'rosette_options can only be an instance of a Hash' raise BadRequestError.new(msg) if @rosette_options && !(@rosette_options.is_a? Hash) + + max_msg = 'maximum_results can only be an instance of an Integer' + raise BadRequestError.new(max_msg) if @maximum_results && !(@maximum_results.is_a? Integer) + + max_range_msg = 'maximum_results must be greater than or equal to 0' + raise BadRequestError.new(max_range_msg) if @maximum_results&.negative? end # Converts this class to Hash with its keys in lower CamelCase. @@ -80,7 +90,8 @@ def to_hash source_script: @source_script, target_language: @target_language, target_scheme: @target_scheme, - target_script: @target_script + target_script: @target_script, + maximum_results: @maximum_results } end end diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index 6817ce2..d7b47a5 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -421,7 +421,29 @@ .to_return(status: 200, body: '{"test": "name-translation"}', headers: {}) + + name_translation_max_results_json = { name: 'معمر محمد أبو منيار القذاف', + targetLanguage: 'eng', + targetScript: 'Latn', + maximumResults: 5 }.to_json + stub_request(:post, 'https://api.rosette.com/rest/v1/name-translation') + .with( + body: name_translation_max_results_json, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-Rosetteapi-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.27.1' + } + ) + .to_return(status: 200, + body: '{"test": "name-translation"}', + headers: {}) end + it 'test name translation' do params = NameTranslationParameters.new('معمر محمد أبو منيار القذاف' .encode('UTF-8'), 'eng') @@ -430,6 +452,27 @@ expect(response).instance_of? Hash end + it 'test name translation with maximumResults' do + params = NameTranslationParameters.new( + 'معمر محمد أبو منيار القذاف'.encode('UTF-8'), + 'eng', + maximum_results: 5 + ) + params.target_script = 'Latn' + response = RosetteAPI.new('0123456789').get_name_translation(params) + expect(response).instance_of? Hash + end + + it 'badRequest: maximum_results must be greater than or equal to 0' do + params = NameTranslationParameters.new( + 'معمر محمد أبو منيار القذاف'.encode('UTF-8'), + 'eng', + maximum_results: -1 + ) + expect { RosetteAPI.new('0123456789').get_name_translation(params) } + .to raise_error(BadRequestError) + end + it 'badRequest: Expects NameTranslationParameters type as an argument' do params = NameSimilarityParameters.new('Michael Jackson', '迈克尔·杰克逊') expect { RosetteAPI.new('0123456789').get_name_translation(params) } From c766ff68d44d451b36bd4624f173a913eb8eee90 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 14:50:21 +0100 Subject: [PATCH 16/24] BX-68618: Add gender to name parameter --- lib/name_parameter.rb | 18 +++++++++++++++++- tests/tests_spec.rb | 12 ++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/lib/name_parameter.rb b/lib/name_parameter.rb index 9778e22..61d18d5 100644 --- a/lib/name_parameter.rb +++ b/lib/name_parameter.rb @@ -8,19 +8,34 @@ class NameParameter attr_accessor :language # ISO 15924 code of the name's script (optional) attr_accessor :script + # Name's gender (male, female, nonbinary) (optional) + attr_accessor :gender # Name to be analyzed attr_accessor :text + VALID_GENDERS = %w[male female nonbinary].freeze + def initialize(text, options = {}) # :notnew: options = { entity_type: nil, language: nil, - script: nil + script: nil, + gender: nil }.update options @text = text @entity_type = options[:entity_type] @language = options[:language] @script = options[:script] + @gender = options[:gender] + + validate_gender + end + + def validate_gender + return if @gender.nil? + return if VALID_GENDERS.include?(@gender) + + raise ArgumentError.new("gender must be one of: #{VALID_GENDERS.join(', ')}") end # Converts this class to Hash with its keys in lower CamelCase. @@ -40,6 +55,7 @@ def to_hash entity_type: @entity_type, language: @language, script: @script, + gender: @gender, text: @text } end diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index d7b47a5..53f57a0 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -1019,4 +1019,16 @@ .to raise_error(BadRequestError) end end + + describe 'NameParameter gender' do + it 'serializes gender when valid' do + name = NameParameter.new('Alex Smith', gender: 'nonbinary') + expect(name.load_param).to include('gender' => 'nonbinary') + end + + it 'raises when gender is invalid' do + expect { NameParameter.new('Alex Smith', gender: 'unknown') } + .to raise_error(ArgumentError) + end + end end From 5a077881c065eef1f7818cb343e7ee39fe751e8f Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 14:54:09 +0100 Subject: [PATCH 17/24] BX-68618: case insensitive gender validation --- lib/name_parameter.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/name_parameter.rb b/lib/name_parameter.rb index 61d18d5..bb04a18 100644 --- a/lib/name_parameter.rb +++ b/lib/name_parameter.rb @@ -33,7 +33,9 @@ def initialize(text, options = {}) # :notnew: def validate_gender return if @gender.nil? - return if VALID_GENDERS.include?(@gender) + + normalized = @gender.to_s.downcase + return if VALID_GENDERS.include?(normalized) raise ArgumentError.new("gender must be one of: #{VALID_GENDERS.join(', ')}") end From d7c32a668ed7858432b651219623cfe629ba251d Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 15:41:49 +0100 Subject: [PATCH 18/24] BX-68618: rebranding changes --- .rubocop_todo.yml | 4 +- examples/address_similarity.rb | 12 +- examples/categories.rb | 12 +- examples/entities.rb | 12 +- examples/events.rb | 12 +- examples/info.rb | 12 +- examples/language.rb | 12 +- examples/language_multilingual.rb | 12 +- examples/morphology_complete.rb | 12 +- examples/morphology_compound-components.rb | 12 +- examples/morphology_han-readings.rb | 12 +- examples/morphology_lemmas.rb | 12 +- examples/morphology_parts-of-speech.rb | 12 +- examples/multipart_language_file.rb | 12 +- examples/name_deduplication.rb | 12 +- examples/name_similarity.rb | 12 +- examples/name_translation.rb | 12 +- examples/ping.rb | 12 +- examples/relationships.rb | 12 +- examples/semantic_vectors.rb | 12 +- examples/sentences.rb | 12 +- examples/sentiment.rb | 12 +- examples/similar_terms.rb | 12 +- examples/syntax_dependencies.rb | 12 +- examples/tokens.rb | 12 +- examples/topics.rb | 12 +- examples/transliteration.rb | 12 +- lib/address_parameter.rb | 2 +- lib/address_similarity_parameters.rb | 2 +- lib/bad_request_error.rb | 2 +- lib/bad_request_format_error.rb | 2 +- lib/document_parameters.rb | 4 +- lib/name_deduplication_parameters.rb | 4 +- lib/name_parameter.rb | 2 +- lib/name_similarity_parameters.rb | 2 +- lib/name_translation_parameters.rb | 4 +- lib/request_builder.rb | 44 ++-- lib/rosette_api.rb | 14 +- lib/rosette_api_error.rb | 6 +- sonar-project.properties | 2 - tests/tests_spec.rb | 232 +++++++++++++-------- 41 files changed, 347 insertions(+), 291 deletions(-) diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index 4148967..bd2822d 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -9,7 +9,7 @@ # Offense count: 4 # Configuration parameters: AllowedMethods, AllowedPatterns, CountRepeatedAttributes. Metrics/AbcSize: - Max: 43 + Max: 50 # Offense count: 10 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. @@ -33,7 +33,7 @@ Metrics/CyclomaticComplexity: # Offense count: 10 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. Metrics/MethodLength: - Max: 46 + Max: 50 # Offense count: 1 # Configuration parameters: CountKeywordArgs, MaxOptionalParameters. diff --git a/examples/address_similarity.rb b/examples/address_similarity.rb index 32d23f7..31615cc 100644 --- a/examples/address_similarity.rb +++ b/examples/address_similarity.rb @@ -4,11 +4,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end begin address1 = AddressParameter.new( @@ -20,7 +20,7 @@ ) address2 = '160 Pennsilvana Avenue, Washington, D.C., 20500' params = AddressSimilarityParameters.new(address1, address2) - response = rosette_api.get_address_similarity(params) + response = analytics_api.get_address_similarity(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/categories.rb b/examples/categories.rb index b9f5de1..d887088 100644 --- a/examples/categories.rb +++ b/examples/categories.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end categories_text_data = 'If you are a fan of the British television series Downton Abbey and you are planning to be in New York anytime before April 2nd, there is a perfect stop for you while in town.' begin params = DocumentParameters.new(content: categories_text_data) - response = rosette_api.get_categories(params) + response = analytics_api.get_categories(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/entities.rb b/examples/entities.rb index 0d6386f..e47d4b4 100644 --- a/examples/entities.rb +++ b/examples/entities.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end entities_text_data = 'The Securities and Exchange Commission today announced the leadership of the agency\'s trial unit. Bridget Fitzpatrick has been named Chief Litigation Counsel of the SEC and David Gottesman will continue to serve as the agency\'s Deputy Chief Litigation Counsel. Since December 2016, Ms. Fitzpatrick and Mr. Gottesman have served as Co-Acting Chief Litigation Counsel. In that role, they were jointly responsible for supervising the trial unit at the agency\'s Washington D.C. headquarters as well as coordinating with litigators in the SEC\'s 11 regional offices around the country.' begin params = DocumentParameters.new(content: entities_text_data) - response = rosette_api.get_entities(params) + response = analytics_api.get_entities(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/events.rb b/examples/events.rb index 6fd8bee..c2836fd 100644 --- a/examples/events.rb +++ b/examples/events.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end events_text_data = 'Bill Gates went to the store.' begin params = DocumentParameters.new(content: events_text_data) - response = rosette_api.get_events(params) + response = analytics_api.get_events(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/info.rb b/examples/info.rb index feae303..932b0bb 100644 --- a/examples/info.rb +++ b/examples/info.rb @@ -4,13 +4,13 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end -response = rosette_api.info +response = analytics_api.info begin puts JSON.pretty_generate(response) rescue RosetteAPIError => e diff --git a/examples/language.rb b/examples/language.rb index 74e43d4..4c42e67 100644 --- a/examples/language.rb +++ b/examples/language.rb @@ -4,17 +4,17 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end language_data = 'Por favor Señorita, says the man.' begin params = DocumentParameters.new(content: language_data) params.custom_headers = { 'X-RosetteAPI-App' => 'ruby-app' } - response = rosette_api.get_language(params) + response = analytics_api.get_language(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/language_multilingual.rb b/examples/language_multilingual.rb index 7bc1be4..21edf27 100644 --- a/examples/language_multilingual.rb +++ b/examples/language_multilingual.rb @@ -4,11 +4,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end language_multilingual_data = 'On Thursday, as protesters gathered in Washington D.C., the United States Federal Communications Commission under Chairman Ajit Pai voted 3-2 to overturn a 2015 decision, commonly called Net Neutrality, that forbade Internet service providers (ISPs) such as Verizon, Comcast, and AT&T from blocking individual websites or charging websites or customers more for faster load times. Quatre femmes ont été nommées au Conseil de rédaction de la loi du Qatar. Jeudi, le décret royal du Qatar a annoncé que 28 nouveaux membres ont été nommés pour le Conseil de la Choura du pays. ذكرت مصادر أمنية يونانية، أن 9 موقوفين من منظمة \"د هـ ك ب ج\" الذين كانت قد أوقفتهم الشرطة اليونانية في وقت سابق كانوا يخططون لاغتيال الرئيس التركي رجب طيب أردوغان.' @@ -16,7 +16,7 @@ params = DocumentParameters.new(content: language_multilingual_data) params.rosette_options = { 'multilingual' => 'true' } params.custom_headers = { 'X-RosetteAPI-App' => 'ruby-app' } - response = rosette_api.get_language(params) + response = analytics_api.get_language(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/morphology_complete.rb b/examples/morphology_complete.rb index 1e505ad..7826d52 100644 --- a/examples/morphology_complete.rb +++ b/examples/morphology_complete.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end morphology_complete_data = 'The quick brown fox jumped over the lazy dog. 👍🏾 Yes he did. B)' begin params = DocumentParameters.new(content: morphology_complete_data) - response = rosette_api.get_morphology_complete(params) + response = analytics_api.get_morphology_complete(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/morphology_compound-components.rb b/examples/morphology_compound-components.rb index 175c7a3..6850d40 100644 --- a/examples/morphology_compound-components.rb +++ b/examples/morphology_compound-components.rb @@ -4,18 +4,18 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end morphology_compound_components_data = 'Rechtsschutzversicherungsgesellschaften' begin params = DocumentParameters.new( content: morphology_compound_components_data ) - response = rosette_api.get_compound_components(params) + response = analytics_api.get_compound_components(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/morphology_han-readings.rb b/examples/morphology_han-readings.rb index bf4366e..4f7934f 100644 --- a/examples/morphology_han-readings.rb +++ b/examples/morphology_han-readings.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end morphology_han_readings_data = '北京大学生物系主任办公室内部会议' begin params = DocumentParameters.new(content: morphology_han_readings_data) - response = rosette_api.get_han_readings(params) + response = analytics_api.get_han_readings(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/morphology_lemmas.rb b/examples/morphology_lemmas.rb index bd68690..c5088fb 100644 --- a/examples/morphology_lemmas.rb +++ b/examples/morphology_lemmas.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end morphology_lemmas_data = 'The fact is that the geese just went back to get a rest and I\'m not banking on their return soon' begin params = DocumentParameters.new(content: morphology_lemmas_data) - response = rosette_api.get_lemmas(params) + response = analytics_api.get_lemmas(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/morphology_parts-of-speech.rb b/examples/morphology_parts-of-speech.rb index 0c69e98..e0c515a 100644 --- a/examples/morphology_parts-of-speech.rb +++ b/examples/morphology_parts-of-speech.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end morphology_parts_of_speech_data = 'The fact is that the geese just went back to get a rest and I\'m not banking on their return soon' begin params = DocumentParameters.new(content: morphology_parts_of_speech_data) - response = rosette_api.get_parts_of_speech(params) + response = analytics_api.get_parts_of_speech(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/multipart_language_file.rb b/examples/multipart_language_file.rb index d32c519..648c63b 100644 --- a/examples/multipart_language_file.rb +++ b/examples/multipart_language_file.rb @@ -5,11 +5,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end begin # Create a sample file to upload (so the example is runnable as-is). @@ -17,7 +17,7 @@ File.write(file_path, "Bonjour tout le monde.\n") params = DocumentParameters.new(file_path: file_path) - response = rosette_api.get_language(params) + response = analytics_api.get_language(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/name_deduplication.rb b/examples/name_deduplication.rb index ff4ca7f..6195a63 100644 --- a/examples/name_deduplication.rb +++ b/examples/name_deduplication.rb @@ -4,11 +4,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end name_dedupe_data = 'Alice Terry,Alice Thierry,Betty Grable,Betty Gable,Norma Shearer,Norm Shearer,Brigitte Helm,Bridget Helem,Judy Holliday,Julie Halliday' @@ -16,7 +16,7 @@ names = name_dedupe_data.split(',').map { |n| NameParameter.new(n) } begin params = NameDeduplicationParameters.new(names, threshold) - response = rosette_api.get_name_deduplication(params) + response = analytics_api.get_name_deduplication(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/name_similarity.rb b/examples/name_similarity.rb index 1264067..f0ec486 100644 --- a/examples/name_similarity.rb +++ b/examples/name_similarity.rb @@ -4,11 +4,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end matched_name_data1 = 'Michael Jackson' matched_name_data2 = '迈克尔·杰克逊' @@ -19,7 +19,7 @@ language: 'eng' ) params = NameSimilarityParameters.new(name1, matched_name_data2) - response = rosette_api.get_name_similarity(params) + response = analytics_api.get_name_similarity(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/name_translation.rb b/examples/name_translation.rb index 86ad6b7..babb8da 100644 --- a/examples/name_translation.rb +++ b/examples/name_translation.rb @@ -4,11 +4,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end translated_name_data = 'معمر محمد أبو منيار القذاف' begin @@ -17,7 +17,7 @@ 'eng', target_script: 'Latn' ) - response = rosette_api.get_name_translation(params) + response = analytics_api.get_name_translation(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/ping.rb b/examples/ping.rb index 156f8e7..45a9d80 100644 --- a/examples/ping.rb +++ b/examples/ping.rb @@ -4,14 +4,14 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end begin - response = rosette_api.ping + response = analytics_api.ping puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/relationships.rb b/examples/relationships.rb index 6505290..c8123bf 100644 --- a/examples/relationships.rb +++ b/examples/relationships.rb @@ -4,17 +4,17 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end relationships_text_data = 'FLIR Systems is headquartered in Oregon and produces thermal imaging, night vision, and infrared cameras and sensor systems. According to the SEC\'s order instituting a settled administrative proceeding, FLIR entered into a multi-million dollar contract to provide thermal binoculars to the Saudi government in November 2008. Timms and Ramahi were the primary sales employees responsible for the contract, and also were involved in negotiations to sell FLIR\'s security cameras to the same government officials. At the time, Timms was the head of FLIR\'s Middle East office in Dubai.' begin params = DocumentParameters.new(content: relationships_text_data) - response = rosette_api.get_relationships(params) + response = analytics_api.get_relationships(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/semantic_vectors.rb b/examples/semantic_vectors.rb index 041fc90..dc007ee 100644 --- a/examples/semantic_vectors.rb +++ b/examples/semantic_vectors.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end semantic_vectors_data = 'Cambridge, Massachusetts' begin params = DocumentParameters.new(content: semantic_vectors_data) - response = rosette_api.get_semantic_vectors(params) + response = analytics_api.get_semantic_vectors(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/sentences.rb b/examples/sentences.rb index 7a22b69..5e9b7d3 100644 --- a/examples/sentences.rb +++ b/examples/sentences.rb @@ -4,18 +4,18 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end sentences_data = 'This land is your land. This land is my land, from California to the New York island; from the red wood forest to the Gulf Stream waters. This land was made for you and Me. As I was walking that ribbon of highway, I saw above me that endless skyway: I saw below me that golden valley: This land was made for you and me.' begin params = DocumentParameters.new params.content = sentences_data - response = rosette_api.get_sentences(params) + response = analytics_api.get_sentences(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/sentiment.rb b/examples/sentiment.rb index d03cb13..07cc57e 100644 --- a/examples/sentiment.rb +++ b/examples/sentiment.rb @@ -5,11 +5,11 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end file = Tempfile.new(%w[foo .html]) sentiment_file_data = 'New Ghostbusters Film

Original Ghostbuster Dan Aykroyd, who also co-wrote the 1984 Ghostbusters film, couldn\'t be more pleased with the new all-female Ghostbusters cast, telling The Hollywood Reporter, "The Aykroyd family is delighted by this inheritance of the Ghostbusters torch by these most magnificent women in comedy."

' @@ -17,7 +17,7 @@ file.close begin params = DocumentParameters.new(file_path: file.path, language: 'eng') - response = rosette_api.get_sentiment(params) + response = analytics_api.get_sentiment(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/similar_terms.rb b/examples/similar_terms.rb index 5657c51..dd7d678 100644 --- a/examples/similar_terms.rb +++ b/examples/similar_terms.rb @@ -4,17 +4,17 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end similar_terms_data = 'spy' begin params = DocumentParameters.new(content: similar_terms_data) params.rosette_options = { 'resultLanguages' => %w[spa deu jpn] } - response = rosette_api.get_similar_terms(params) + response = analytics_api.get_similar_terms(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/syntax_dependencies.rb b/examples/syntax_dependencies.rb index 140d1fb..ebe032e 100644 --- a/examples/syntax_dependencies.rb +++ b/examples/syntax_dependencies.rb @@ -4,17 +4,17 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end syntax_dependencies_data = 'Yoshinori Ohsumi, a Japanese cell biologist, was awarded the Nobel Prize in Physiology or Medicine on Monday.' begin params = DocumentParameters.new(content: syntax_dependencies_data) - response = rosette_api.get_syntax_dependencies(params) + response = analytics_api.get_syntax_dependencies(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/tokens.rb b/examples/tokens.rb index 020c465..17998c1 100644 --- a/examples/tokens.rb +++ b/examples/tokens.rb @@ -4,16 +4,16 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end tokens_data = '北京大学生物系主任办公室内部会议' begin params = DocumentParameters.new(content: tokens_data) - response = rosette_api.get_tokens(params) + response = analytics_api.get_tokens(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/topics.rb b/examples/topics.rb index 76f1356..e0fb08c 100644 --- a/examples/topics.rb +++ b/examples/topics.rb @@ -4,17 +4,17 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end topics_data = 'Lily Collins is in talks to join Nicholas Hoult in Chernin Entertainment and Fox Searchlight\'s J.R.R. Tolkien biopic Tolkien. Anthony Boyle, known for playing Scorpius Malfoy in the British play Harry Potter and the Cursed Child, also has signed on for the film centered on the famed author. In Tolkien, Hoult will play the author of the Hobbit and Lord of the Rings book series that were later adapted into two Hollywood trilogies from Peter Jackson. Dome Karukoski is directing the project.' begin params = DocumentParameters.new(content: topics_data) - response = rosette_api.get_topics(params) + response = analytics_api.get_topics(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/examples/transliteration.rb b/examples/transliteration.rb index 887b46f..9f1dec9 100644 --- a/examples/transliteration.rb +++ b/examples/transliteration.rb @@ -4,18 +4,18 @@ api_key, url = ARGV -rosette_api = if url - RosetteAPI.new(api_key, url) - else - RosetteAPI.new(api_key) - end +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end transliteration_content_data = 'ana r2ye7 el gam3a el sa3a 3 el 3asr' begin params = DocumentParameters.new params.content = transliteration_content_data - response = rosette_api.get_transliteration(params) + response = analytics_api.get_transliteration(params) puts JSON.pretty_generate(response) rescue RosetteAPIError => e printf('Rosette API Error (%s): %s', diff --git a/lib/address_parameter.rb b/lib/address_parameter.rb index 19a79c5..e66f677 100644 --- a/lib/address_parameter.rb +++ b/lib/address_parameter.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# This class represents an address in Rosette API. +# This class represents an address in Analytics API. class AddressParameter # house (optional) attr_accessor :house diff --git a/lib/address_similarity_parameters.rb b/lib/address_similarity_parameters.rb index 44dcdca..265ae92 100644 --- a/lib/address_similarity_parameters.rb +++ b/lib/address_similarity_parameters.rb @@ -4,7 +4,7 @@ require_relative 'address_parameter' # This class encapsulates parameters that are needed for address-similarity in -# Rosette API. +# Analytics API. class AddressSimilarityParameters # Address to be compared to address2 attr_accessor :address1 diff --git a/lib/bad_request_error.rb b/lib/bad_request_error.rb index 473e0e8..4660001 100644 --- a/lib/bad_request_error.rb +++ b/lib/bad_request_error.rb @@ -2,7 +2,7 @@ require_relative 'rosette_api_error' -# This class represents Rosette API errors with badRequest status_code. +# This class represents Analytics API errors with badRequest status_code. class BadRequestError < RosetteAPIError def initialize(message) # :notnew: super('badRequest', message) diff --git a/lib/bad_request_format_error.rb b/lib/bad_request_format_error.rb index 1a6fb45..f4a088f 100644 --- a/lib/bad_request_format_error.rb +++ b/lib/bad_request_format_error.rb @@ -2,7 +2,7 @@ require_relative 'rosette_api_error' -# This class represents Rosette API errors with badRequestFormat status_code. +# This class represents Analytics API errors with badRequestFormat status_code. class BadRequestFormatError < RosetteAPIError def initialize(message) # :notnew: super('badRequestFormat', message) diff --git a/lib/document_parameters.rb b/lib/document_parameters.rb index 734a7b8..d810bb5 100644 --- a/lib/document_parameters.rb +++ b/lib/document_parameters.rb @@ -17,9 +17,9 @@ class DocumentParameters attr_accessor :genre # ISO 639-3 language code of the provided content (optional) attr_accessor :language - # Rosette API options (optional, should be a hash) + # API options (optional, should be a hash) attr_accessor :rosette_options - # custom Rosette API headers + # custom API headers attr_accessor :custom_headers def initialize(options = {}) # :notnew: diff --git a/lib/name_deduplication_parameters.rb b/lib/name_deduplication_parameters.rb index e6baa33..4755d7d 100644 --- a/lib/name_deduplication_parameters.rb +++ b/lib/name_deduplication_parameters.rb @@ -4,9 +4,9 @@ require_relative 'name_parameter' # This class encapsulates parameters that are needed for name-deduplication in -# Rosette API. +# Analytics API. class NameDeduplicationParameters - # Rosette API options (optional, should be a hash) + # API options (optional, should be a hash) attr_accessor :rosette_options # List of Name objects to be de-duplicated attr_accessor :names diff --git a/lib/name_parameter.rb b/lib/name_parameter.rb index bb04a18..5b0715e 100644 --- a/lib/name_parameter.rb +++ b/lib/name_parameter.rb @@ -1,6 +1,6 @@ # frozen_string_literal: true -# This class represents an entity name in Rosette API. +# This class represents an entity name in Analytics API. class NameParameter # Name's entity type (PERSON, LOCATION, ORGANIZATION) (optional) attr_accessor :entity_type diff --git a/lib/name_similarity_parameters.rb b/lib/name_similarity_parameters.rb index e27353e..9236acc 100644 --- a/lib/name_similarity_parameters.rb +++ b/lib/name_similarity_parameters.rb @@ -4,7 +4,7 @@ require_relative 'name_parameter' # This class encapsulates parameters that are needed for name-similarity in -# Rosette API. +# Analytics API. class NameSimilarityParameters # genre to categorize the input data attr_accessor :genre diff --git a/lib/name_translation_parameters.rb b/lib/name_translation_parameters.rb index 70e9dad..aa4fb09 100644 --- a/lib/name_translation_parameters.rb +++ b/lib/name_translation_parameters.rb @@ -3,7 +3,7 @@ require_relative 'rosette_api_error' # This class encapsulates parameters that are needed for name-translation in -# Rosette API. +# Analytics API. class NameTranslationParameters # Name's entity type (PERSON, LOCATION, ORGANIZATION) (optional) attr_accessor :entity_type @@ -11,7 +11,7 @@ class NameTranslationParameters attr_accessor :genre # Name to translate attr_accessor :name - # Rosette API options (optional, should be a hash) + # API options (optional, should be a hash) attr_accessor :rosette_options # ISO 693-3 code of the name's native language the name originates in # (optional) diff --git a/lib/request_builder.rb b/lib/request_builder.rb index d6173c3..28914c9 100644 --- a/lib/request_builder.rb +++ b/lib/request_builder.rb @@ -6,17 +6,17 @@ require 'securerandom' require_relative 'rosette_api_error' -# This class handles all Rosette API requests. +# This class handles all Analytics API requests. class RequestBuilder - # Alternate Rosette API URL + # Alternate API URL attr_reader :alternate_url - # Rosette API HTTP client + # API HTTP client attr_reader :http_client # Parameters to build the body of the request from attr_accessor :params - # Rosette API key + # API key attr_accessor :user_key - # Rosette API binding version + # API binding version attr_accessor :binding_version # User-Agent string attr_reader :user_agent @@ -35,7 +35,7 @@ def initialize(user_key, alternate_url, http_client, binding_version, @alternate_url = "#{@alternate_url}?#{URI.encode_www_form(url_parameters)}" end - # Prepares a plain POST request for Rosette API. + # Prepares a plain POST request for Analytics API. # # ==== Attributes # @@ -51,7 +51,7 @@ def prepare_plain_request(params) # https://stackoverflow.com/a/11802674 raise RosetteAPIError.new( 'connectionError', - 'Failed to establish connection with Rosette server.' + 'Failed to establish connection with Analytics server.' ) end @@ -60,30 +60,32 @@ def prepare_plain_request(params) if custom_headers keys_array = custom_headers.keys keys_array.each do |key| - if key.to_s =~ /^X-RosetteAPI-/ + if key.to_s =~ /^X-RosetteAPI-/ || key.to_s =~ /^X-BabelStreetAPI-/ request[key] = custom_headers[key] else raise RosetteAPIError.new( 'invalidHeader', - 'Custom header must begin with "X-RosetteAPI-"' + 'Custom header must begin with "X-RosetteAPI-" or "X-BabelStreetAPI-"' ) end end params.delete 'customHeaders' end - request['X-RosetteAPI-Key'] = @user_key + request['X-BabelStreetAPI-Key'] = @user_key request['Content-Type'] = 'application/json' request['Accept'] = 'application/json' request['User-Agent'] = @user_agent request['X-RosetteAPI-Binding'] = 'ruby' + request['X-BabelStreetAPI-Binding'] = 'ruby' request['X-RosetteAPI-Binding-Version'] = @binding_version + request['X-BabelStreetAPI-Binding-Version'] = @binding_version request.body = params.to_json [@http_client, request] end - # Prepares a multipart/form-data POST request for Rosette API. + # Prepares a multipart/form-data POST request for Anaytyics API. # # ==== Attributes # @@ -122,7 +124,7 @@ def prepare_multipart_request(params) # https://stackoverflow.com/a/11802674 raise RosetteAPIError.new( 'connectionError', - 'Failed to establish connection with Rosette API server.' + 'Failed to establish connection with Analytics server.' ) end @@ -130,12 +132,12 @@ def prepare_multipart_request(params) unless params['customHeaders'].nil? keys_array = params['customHeaders'].keys keys_array.each do |k| - if k.to_s =~ /^X-RosetteAPI-/ + if k.to_s =~ /^X-RosetteAPI-/ || key.to_s =~ /^X-BabelStreetAPI-/ request.add_field k, params['customHeaders'][k] else raise RosetteAPIError.new( 'invalidHeader', - 'Custom header must begin with "X-RosetteAPI-"' + 'Custom header must begin with "X-RosetteAPI-" or "X-BabelStreetAPI-"' ) end end @@ -145,9 +147,11 @@ def prepare_multipart_request(params) request.add_field 'Content-Type', "multipart/form-data; boundary=#{boundary}" request.add_field 'User-Agent', @user_agent - request.add_field 'X-RosetteAPI-Key', @user_key + request.add_field 'X-BabelStreetAPI-Key', @user_key request.add_field 'X-RosetteAPI-Binding', 'ruby' + request.add_field 'X-BabelStreetAPI-Binding', 'ruby' request.add_field 'X-RosetteAPI-Binding-Version', @binding_version + request.add_field 'X-BabelStreetAPI-Binding-Version', @binding_version request.body = post_body.join [@http_client, request] @@ -164,7 +168,7 @@ def read_multipart_file(file_path) raise RosetteAPIError.new('readMultipartError', e) end - # Sends a GET request to Rosette API. + # Sends a GET request to Analytics API. # # Returns JSON response or raises RosetteAPIError if encountered. def send_get_request @@ -176,16 +180,16 @@ def send_get_request # https://stackoverflow.com/a/11802674 raise RosetteAPIError.new( 'connectionError', - 'Failed to establish connection with Rosette API server.' + 'Failed to establish connection with Analytics server.' ) end - request['X-RosetteAPI-Key'] = @user_key + request['X-BabelStreetAPI-Key'] = @user_key request['User-Agent'] = @user_agent get_response @http_client, request end - # Sends a POST request to Rosette API. + # Sends a POST request to Analytics API. # # Returns JSON response or raises RosetteAPIError if encountered. def send_post_request @@ -204,7 +208,7 @@ def send_post_request # # * +http+ - HTTP connection. # - # * +request+ - Prepared Rosette API request. + # * +request+ - Prepared API request. # # Returns JSON response or raises RosetteAPIError if encountered. def get_response(http, request) diff --git a/lib/rosette_api.rb b/lib/rosette_api.rb index 5115cf5..c43892e 100644 --- a/lib/rosette_api.rb +++ b/lib/rosette_api.rb @@ -14,7 +14,7 @@ # This class allows you to access all Analytics API endpoints. class RosetteAPI # Version of Ruby binding - BINDING_VERSION = '1.27.1' + BINDING_VERSION = '1.37.0' # API language endpoint LANGUAGE_ENDPOINT = '/language' # API morphology endpoint @@ -58,16 +58,16 @@ class RosetteAPI # Topics endpoint TOPICS_ENDPOINT = '/topics' - # Rosette API key + # API key attr_accessor :user_key - # Alternate Rosette API URL + # Alternate API URL attr_accessor :alternate_url - # custom Rosette API headers + # custom API headers attr_accessor :custom_headers # URL query parameter(s) attr_accessor :url_parameters - def initialize(user_key, alternate_url = 'https://api.rosette.com/rest/v1') + def initialize(user_key, alternate_url = 'https://analytics.babelstreet.com/rest/v1') @log = Logger.new($stdout) @user_key = user_key @alternate_url = alternate_url @@ -521,7 +521,7 @@ def get_events(params) .send_post_request end - # Gets information about the Rosette API, returns name, build number + # Gets information about the API, returns name, build number # and build time. def info RequestBuilder.new(@user_key, @alternate_url + INFO, @http_client, @@ -529,7 +529,7 @@ def info .send_get_request end - # Pings the Rosette API for a response indicting that the service is + # Pings the API for a response indicting that the service is # available. def ping RequestBuilder.new(@user_key, @alternate_url + PING, @http_client, diff --git a/lib/rosette_api_error.rb b/lib/rosette_api_error.rb index 427e4cd..cb5abcb 100644 --- a/lib/rosette_api_error.rb +++ b/lib/rosette_api_error.rb @@ -1,11 +1,11 @@ # frozen_string_literal: true -# This class encapsulates all Rosette API server errors encountered during +# This class encapsulates all API server errors encountered during # requests. class RosetteAPIError < StandardError - # Rosette API error's status code + # API error's status code attr_accessor :status_code - # Rosette API error's message + # API error's message attr_accessor :message def initialize(status_code, message) # :notnew: diff --git a/sonar-project.properties b/sonar-project.properties index d23e709..500f06a 100644 --- a/sonar-project.properties +++ b/sonar-project.properties @@ -1,4 +1,2 @@ sonar.projectKey=rosette-api-ruby-binding -sonar.ruby.coverage.reportPaths=coverage/.resultset.json -#sonar.ruby.coverage.reportPaths=coverage/coverage.json sonar.exclusions=**/tests/**,**/examples/** diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index 53f57a0..23ce51e 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -30,7 +30,7 @@ describe '.get_language' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/language') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/language') .with( body: @json, headers: { @@ -38,9 +38,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "language"}', headers: {}) @@ -69,7 +71,7 @@ describe '.get_morphology_complete' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/morphology/complete') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/morphology/complete') .with( body: @json, headers: { @@ -77,9 +79,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -96,7 +100,7 @@ describe '.get_compound_components' do before do - url = 'https://api.rosette.com/rest/v1/morphology/compound-components' + url = 'https://analytics.babelstreet.com/rest/v1/morphology/compound-components' stub_request(:post, url) .with( body: @json, @@ -105,9 +109,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -124,7 +130,7 @@ describe '.get_han_readings' do before do - url = 'https://api.rosette.com/rest/v1/morphology/han-readings' + url = 'https://analytics.babelstreet.com/rest/v1/morphology/han-readings' stub_request(:post, url) .with( body: @json, @@ -133,9 +139,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -152,7 +160,7 @@ describe '.get_parts_of_speech' do before do - url = 'https://api.rosette.com/rest/v1/morphology/parts-of-speech' + url = 'https://analytics.babelstreet.com/rest/v1/morphology/parts-of-speech' stub_request(:post, url) .with( body: @json, @@ -161,9 +169,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -180,7 +190,7 @@ describe '.get_lemmas' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/morphology/lemmas') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/morphology/lemmas') .with( body: @json, headers: { @@ -188,9 +198,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -207,7 +219,7 @@ describe '.get_entities' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/entities') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/entities') .with( body: @json, headers: { @@ -215,9 +227,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "entities"}', headers: {}) @@ -234,7 +248,7 @@ before do no_qids_json = { content: 'Sample Content', options: { linkEntities: false } }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/entities') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/entities') .with( body: no_qids_json, headers: { @@ -242,9 +256,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "entities"}', headers: {}) @@ -271,7 +287,7 @@ describe '.get_categories' do before do categories_json = { contentUri: 'http://google.com' }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/categories') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/categories') .with( body: categories_json, headers: { @@ -279,9 +295,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "categories"}', headers: {}) @@ -297,7 +315,7 @@ describe '.get_events' do before do events_json = { contentUri: 'http://google.com' }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/events') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/events') .with( body: events_json, headers: { @@ -305,9 +323,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "events"}', headers: {}) @@ -324,7 +344,7 @@ describe '.get_sentiment' do before do sentiment_json = { contentUri: 'http://google.com' }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/sentiment') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/sentiment') .with( body: sentiment_json, headers: { @@ -332,9 +352,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "sentiment"}', headers: {}) @@ -351,7 +373,7 @@ describe '.get_text_embedding' do before do text_embedding_json = { contentUri: 'http://google.com' }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/text-embedding') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/text-embedding') .with( body: text_embedding_json, headers: { @@ -359,9 +381,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "text-embedding"}', headers: {}) @@ -377,7 +401,7 @@ describe '.get_relationships' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/relationships') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/relationships') .with( body: @json, headers: { @@ -385,9 +409,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "relationships"}', headers: {}) @@ -405,7 +431,7 @@ name_translation_json = { name: 'معمر محمد أبو منيار القذاف', targetLanguage: 'eng', targetScript: 'Latn' }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/name-translation') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/name-translation') .with( body: name_translation_json, headers: { @@ -413,9 +439,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -426,7 +454,7 @@ targetLanguage: 'eng', targetScript: 'Latn', maximumResults: 5 }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/name-translation') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/name-translation') .with( body: name_translation_max_results_json, headers: { @@ -434,9 +462,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -482,7 +512,7 @@ describe '.name_similarity' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/name-similarity') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/name-similarity') .with( body: hash_including( name1: 'Michael Jackson', @@ -493,9 +523,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -518,7 +550,7 @@ RosetteAPI.new('0123456789').get_name_similarity(params) expect( - a_request(:post, 'https://api.rosette.com/rest/v1/name-similarity') + a_request(:post, 'https://analytics.babelstreet.com/rest/v1/name-similarity') .with(body: hash_including(parameters: { finalBias: '0.0003' })) ).to have_been_made.once end @@ -549,7 +581,7 @@ before do names_json = { names: names.map(&:load_param), threshold: 0.75 }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/name-deduplication') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/name-deduplication') .with( body: names_json, headers: { @@ -557,9 +589,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -568,7 +602,7 @@ nothresh_json = { names: names.map(&:load_param) }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/name-deduplication') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/name-deduplication') .with( body: nothresh_json, headers: { @@ -576,9 +610,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -629,7 +665,7 @@ before do transliteration_json = { content: content }.to_json - stub_request(:post, 'https://api.rosette.com/rest/v1/transliteration') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/transliteration') .with( body: transliteration_json, headers: { @@ -637,9 +673,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -670,7 +708,7 @@ describe '.get_tokens' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/tokens') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/tokens') .with( body: @json, headers: { @@ -678,9 +716,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "tokens"}', headers: {}) @@ -695,7 +735,7 @@ describe '.get_topics' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/topics') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/topics') .with( body: @json, headers: { @@ -703,9 +743,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "topics"}', headers: {}) @@ -720,7 +762,7 @@ describe '.get_sentences' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/sentences') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/sentences') .with( body: @json, headers: { @@ -728,9 +770,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "sentences"}', headers: {}) @@ -745,13 +789,13 @@ describe '.info' do before do - stub_request(:get, 'https://api.rosette.com/rest/v1/info') + stub_request(:get, 'https://analytics.babelstreet.com/rest/v1/info') .with( headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789' + 'X-BabelStreetAPI-Key' => '0123456789' } ) .to_return(status: 200, body: '{"test": "info"}', headers: {}) @@ -764,13 +808,13 @@ describe '.ping' do before do - stub_request(:get, 'https://api.rosette.com/rest/v1/ping') + stub_request(:get, 'https://analytics.babelstreet.com/rest/v1/ping') .with( headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789' + 'X-BabelStreetAPI-Key' => '0123456789' } ) .to_return(status: 200, body: '{"test": "ping"}', headers: {}) @@ -783,7 +827,7 @@ describe '.get_language_custom_header' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/language') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/language') .with( body: @json, headers: { @@ -791,9 +835,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1', + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0', 'X-RosetteApi-App' => 'ruby-app' } ) @@ -811,13 +857,13 @@ describe '.error_409_incompatible_client_version' do before do - stub_request(:get, 'https://api.rosette.com/rest/v1/info') + stub_request(:get, 'https://analytics.babelstreet.com/rest/v1/info') .with( headers: { 'Accept' => '*/*', 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789' + 'X-BabelStreetAPI-Key' => '0123456789' } ) .to_return(status: 409, @@ -832,7 +878,7 @@ describe '.get_similar_terms' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/semantics/similar') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/semantics/similar') .with( body: @json, headers: { @@ -840,9 +886,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "language"}', headers: {}) @@ -859,7 +907,7 @@ describe '.get_semantic_vectors' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/semantics/vector') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/semantics/vector') .with( body: @json, headers: { @@ -867,9 +915,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "language"}', headers: {}) @@ -884,7 +934,7 @@ describe '.get_syntax_dependencies' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/syntax/dependencies') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/syntax/dependencies') .with( body: @json, headers: { @@ -892,9 +942,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, body: '{"test": "language"}', headers: {}) @@ -909,7 +961,7 @@ describe '.address_similarity' do before do - stub_request(:post, 'https://api.rosette.com/rest/v1/address-similarity') + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/address-similarity') .with( body: hash_including( address1: { @@ -930,9 +982,11 @@ 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Content-Type' => 'application/json', 'User-Agent' => @user_agent, - 'X-Rosetteapi-Key' => '0123456789', + 'X-BabelStreetAPI-Key' => '0123456789', 'X-Rosetteapi-Binding' => 'ruby', - 'X-Rosetteapi-Binding-Version' => '1.27.1' + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' } ) .to_return(status: 200, @@ -963,7 +1017,7 @@ RosetteAPI.new('0123456789').get_address_similarity(params) expect( - a_request(:post, 'https://api.rosette.com/rest/v1/address-similarity') + a_request(:post, 'https://analytics.babelstreet.com/rest/v1/address-similarity') .with(body: hash_including(parameters: { someOption: true })) ).to have_been_made.once end From 332179f1b1adb2334614b479bba88d4f348fa3b1 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 15:49:12 +0100 Subject: [PATCH 19/24] BX-68618: positive custom header tests --- tests/tests_spec.rb | 69 ++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index 23ce51e..2ee0cdd 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -840,12 +840,79 @@ 'X-BabelStreetAPI-Binding' => 'ruby', 'X-Rosetteapi-Binding-Version' => '1.37.0', 'X-BabelStreetAPI-Binding-Version' => '1.37.0', - 'X-RosetteApi-App' => 'ruby-app' + 'X-RosetteAPI-App' => 'ruby-app' } ) .to_return(status: 200, body: '{"test": "language"}', headers: {}) end + it 'sends custom header with X-RosetteAPI- prefix' do + params = DocumentParameters.new + params.content = 'Por favor Senorita, says the man.?' + params.custom_headers = { 'X-RosetteAPI-App' => 'ruby-app' } + + response = RosetteAPI.new('0123456789').get_language(params) + expect(response).instance_of? Hash + end + + it 'sends custom header with X-BabelStreetAPI- prefix' do + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/language') + .with( + body: @json, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-BabelStreetAPI-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-App' => 'ruby-app' + } + ) + .to_return(status: 200, body: '{"test": "language"}', headers: {}) + + params = DocumentParameters.new + params.content = 'Por favor Senorita, says the man.?' + params.custom_headers = { 'X-BabelStreetAPI-App' => 'ruby-app' } + + response = RosetteAPI.new('0123456789').get_language(params) + expect(response).instance_of? Hash + end + + it 'sends custom headers with both prefixes together' do + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/language') + .with( + body: @json, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-BabelStreetAPI-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0', + 'X-RosetteAPI-App' => 'ruby-app', + 'X-BabelStreetAPI-App' => 'ruby-app' + } + ) + .to_return(status: 200, body: '{"test": "language"}', headers: {}) + + params = DocumentParameters.new + params.content = 'Por favor Senorita, says the man.?' + params.custom_headers = { + 'X-RosetteAPI-App' => 'ruby-app', + 'X-BabelStreetAPI-App' => 'ruby-app' + } + + response = RosetteAPI.new('0123456789').get_language(params) + expect(response).instance_of? Hash + end + it 'test custom_headers is invalid' do params = DocumentParameters.new params.content = 'Por favor Senorita, says the man.?' From f3ec46d36ed92fcffe71779798bd523533ff2686 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 16:28:39 +0100 Subject: [PATCH 20/24] BX-68618: alphabetically ordered endpoints --- lib/rosette_api.rb | 48 +++++++++++++++++++++++----------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/lib/rosette_api.rb b/lib/rosette_api.rb index c43892e..620e4dc 100644 --- a/lib/rosette_api.rb +++ b/lib/rosette_api.rb @@ -15,48 +15,48 @@ class RosetteAPI # Version of Ruby binding BINDING_VERSION = '1.37.0' - # API language endpoint - LANGUAGE_ENDPOINT = '/language' - # API morphology endpoint - MORPHOLOGY_ENDPOINT = '/morphology' + # API address-similarity endpoint + ADDRESS_SIMILARITY_ENDPOINT = '/address-similarity' + # API categories endpoint + CATEGORIES_ENDPOINT = '/categories' # API entities endpoint ENTITIES_ENDPOINT = '/entities' # API events endpoint EVENTS_ENDPOINT = '/events' - # API categories endpoint - CATEGORIES_ENDPOINT = '/categories' - # API relationships endpoint - RELATIONSHIPS_ENDPOINT = '/relationships' - # API sentiment endpoint - SENTIMENT_ENDPOINT = '/sentiment' + # API info endpoint + INFO = '/info' + # API language endpoint + LANGUAGE_ENDPOINT = '/language' + # API morphology endpoint + MORPHOLOGY_ENDPOINT = '/morphology' # Name Deduplication endpoint NAME_DEDUPLICATION_ENDPOINT = '/name-deduplication' - # API name-translation endpoint - NAME_TRANSLATION_ENDPOINT = '/name-translation' # API name-similarity endpoint NAME_SIMILARITY_ENDPOINT = '/name-similarity' - # API address-similarity endpoint - ADDRESS_SIMILARITY_ENDPOINT = '/address-similarity' - # API tokens endpoint - TOKENS_ENDPOINT = '/tokens' - # API sentences endpoint - SENTENCES_ENDPOINT = '/sentences' - # API info endpoint - INFO = '/info' + # API name-translation endpoint + NAME_TRANSLATION_ENDPOINT = '/name-translation' # API ping endpoint PING = '/ping' - # Text Embedding endpoint (deprecated) - TEXT_EMBEDDING = '/text-embedding' + # API relationships endpoint + RELATIONSHIPS_ENDPOINT = '/relationships' # Semantic Vectors endpoint (replaces /text-embedding) SEMANTIC_VECTORS = '/semantics/vector' + # API sentences endpoint + SENTENCES_ENDPOINT = '/sentences' + # API sentiment endpoint + SENTIMENT_ENDPOINT = '/sentiment' # Similar Terms endpoint SIMILAR_TERMS_ENDPOINT = '/semantics/similar' # Syntactic Dependencies endpoint SYNTACTIC_DEPENDENCIES_ENDPOINT = '/syntax/dependencies' - # Transliteration endpoint - TRANSLITERATION_ENDPOINT = '/transliteration' + # Text Embedding endpoint (deprecated) + TEXT_EMBEDDING = '/text-embedding' + # API tokens endpoint + TOKENS_ENDPOINT = '/tokens' # Topics endpoint TOPICS_ENDPOINT = '/topics' + # Transliteration endpoint + TRANSLITERATION_ENDPOINT = '/transliteration' # API key attr_accessor :user_key From 411fb8d7acd581a1651183b0b47a82b258451370 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 17:11:12 +0100 Subject: [PATCH 21/24] BX-68618: add record similarity support --- .rubocop_todo.yml | 9 +- examples/record_similarity.rb | 127 ++++++++++++++++++++++++++++ lib/record_similarity_parameters.rb | 68 +++++++++++++++ lib/rosette_api.rb | 23 +++++ tests/tests_spec.rb | 116 +++++++++++++++++++++++++ 5 files changed, 341 insertions(+), 2 deletions(-) create mode 100644 examples/record_similarity.rb create mode 100644 lib/record_similarity_parameters.rb diff --git a/.rubocop_todo.yml b/.rubocop_todo.yml index bd2822d..3023156 100644 --- a/.rubocop_todo.yml +++ b/.rubocop_todo.yml @@ -23,12 +23,16 @@ Metrics/BlockLength: # Offense count: 2 # Configuration parameters: CountComments, CountAsOne. Metrics/ClassLength: - Max: 239 + Max: 250 # Offense count: 1 # Configuration parameters: AllowedMethods, AllowedPatterns. Metrics/CyclomaticComplexity: - Max: 8 + Max: 10 + +Metrics/PerceivedComplexity: + Max: 10 + # Offense count: 10 # Configuration parameters: CountComments, CountAsOne, AllowedMethods, AllowedPatterns. @@ -64,6 +68,7 @@ Style/CommentedKeyword: - 'lib/name_parameter.rb' - 'lib/name_similarity_parameters.rb' - 'lib/name_translation_parameters.rb' + - 'lib/record_similarity_parameters.rb' - 'lib/rosette_api_error.rb' # Offense count: 14 diff --git a/examples/record_similarity.rb b/examples/record_similarity.rb new file mode 100644 index 0000000..05ff371 --- /dev/null +++ b/examples/record_similarity.rb @@ -0,0 +1,127 @@ +# frozen_string_literal: true + +require 'rosette_api' + +api_key, url = ARGV + +analytics_api = if url + RosetteAPI.new(api_key, url) + else + RosetteAPI.new(api_key) + end + +begin + # Field names + primary_name_field = 'primaryName' + dob_field = 'dob' + dob2_field = 'dob2' + addr_field = 'addr' + str_field = 'jobTitle' + number_field = 'age' + bool_field = 'isRetired' + + dob_hyphen = '1993-04-16' + + # Request fields definition + fields = { + primary_name_field => { type: 'rni_name', weight: 0.5 }, + dob_field => { type: 'rni_date', weight: 0.2 }, + dob2_field => { type: 'rni_date', weight: 0.1 }, + addr_field => { type: 'rni_address', weight: 0.5 }, + str_field => { type: 'rni_string', weight: 0.2 }, + number_field => { type: 'rni_number', weight: 0.4 }, + bool_field => { type: 'rni_boolean', weight: 0.05 } + } + + # Request properties + properties = { + threshold: 0.7, + includeExplainInfo: true + } + + # Records payload. This shape mirrors the Java example's left/right lists. + # + # NOTE: The exact record field object schemas are API-specific. This example + # uses descriptive hashes that are intended to serialize cleanly to JSON. + records = { + left: [ + { + primary_name_field => { + text: 'Ethan R', + entityType: 'PERSON', + language: 'eng', + languageOfOrigin: 'eng', + script: 'Latn' + }, + dob_field => dob_hyphen, + dob2_field => { + date: '04161993', + format: 'MMddyyyy' + }, + addr_field => '123 Roadlane Ave', + str_field => { + data: 'software engineer' + } + }, + { + primary_name_field => { + text: 'Evan R' + }, + dob_field => { + date: dob_hyphen + }, + number_field => { + data: 47 + }, + bool_field => { + data: false + } + } + ], + right: [ + { + primary_name_field => { + text: 'Seth R', + language: 'eng' + }, + dob_field => { + date: dob_hyphen + }, + str_field => { + data: 'manager' + }, + bool_field => { + data: true + } + }, + { + primary_name_field => 'Ivan R', + dob_field => { + date: dob_hyphen + }, + dob2_field => { + date: '1993/04/16' + }, + addr_field => { + houseNumber: '123', + road: 'Roadlane Ave', + cityDistrict: 'Alpha' + }, + number_field => { + data: 72 + }, + bool_field => { + data: true + } + } + ] + } + + params = RecordSimilarityParameters.new(fields, records, properties) + response = analytics_api.get_record_similarity(params) + puts JSON.pretty_generate(response) +rescue RosetteAPIError => e + printf('Rosette API Error (%s): %s', + status_code: e.status_code, + message: e.message) +end diff --git a/lib/record_similarity_parameters.rb b/lib/record_similarity_parameters.rb new file mode 100644 index 0000000..6b68dc0 --- /dev/null +++ b/lib/record_similarity_parameters.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +require_relative 'bad_request_error' + +# This class encapsulates parameters that are needed for record-similarity in +# Analytics API. +class RecordSimilarityParameters + # Records to be compared (required) + attr_accessor :records + + # Field names/definitions used for similarity scoring (required) + attr_accessor :fields + + # Optional properties map sent to the API (optional, should be a hash) + attr_accessor :properties + + def initialize(fields, records, properties = nil) # :notnew: + @fields = fields + @records = records + @properties = properties + end + + # Validates the parameters by checking if required fields are present and + # optional properties is a Hash if provided. + def validate_params + f_msg = 'fields option is required' + raise BadRequestError.new(f_msg) if @fields.nil? + + f_type_msg = 'fields can only be an instance of a Hash' + raise BadRequestError.new(f_type_msg) unless @fields.is_a? Hash + + f_empty_msg = 'fields must not be empty' + raise BadRequestError.new(f_empty_msg) if @fields.empty? + + r_msg = 'records option is required' + raise BadRequestError.new(r_msg) if @records.nil? + + r_type_msg = 'records can only be an instance of a Hash' + raise BadRequestError.new(r_type_msg) unless @records.is_a? Hash + + r_empty_msg = 'records must not be empty' + raise BadRequestError.new(r_empty_msg) if @records.empty? + + p_msg = 'properties can only be an instance of a Hash' + raise BadRequestError.new(p_msg) if @properties && !(@properties.is_a? Hash) + end + + # Converts this class to Hash with its keys in lower CamelCase. + # + # Returns the new Hash. + def load_params + validate_params + to_hash + .compact + .transform_keys { |key| key.to_s.split('_').map(&:capitalize).join.sub!(/\D/, &:downcase) } + end + + # Converts this class to Hash. + # + # Returns the new Hash. + def to_hash + { + fields: @fields, + records: @records, + properties: @properties + } + end +end diff --git a/lib/rosette_api.rb b/lib/rosette_api.rb index 620e4dc..24ac10c 100644 --- a/lib/rosette_api.rb +++ b/lib/rosette_api.rb @@ -5,6 +5,7 @@ require_relative 'name_deduplication_parameters' require_relative 'name_translation_parameters' require_relative 'name_similarity_parameters' +require_relative 'record_similarity_parameters' require_relative 'address_similarity_parameters' require_relative 'rosette_api_error' require_relative 'bad_request_error' @@ -37,6 +38,8 @@ class RosetteAPI NAME_TRANSLATION_ENDPOINT = '/name-translation' # API ping endpoint PING = '/ping' + # Record Similarity endpoint + RECORD_SIMILARITY_ENDPOINT = '/record-similarity' # API relationships endpoint RELATIONSHIPS_ENDPOINT = '/relationships' # Semantic Vectors endpoint (replaces /text-embedding) @@ -352,6 +355,26 @@ def get_address_similarity(params) .send_post_request end + # Compares records and returns similarity information. + # + # ==== Attributes + # + # * +params+ - RecordSimilarityParameters helps to build the request body in + # RequestBuilder. + # + # Returns record similarity results. + def get_record_similarity(params) + check_params params, + 'Expects a RecordSimilarityParameters type as an argument', + RecordSimilarityParameters + + params = params.load_params + + RequestBuilder.new(@user_key, @alternate_url + RECORD_SIMILARITY_ENDPOINT, + @http_client, BINDING_VERSION, params, @url_parameters) + .send_post_request + end + # Divides the input into tokens. # # ==== Attributes diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index 2ee0cdd..65ee621 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -1152,4 +1152,120 @@ .to raise_error(ArgumentError) end end + + describe '.get_record_similarity' do + before do + body = { + fields: { 'primaryName' => { type: 'rni_name', weight: 0.5 } }, + records: { left: [{ 'primaryName' => { text: 'Ethan R' } }], right: [{ 'primaryName' => { text: 'Seth R' } }] }, + properties: { threshold: 0.7 } + }.to_json + + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/record-similarity') + .with( + body: body, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-BabelStreetAPI-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' + } + ) + .to_return(status: 200, body: '{"test": "record-similarity"}', headers: {}) + end + + it 'test record similarity (minimal request with properties)' do + fields = { 'primaryName' => { type: 'rni_name', weight: 0.5 } } + records = { + left: [{ 'primaryName' => { text: 'Ethan R' } }], + right: [{ 'primaryName' => { text: 'Seth R' } }] + } + properties = { threshold: 0.7 } + + params = RecordSimilarityParameters.new(fields, records, properties) + response = RosetteAPI.new('0123456789').get_record_similarity(params) + expect(response).instance_of? Hash + end + + it 'test record similarity without properties' do + body = { + fields: { 'primaryName' => { type: 'rni_name', weight: 0.5 } }, + records: { left: [{ 'primaryName' => { text: 'Ethan R' } }], right: [{ 'primaryName' => { text: 'Seth R' } }] } + }.to_json + + stub_request(:post, 'https://analytics.babelstreet.com/rest/v1/record-similarity') + .with( + body: body, + headers: { + 'Accept' => 'application/json', + 'Accept-Encoding' => 'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', + 'Content-Type' => 'application/json', + 'User-Agent' => @user_agent, + 'X-BabelStreetAPI-Key' => '0123456789', + 'X-Rosetteapi-Binding' => 'ruby', + 'X-BabelStreetAPI-Binding' => 'ruby', + 'X-Rosetteapi-Binding-Version' => '1.37.0', + 'X-BabelStreetAPI-Binding-Version' => '1.37.0' + } + ) + .to_return(status: 200, body: '{"test": "record-similarity"}', headers: {}) + + fields = { 'primaryName' => { type: 'rni_name', weight: 0.5 } } + records = { + left: [{ 'primaryName' => { text: 'Ethan R' } }], + right: [{ 'primaryName' => { text: 'Seth R' } }] + } + + params = RecordSimilarityParameters.new(fields, records) + response = RosetteAPI.new('0123456789').get_record_similarity(params) + expect(response).instance_of? Hash + end + + it 'badRequest: fields is required' do + params = RecordSimilarityParameters.new(nil, { left: [{}], right: [{}] }, { threshold: 0.7 }) + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + + it 'badRequest: fields must be a Hash' do + params = RecordSimilarityParameters.new(['not-a-hash'], { left: [{}], right: [{}] }, { threshold: 0.7 }) + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + + it 'badRequest: fields must not be empty' do + params = RecordSimilarityParameters.new({}, { left: [{}], right: [{}] }, { threshold: 0.7 }) + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + + it 'badRequest: records is required' do + params = RecordSimilarityParameters.new({ 'primaryName' => {} }, nil, { threshold: 0.7 }) + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + + it 'badRequest: records must be a Hash' do + params = RecordSimilarityParameters.new({ 'primaryName' => {} }, ['not-a-hash'], { threshold: 0.7 }) + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + + it 'badRequest: records must not be empty' do + params = RecordSimilarityParameters.new({ 'primaryName' => {} }, {}, { threshold: 0.7 }) + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + + it 'badRequest: properties must be a Hash when provided' do + params = RecordSimilarityParameters.new({ 'primaryName' => {} }, { left: [{}], right: [{}] }, 'nope') + expect { RosetteAPI.new('0123456789').get_record_similarity(params) } + .to raise_error(BadRequestError) + end + end end From ce14ebbbaca8c108d2d088cda18f6a606c54738d Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 17:23:03 +0100 Subject: [PATCH 22/24] BX-68618: fix custom header tests --- tests/tests_spec.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/tests_spec.rb b/tests/tests_spec.rb index 65ee621..2899dd9 100644 --- a/tests/tests_spec.rb +++ b/tests/tests_spec.rb @@ -848,7 +848,7 @@ it 'sends custom header with X-RosetteAPI- prefix' do params = DocumentParameters.new - params.content = 'Por favor Senorita, says the man.?' + params.content = @content params.custom_headers = { 'X-RosetteAPI-App' => 'ruby-app' } response = RosetteAPI.new('0123456789').get_language(params) @@ -875,7 +875,7 @@ .to_return(status: 200, body: '{"test": "language"}', headers: {}) params = DocumentParameters.new - params.content = 'Por favor Senorita, says the man.?' + params.content = @content params.custom_headers = { 'X-BabelStreetAPI-App' => 'ruby-app' } response = RosetteAPI.new('0123456789').get_language(params) @@ -903,7 +903,7 @@ .to_return(status: 200, body: '{"test": "language"}', headers: {}) params = DocumentParameters.new - params.content = 'Por favor Senorita, says the man.?' + params.content = @content params.custom_headers = { 'X-RosetteAPI-App' => 'ruby-app', 'X-BabelStreetAPI-App' => 'ruby-app' @@ -915,7 +915,7 @@ it 'test custom_headers is invalid' do params = DocumentParameters.new - params.content = 'Por favor Senorita, says the man.?' + params.content = @content params.custom_headers = { 'test' => 'ruby-app' } expect { RosetteAPI.new('0123456789').get_language(params) } .to raise_error(RosetteAPIError) From 748ba8abd0927dbce4ed6ffdaf85749aa9031192 Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 17:30:34 +0100 Subject: [PATCH 23/24] BX-68618: fix record-similarity examples --- examples/record_similarity.rb | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/examples/record_similarity.rb b/examples/record_similarity.rb index 05ff371..f56d74e 100644 --- a/examples/record_similarity.rb +++ b/examples/record_similarity.rb @@ -59,9 +59,7 @@ format: 'MMddyyyy' }, addr_field => '123 Roadlane Ave', - str_field => { - data: 'software engineer' - } + str_field => 'software engineer' }, { primary_name_field => { @@ -70,12 +68,8 @@ dob_field => { date: dob_hyphen }, - number_field => { - data: 47 - }, - bool_field => { - data: false - } + number_field => 47, + bool_field => false } ], right: [ @@ -87,12 +81,8 @@ dob_field => { date: dob_hyphen }, - str_field => { - data: 'manager' - }, - bool_field => { - data: true - } + str_field => 'manager', + bool_field => true }, { primary_name_field => 'Ivan R', @@ -107,12 +97,8 @@ road: 'Roadlane Ave', cityDistrict: 'Alpha' }, - number_field => { - data: 72 - }, - bool_field => { - data: true - } + number_field => 72, + bool_field => true } ] } From 72da7499f85af27bfe7c7c18b00c2f4a592bbb4b Mon Sep 17 00:00:00 2001 From: Adam Soos Date: Fri, 6 Mar 2026 17:51:15 +0100 Subject: [PATCH 24/24] BX-68618: fixing code smells --- lib/document_parameters.rb | 4 +- lib/request_builder.rb | 96 ++++++++++++++++++++++++-------------- 2 files changed, 64 insertions(+), 36 deletions(-) diff --git a/lib/document_parameters.rb b/lib/document_parameters.rb index d810bb5..cef0268 100644 --- a/lib/document_parameters.rb +++ b/lib/document_parameters.rb @@ -55,8 +55,8 @@ def validate_params raise BadRequestFormatError.new(content_msg) elsif [@content, @content_uri, @file_path].all?(&:nil?) raise BadRequestFormatError.new(no_content_msg) - elsif @rosette_options - raise BadRequestError.new(opt_msg) unless @rosette_options.is_a? Hash + elsif @rosette_options && !@rosette_options.is_a?(Hash) + raise BadRequestError.new(opt_msg) end end diff --git a/lib/request_builder.rb b/lib/request_builder.rb index 28914c9..105d4e7 100644 --- a/lib/request_builder.rb +++ b/lib/request_builder.rb @@ -8,6 +8,34 @@ # This class handles all Analytics API requests. class RequestBuilder + CONNECTION_ERROR_CODE = 'connectionError' + CONNECTION_ERROR_MESSAGE = 'Failed to establish connection with Analytics server.' + + INVALID_HEADER_CODE = 'invalidHeader' + INVALID_HEADER_MESSAGE = 'Custom header must begin with "X-RosetteAPI-" or "X-BabelStreetAPI-"' + + READ_MULTIPART_ERROR_CODE = 'readMultipartError' + + HEADER_API_KEY = 'X-BabelStreetAPI-Key' + HEADER_CONTENT_TYPE = 'Content-Type' + HEADER_ACCEPT = 'Accept' + HEADER_USER_AGENT = 'User-Agent' + HEADER_BINDING_LEGACY = 'X-RosetteAPI-Binding' + HEADER_BINDING = 'X-BabelStreetAPI-Binding' + HEADER_BINDING_VERSION_LEGACY = 'X-RosetteAPI-Binding-Version' + HEADER_BINDING_VERSION = 'X-BabelStreetAPI-Binding-Version' + + BINDING_NAME = 'ruby' + + CONTENT_TYPE_JSON = 'application/json' + CONTENT_TYPE_TEXT_PLAIN = 'text/plain' + ACCEPT_JSON = 'application/json' + + MULTIPART_FORM_DATA = 'multipart/form-data' + + CUSTOM_HEADER_PREFIX_ROSETTE = /^X-RosetteAPI-/ + CUSTOM_HEADER_PREFIX_BABELSTREET = /^X-BabelStreetAPI-/ + # Alternate API URL attr_reader :alternate_url # API HTTP client @@ -50,8 +78,8 @@ def prepare_plain_request(params) # Not ideal. Consider switching to a different library. # https://stackoverflow.com/a/11802674 raise RosetteAPIError.new( - 'connectionError', - 'Failed to establish connection with Analytics server.' + CONNECTION_ERROR_CODE, + CONNECTION_ERROR_MESSAGE ) end @@ -60,32 +88,32 @@ def prepare_plain_request(params) if custom_headers keys_array = custom_headers.keys keys_array.each do |key| - if key.to_s =~ /^X-RosetteAPI-/ || key.to_s =~ /^X-BabelStreetAPI-/ + if key.to_s =~ CUSTOM_HEADER_PREFIX_ROSETTE || key.to_s =~ CUSTOM_HEADER_PREFIX_BABELSTREET request[key] = custom_headers[key] else raise RosetteAPIError.new( - 'invalidHeader', - 'Custom header must begin with "X-RosetteAPI-" or "X-BabelStreetAPI-"' + INVALID_HEADER_CODE, + INVALID_HEADER_MESSAGE ) end end params.delete 'customHeaders' end - request['X-BabelStreetAPI-Key'] = @user_key - request['Content-Type'] = 'application/json' - request['Accept'] = 'application/json' - request['User-Agent'] = @user_agent - request['X-RosetteAPI-Binding'] = 'ruby' - request['X-BabelStreetAPI-Binding'] = 'ruby' - request['X-RosetteAPI-Binding-Version'] = @binding_version - request['X-BabelStreetAPI-Binding-Version'] = @binding_version + request[HEADER_API_KEY] = @user_key + request[HEADER_CONTENT_TYPE] = CONTENT_TYPE_JSON + request[HEADER_ACCEPT] = ACCEPT_JSON + request[HEADER_USER_AGENT] = @user_agent + request[HEADER_BINDING_LEGACY] = BINDING_NAME + request[HEADER_BINDING] = BINDING_NAME + request[HEADER_BINDING_VERSION_LEGACY] = @binding_version + request[HEADER_BINDING_VERSION] = @binding_version request.body = params.to_json [@http_client, request] end - # Prepares a multipart/form-data POST request for Anaytyics API. + # Prepares a multipart/form-data POST request for Analytics API. # # ==== Attributes # @@ -102,7 +130,7 @@ def prepare_multipart_request(params) post_body << "--#{boundary}\r\n" post_body << 'Content-Disposition: form-data; name="content"; ' \ "filename=\"#{File.basename(params['filePath'])}\"\r\n" - post_body << "Content-Type: text/plain\r\n\r\n" + post_body << "#{HEADER_CONTENT_TYPE}: #{CONTENT_TYPE_TEXT_PLAIN}\r\n\r\n" post_body << text # Add the request data @@ -111,7 +139,7 @@ def prepare_multipart_request(params) post_body << "\r\n\r\n--#{boundary}\r\n" post_body << "Content-Disposition: form-data; name=\"request\"\r\n" - post_body << "Content-Type: application/json\r\n\r\n" + post_body << "#{HEADER_CONTENT_TYPE}: #{CONTENT_TYPE_JSON}\r\n\r\n" post_body << request_file post_body << "\r\n\r\n--#{boundary}--\r\n" @@ -123,8 +151,8 @@ def prepare_multipart_request(params) # Not ideal. Consider switching to a different library. # https://stackoverflow.com/a/11802674 raise RosetteAPIError.new( - 'connectionError', - 'Failed to establish connection with Analytics server.' + CONNECTION_ERROR_CODE, + CONNECTION_ERROR_MESSAGE ) end @@ -132,26 +160,26 @@ def prepare_multipart_request(params) unless params['customHeaders'].nil? keys_array = params['customHeaders'].keys keys_array.each do |k| - if k.to_s =~ /^X-RosetteAPI-/ || key.to_s =~ /^X-BabelStreetAPI-/ + if k.to_s =~ CUSTOM_HEADER_PREFIX_ROSETTE || k.to_s =~ CUSTOM_HEADER_PREFIX_BABELSTREET request.add_field k, params['customHeaders'][k] else raise RosetteAPIError.new( - 'invalidHeader', - 'Custom header must begin with "X-RosetteAPI-" or "X-BabelStreetAPI-"' + INVALID_HEADER_CODE, + INVALID_HEADER_MESSAGE ) end end params.delete 'customHeaders' end - request.add_field 'Content-Type', - "multipart/form-data; boundary=#{boundary}" - request.add_field 'User-Agent', @user_agent - request.add_field 'X-BabelStreetAPI-Key', @user_key - request.add_field 'X-RosetteAPI-Binding', 'ruby' - request.add_field 'X-BabelStreetAPI-Binding', 'ruby' - request.add_field 'X-RosetteAPI-Binding-Version', @binding_version - request.add_field 'X-BabelStreetAPI-Binding-Version', @binding_version + request.add_field HEADER_CONTENT_TYPE, + "#{MULTIPART_FORM_DATA}; boundary=#{boundary}" + request.add_field HEADER_USER_AGENT, @user_agent + request.add_field HEADER_API_KEY, @user_key + request.add_field HEADER_BINDING_LEGACY, BINDING_NAME + request.add_field HEADER_BINDING, BINDING_NAME + request.add_field HEADER_BINDING_VERSION_LEGACY, @binding_version + request.add_field HEADER_BINDING_VERSION, @binding_version request.body = post_body.join [@http_client, request] @@ -165,7 +193,7 @@ def read_multipart_file(file_path) return f.read end rescue StandardError => e - raise RosetteAPIError.new('readMultipartError', e) + raise RosetteAPIError.new(READ_MULTIPART_ERROR_CODE, e) end # Sends a GET request to Analytics API. @@ -179,12 +207,12 @@ def send_get_request # Not ideal. Consider switching to a different library. # https://stackoverflow.com/a/11802674 raise RosetteAPIError.new( - 'connectionError', - 'Failed to establish connection with Analytics server.' + CONNECTION_ERROR_CODE, + CONNECTION_ERROR_MESSAGE ) end - request['X-BabelStreetAPI-Key'] = @user_key - request['User-Agent'] = @user_agent + request[HEADER_API_KEY] = @user_key + request[HEADER_USER_AGENT] = @user_agent get_response @http_client, request end