###Goal
- Create a small PORO application that will fetch sample data from API, convert it to given format and save to SQL.
- Write tests for each component of your application using RSpec.
- For testing - create a fake API server that will respond with API samples provided.
Estimated time for completion: 6 - 8 hours
###Business Specification
For this challenge, we want to collect statistics of web site visits, that is provided by an API server, and store it to a MySQL database for later usage.
A sample API server response is located at samples/api_response.json
The API response is an array containing multiple elements, each representing a visit
. Each visit
contains a nested array, called actionDetails
, each element in that array represents a pageview
.
Models
We need the data to be saved into 2 different tables: visits
and pageviews
.
- Create migrations to create those tables.
- Create models
Visit
andPageview
.Visit
is as associated withPageview
with a one-to-many relation. - The API response field names are different from the table column names. These need to be mapped accordingly.
- Please use the mapping structure given below to assign source field values to target database columns.
- Ignore source fields that are not listed in the mapping structure below.
Visits schema and mappings
t.string "evid"
t.string "vendor_site_id"
t.string "vendor_visit_id"
t.string "visit_ip"
t.string "vendor_visitor_id"
visit element
=> visits table
field mapping:
{
'referrerName' => :evid,
'idSite' => :vendor_site_id,
'idVisit' => :vendor_visit_id,
'visitIp' => :visit_ip,
'visitorId' => :vendor_visitor_id
}
evid
column validation
Please clean up the referrerName
response field value before saving, it should validate with following regex:
/\A[A-z0-9]{8}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{4}-[A-z0-9]{12}\z/
Note: If should not contain evid_
.
Pageviews schema and mappings
t.bigint "visit_id"
t.string "title"
t.string "position"
t.text "url"
t.string "time_spent"
t.decimal "timestamp", precision: 14, scale: 3
pageview element
=> pageviews table
field mapping:
{
'url' => :url,
'pageTitle' => :title,
'timeSpent' => :time_spent,
'timestamp' => :timestamp
}
Pageviews order
Pageviews should be sorted by timestamp
field, in ascending order.
Position column
For pageview
you will need to add the position
field which indicates pageview
position in data source array.
Please ensure that pages are unique, and there are no duplicates.
Fake API server
You will need to create a simple Fake API server for handling responses. The server should accept a get request, and respond with the JSON given in samples/api_response.json
. We suggest to use Sinatra for creating a small inline server, but the final solution is up to you.
Setup
Please use the included docker-compose.yml to setup the environment for this challenge. It will spinup a ready-for-work ruby-2.5.5 and mysql containers linking each other.
Create a Gemfile with your required gems, before executing docker-compose up
, as it will attempt to do bundle install
.
###Requirements
- Ruby MRI 2.5+
- Rspec for tests (100% coverage)
- Rubocop for linting ruby code
- Simplecov for code coverage
- ActiveRecord for models (arguable)
- MySQL for database
- Docker + docker-compose for containerization
###Deliverable
A project directory containing app.rb
file, with the call
method inside, that we can run inside Docker:
docker build -t shastic_challenge .
docker run -it -v "$(pwd)"/:/app shastic_challenge
bash# bundle exec -r 'app.rb' -e 'call'
or with Docker compose
docker-compose build
docker-compose up -d
docker-compose exec shastic_challenge bundle exec -r 'app.rb' -e 'call'
Executing above commands should create records in the MySQL database according to specification.
###Things this challenge evaluates
- Application architecture (classes naming and placement, code split)
- How candidate manages requirements of files
- What gems candidate will choose
- What patterns and best practices will be used (SRP, DRY, ServiceObject, Strategy, etc..)
###Goal
Continuing from the application created back in Application Challenge - Level 1:
- Create a Rake task for deploying the application to AWS Lambda, using the ruby AWS SDK.
- Deploy the application to AWS Lambda, and make sure it works.
Estimated time for completion: 6 - 8 hours
Setup
Change docker/app/Dockerfile
image source to lambci/lambda:build-ruby2.5
as it's the closest image to AWS Lambda. You will need to install mysql-devel
package there and copy mysql shared library to lib
folder, in order to make the mysql client work on AWS Lambda.
###Requirements
- Use exactly
lambci/lambda:build-ruby2.5
as source image - Use AWS Lambda for code execution
- Use AWS RDS for MySQL database (use free tier and remember to terminate the DB instance when not using it to avoid any fees)
###Deliverable
A working AWS Lambda function that fetches a sample response from the fake API server (inline) and saves converted data to RDS.
###Things this challenge evaluates
- AWS services knowledge
- Dev Ops skills
- Usage of environment variables