Things I Learned Building a Gem

Tech: Ruby, Rubocop, Splunk, Docker, CI, Rspec, TigerConnect

Challenge: a particular component (HIPAA-compliant text messaging) of an application proved valuable in other applications. The code was organically customized and integrated into several applications. Eventually, we had a clear case to pull out the duplicated code (DRY!) from the various repos, standardize, and package as a gem.

What I learned:

  1. send is a Ruby reserved keyword (for dynamically calling method names)
  2. How to pass creds for a private GitLab/GitHub repo into Gemfile, so the gem can be implemented (gitlab-ci-token)
  3. After updating the gem, and using bundle update in an app implementing the gem, sometimes you must force pull from the private repo to get the latest changes.
  4. GitLab CI w/ RSpec, Rubocop!
  5. garbage collection https://blog.codeship.com/visualizing-garbage-collection-ruby-python/
  6. Splunk search is NOT case sensitive!

 

And topics/pitfalls for further research:

  1. Oddly, my Mail settings took in the local environment, but not in the application Docker image utilizing the gem
  2. In the local environment, one dynamic require all in the main module worked nicely for files in ./lib. However, needed multiple require statements (one for each file) when implementing the gem elsewhere.
  3. Ignoring Gemfile.lock in commits was helpful when trying to implement gem in applications.

 

Reference:

Generic Gem Template

Building a Gem Guide

Naming, Versioning, Dependencies, etc.

Bundler – creating gem

GitLab Token

published_blue_ribbon

Published!

Tech: Angular, Angular-Cli, Docker, nginx

Challenge: the challenge was making & releasing the app. Utilized by the American Association of Colleges of Osteopathic Medicine for studying empathy, I am happy to report no bugs or issues since the release approximately 1 year ago! The icing on the cake is a small acknowledgment in a published research paper. The pudding..

published

 

 

 

 

 

published_pomee

 

Ruby Template => Data to JSON

Tech: Ruby, JSON, Docker

Challenge: data for daily reporting is captured in a class instance variable hash. If/when the docker container restarts, I want the data, which is regularly written to a JSON file, to be reloaded into the @hash.

Code:

def initialize

if FileTest.exists?('./data.json')

@instance_var_hash = JSON.parse(File.read('./data.json'))

else

@instance_var_hash = { ... }

end

end

Potential Pitfall: when sandboxing, I had an instance variable hash with symbol keys. When reading in the JSON file and writing to my instance variable, I generated an error in my methods… :key in original instance variable versus 'key' from incoming JSON.
 
Does the JSON file exist?

if FileTest.exists?('./file_name.json')

Read file

JSON.parse(File.read('./file_name.json'))

Open the file & write

File.open('./temp.json', 'w') do |f|

f.write(JSON.pretty_generate(object))

end

 
Reference:

https://github.com/lukekedz/ruby_json_template

http://ruby-doc.org/stdlib-1.9.3/libdoc/json/rdoc/JSON.html

http://ruby-doc.org/core-2.2.0/FileTest.html

https://stackoverflow.com/questions/5507512/how-to-write-to-a-json-file-in-the-correct-format/5507535

https://hackhands.com/ruby-read-json-file-hash/

 

App Launch! ==> Redis RRF Data Cache

Tech: Redis, Ruby, Docker, Epic, AllScripts, SHA-2

Challenge/Description: create a central data repository for querying & discovering if a current emergency room patient has been discharged from any hospital network campus (read: multiple data sources!) within the past 30 days. If the current ER patient’s hashed data keys match a Redis key, then the patient is flagged as a Readmit Risk (RRF) on the ER Dashing dashboard.

 

Architecture:

readmit_risk_flag_for_blog_post

Error! Is port 5432 allocated?

Tech: PostgreSQL, Docker, Rails, Ruby, grep

Challenge: seeing error messages when launching PostgreSQL. I have been seeing this in a few different scenarios. One is when Docker is/was running a PG container, and the computer has slept or been closed. 

HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.

LOG:  could not bind IPv4 socket: Address already in use</code>

HINT:  Is another postmaster already running on port 5432? If not, wait a few seconds and retry.

WARNING:  could not create listen socket for "localhost"

FATAL:  could not create any TCP/IP sockets

LOG:  database system is shut down

Code:

In the case of a Docker/Rails Server conflict, I have been grepping for PG instances and shutting them down.

ps -ef | grep postgres

What’s going on here? …

ps = process select

-ef = every process

Let’s take out PG and start over…

sudo pkill -u postgres

 

Challenge: another time, a similar error when the Rails database file was not fully configured.

could not connect to server: No such file or directory
Is the server running locally and accepting
connections on Unix domain socket "/var/pgsql_socket/.s.PGSQL.5432"?

Code:

I tried the above, encountered the same problem, and then looked to the database.yml file:

simply add… host: localhost

 

Reference:

http://stackoverflow.com/questions/18721149/check-if-a-particular-service-is-running-on-ubuntu

