St. Baldrick's Ruby SDK
Installation
gem install stbaldricks
Configuration
- The SDK is configured using environment variables.
- Required configurations:
API_ENDPOINT="https://stbaldricks.org/api" API_KEY="abc123"
Usage
Require the gem
require 'stbaldricks'
Configure the log level (optional)
SBF::Client::Configuration.logger.level = ::Logger::WARN
NOTE the SDK does not raise exceptions for failed requests. This is to allow for more complex logic around error scenarios.
- If you would like the client to raise errors by default you can wrap your requests in a helper ``` ruby def request_helper # Yield to the block to execute the request client_response = yield
# If there was an error, raise it to the error handling block if client_response.error? puts "Error received from API. (code: #client_responseclient_response.http_code)" puts JSON.pretty_generate(client_response.to_hash)
raise "Error received from API"
end
# Otherwise simply return the client data client_response.data end
#### Default Entity Actions
##### Lookup
* Use `aggregate` to perform actions like gathering the size of a data set without returning all of the rows
``` ruby
active_donation_count = request_helper {
SBF::Client::Donation.aggregate([status: :active], {id: :count})
}
puts "Beginning number of active donations: #{active_donation_count[:id]}"
- Use
get
to get an entity by its id fieldsruby existing_donation = request_helper { SBF::Client::Donation.get(188) } puts "Donation: #{JSON.pretty_generate(existing_donation.to_hash)}"
Creation
- To create an entity, create the object using
new
and persist the object to the database usingsave
``` ruby # Find a random, active user to use as the recipient existing_participant = request_helper { SBF::Client::Participant.find(SBF::Client::Participant::Status::ACTIVE) }[:results].sample recipient = SBF::Client::Donation::PartialParticipant.new(id: existing_participant.id)
Create a new donor profile. This will be saved at the same time as the donation
donor = SBF::Client::Donation::FullPerson.new( status: SBF::Client::Person::Status::ACTIVE, gender: SBF::Client::Person::Gender::NOT_SELECTED, how_created: SBF::Client::Person::HowCreated::PAYMENT_SPRING_APP, name_pieces: SBF::Client::NamePieces.new( first_name: 'Foo', last_name: 'Testerman' ), email_addresses: { primary: SBF::Client::EmailAddress.new( type: SBF::Client::EmailAddress::Type::PERSONAL, email_address: '[email protected]' ) }, opt_out_settings: { email_mass_online: true } )
Payment details may be provided if the charging is completed.
Otherwise a nonce should be used which will be settled when the donation is saved
payment_details = SBF::Client::Payment::CreditCardDetails.new( authorization_id: 'abc123', cardholder_name: 'Foo Testerman', card_type: 'Visa', expiration_date: '02/2027', card_number: '************1234' )
Create the donation object itself. Status should be active unless this is a submit cash
type donation.
donation = SBF::Client::FullDonation.new( status: SBF::Client::Donation::Status::ACTIVE, amount: 50.00, display_name: 'Test Display Name', is_unrecognized: false, how_created: SBF::Client::Donation::HowCreated::PAYMENT_SPRING_APP, donor: donor, recipient: recipient, payment_details: payment_details )
request_helper { donation.save } puts "Added donation #donationdonation.id"
#### Search Actions
##### Text search
``` ruby
# Find all participants or fundraisers with 'John' in the searchable fields
model_types = [SBF::Client::Search::Type::PARTICIPANT, SBF::Client::Search::Type::FUNDRAISER]
participants_and_fundraisers = request_helper { SBF::Client::Search.find(model_types, 'John')}[:results]
puts JSON.pretty_generate(participants_and_fundraisers)
Filtered Search
# Find all active participants, teams, and fundraisers at the railyard event
railyard_event = request_helper { SBF::Client::Event.find(venue: {location: {name: {like: "%Rail%"}}}, year: 2017) }[:results].first
model_types = [SBF::Client::Search::Type::PARTICIPANT, SBF::Client::Search::Type::TEAM, SBF::Client::Search::Type::FUNDRAISER]
filter = {
and: [
{column: 'status_id', operator: 'equals', value: SBF::Client::Search::Status::ACTIVE},
{column: 'event_id', operator: 'equals', value: railyard_event.id},
{column: 'event_year', operator: 'equals', value: railyard_event.year}
]
}
entities_at_the_railyard = request_helper { SBF::Client::Search.find(model_types, nil, filter, nil, limit: 20) }[:results]
puts JSON.pretty_generate(entities_at_the_railyard)
Geocode Search
# Find all active participants with 10 miles of Lincoln, NE
require 'geocoder'
data = Geocoder::Lookup.get(:google).search("Lincoln, NE").first
lat = data.latitude.round(6)
lon = data.longitude.round(6)
geo_location = {lat: lat, lon: lon, distance: 10}
model_type = SBF::Client::Search::Type::PARTICIPANT
filter = {and: [{column: 'status_id', operator: 'equals', value: SBF::Client::Search::Status::ACTIVE}]}
active_participant_within_10_mi = request_helper { SBF::Client::Search.find(model_type, nil, filter, geo_location, limit: 2) }[:results]
puts JSON.pretty_generate(active_participant_within_10_mi)
Architecture
Component | Location |
---|---|
Endpoints | /lib/stbaldricks/endpoints |
Entities | /lib/stbaldricks/entities |
Enums | /lib/stbaldricks/enums |
Rspec Unit | /spec/unit |
Rspec Integration | /spec/integration |
Endpoints
- Define supported requests that can be made to the SBF API for entities in the client library.
- Extend
SBF::Client::EntityEndpoint
to receive common core action for the entities.- If additional or non-standard functionality is required, actions can be added or overridden.
- Return a response object which will contain an http status code and depending on the code either error details or the expected API response data for a successful request.
Entities
- Object representations of the data sent to and received from the API.
- Top-level entities (those that can be directly requested or modified via the API) inherit from
SBF::Client::TopLevelEntity
.- Supported actions on the entity are defined via
action
andactions
. - Any actions that are disallowed are blocked via
blacklist_action
. - The entities also map to their corresponding endpoint for handling all related API requests.
- Supported actions on the entity are defined via
- Sub-entities should still extend the
SBF::Client::BaseEntity
.
Enums
- Collections of constants to assist with specifying values within a finite list.
Rspec Tests
Tests are broken out into unit and integration tests. Test coverage thresholds are enforced and test additions or modifications are required for nearly any client library change.
More detail on understanding and writing Rspec tests can be found in the Rspec Guide.
Running Tests
- use
rake client:ruby:test:all
to run all tests- use
TESTS={path-to-test} rake client:ruby:test:all
to run specific test(s)
- use