http://askubuntu.com/questions/547434/how-to-nicely-stop-all-postgres-processes

App Launch! ==> {{ng2}} Web App

Tech Stack: Angular2, ng-cli, TypeScript, Bootstrap, Docker, Nginx, ColdFusion, Gitlab

Description: “single page” survey web application

aacom_arch

 

Key Components:

  1. Survey sent to several universities… url extension (survey.baseurl.edu/oxford) sets up dynamic content specific to that university/participant
  2. Survey content broken into pages… content is displayed depending on variable currentPage, which is incremented/decremented upon user clicking ‘next’ or ‘previous’
  3. Participant is asked to opt-in to return to unanswered questions… variable userFirstPass used to determine displayed content, along with currentPage
  4. Custom checkboxes with corresponding ng2 code to add/remove selections from array, which is attribute of survey data object, using javascript Array.prototype.includes()

aacom_custom_checkbox

Challenges:

  1. Initially, previous/next navigation buttons simply incremented/decremented currentPage by 1. As the “simple” one-page survey app progressed, better logic was needed to properly navigate. An argument was added to the function in certain cases, thus ensuring the correct content. Examples:
    • Tracking a participant’s time to complete the survey. We pass ‘start’ as the argument on the click of ‘next’ prior to the first question, and use Date.now() to capture the start time.
    • Validating age input. We pass ‘age’ as an indicator to validate the participant’s age input. 
  2. Capturing the participant’s unanswered questions. We apply an attribute to the question object, ‘answered’. When the participant gets to the end of the survey, a function is kicked off that iterates over the survey object attributes’ answers. If the attribute lacks an answer, then the question attribute ‘answered’ remains false. On the participant’s second pass, only questions with the ‘answered’ attribute of ‘false’ are displayed.
  3. Implementing a Dynamic Progress Bar

 

Related Posts:

Relocating Public JS Files

Application Not Loading in Safari

SSL-Certified Application in Docker

Class/Service into Interface Export

404 Not Found (pt. 2)

 
Read more here ==> Press Release

Error! {{ng2}} 404 Not Found (pt. 2)

Tech: Angular2, Docker, nginx

Challenge: ng2 app designed for all routes/extensions after base URL to redirect to app root. Example… app.website.edu/anyong loads the root app.website.edu/. Working well using ng serve locally, but when deployed to the docker server, any extension is returning a 404 error. See original solution here (pt. 1).

Solution: I believe I was pretty close to the right solution initially, but didn’t quite have the correct code. One small change, and the docker/nginx/ng2 app is properly interpreting and serving url extensions. We remove the error_page 404 catch-all and implement this:

location / {

try_files $uri $uri/ /index.html;

}

 

Error! {{ng2}} 404 Not Found (pt. 1)

Tech: Angular2, Docker, nginx

Challenge: ng2 app designed for all routes/extensions after base URL to redirect to app root. Example… app.website.edu/anyong loads the root app.website.edu/. Working well using ng serve locally, but when deployed to the docker server, any extension is returning a 404 error.

 

(Temporary) Solution: nginx is looking for a folder to match the extension. When it cannot find a match, it returns the error. First, we add a nginx.conf file to Docker, and then configure nginx to deal with the 404 error.

FROM nginx

ADD dist /usr/share/nginx/html

ADD nginx.conf /etc/nginx/nginx.conf

EXPOSE 80

nginx_config

 

Takeaway: this is not the production-ready or most elegant solution. There must be a way to configure nginx along with ng2 to redirect any extension after the base URL. Maybe regex? Temporary fix will be optimized… part 2 published!

{{ng2}} SSL-Certified Application in Docker

Tech: Angular2, Lite-Server, BrowserSync, Docker

Challenge: launch SSL-certified ng2 development instance on Docker

Code:

Two steps…

  1. Configure ng2 bs-config.json file. We create a folder in the js files deploy directory, https_certs. The key & cert values will be mapped in step 2:

ng2_ssl_bs_config

 

2. Map the certification files on the docker server to the ng2 app when launching the app. cli:

docker run --name containername -td -p 6001:6001 -v /var/docker/certs:/deploy/https_certs imagename

 

Reference:

my own post regarding this process with Ruby on Rails!

BrowerSync Options

Reference: Docker

Challenge: creating a “sticky” post, like timezones … a quick reference for useful, but not-as-frequently used Docker commands. 

View Docker logs:

docker logs running_container_name

Container size / memory usage:

docker system df

docker ps -s

CLI in running container:

docker exec -it running_container_name bash

View dettached container log output:

docker attach --sig-proxy=false running_container_name

List specific # of running containers, newest on top:

docker ps --last #

Filter for unused images:

docker images --filter "dangling=true"

Remove all unused images:

docker rmi -f $(docker images --filter "dangling=true")

Remove all non-running containers:

docker rm $(docker ps -a -q) 

Port syntax:

-p exposed_container_port_in_Dockerfile:live_url_access_point_port

 

Reference:

https://aboullaite.me/docker-hacks/