Baby Name Rails App: Part 1 Import Data

Standard
Reading Time: 2 minutes

I guess this is my how-to build a rails app from scratch.

Using Rails 6.0.3.3, ElasticSearch (Searchkick), Sidekiq, Redis, PostgreSQL to build an app to utilize the data.

Find code here.

rails new baby_names -d postgresql -T

Adding Rspec.

# Add gem to Gemfile
gem 'rspec-rails'
# Run bundler
bundle install

# install rspec
rails g rspec:install

# test
rails test

# configure rspec spec/rails_helper.rb
...
require 'simplecov'
require 'simplecov-bamboo'
SimpleCov.start 'rails'
...
# my installation is unique to my setup

Adding Bootstrap, JQuery, Popper.js

yarn add bootstrap jquery popper.js

# edit config/webpack/environment.js

...
const webpack = require("webpack")
const customConfig = require('./custom');

environment.plugins.prepend("Provide", new webpack.ProvidePlugin({
  $: 'jquery/src/jquery',
  jQuery: 'jquery/src/jquery',
  'window.jQuery': 'jquery',
  Popper: ['popper.js', 'default'],
  _: 'underscore'
}))
environment.config.merge(customConfig);
...

Load Bootstrap.css to Rails

# app/assets/stylesheets/application.css.scss add
*= require bootstrap

Database setup.

I use credentials, your setup might be different.

EDITOR="vi" rails credentials:edit

# my format looks like this
development:
  postgres:
    host: localhost
    username: user
    password: secret

test:
  postgres:
    host: localhost
    username: user
    password: secret

production:
  postgres:
    host: localhost
    username: user
    password: secret

My database.yml looks like this:

...
development:
  <<: *default
  host: <%= Rails.application.credentials.dig(:development, :postgres, :host) %>
  username: <%= Rails.application.credentials.dig(:development, :postgres, :username) %>
  password: <%= Rails.application.credentials.dig(:development, :postgres, :password) %>
  database: baby_names_development

test:
  <<: *default
  host: <%= Rails.application.credentials.dig(:test, :postgres, :host) %>
  username: <%= Rails.application.credentials.dig(:test, :postgres, :username) %>
  password: <%= Rails.application.credentials.dig(:test, :postgres, :password) %>
  database: baby_names_test

production:
  <<: *default
  host: <%= Rails.application.credentials.dig(:production, :postgres, :host) %>
  username: <%= Rails.application.credentials.dig(:production, :postgres, :username) %>
  password: <%= Rails.application.credentials.dig(:production, :postgres, :password) %>
  database: baby_names_production

Create Database.

rails db:create

Create Home Page.

rails g controller Home index

# Added root route config/routes.rb
root to: 'home#index'

Create the Name and DataFiles Model.

rails g model Name name:string gender:string{1} amount:integer rank:integer year:integer

rails g model DataFile name:string

rails db:migrate

# If we care about duplicate entries for Names when we do an import that does not use ActiveRecord we can add an index like so:

add_index :names, [:name, :gender, :year], unique: true

Install ActiveStorage.

rails active_storage:install

rails db:migrate

Importing Data

I will be using Jobs, Sidekiq, Redis

Adding Sidekiq

# Gemfile
gem 'sidekiq'

bundle install

Mounting SideKiq::Web

# config/routes.rb

require 'sidekiq/web'
...
mount Sidekiq::Web => '/sidekiq'
...

# Now you can go to localhost:3000/sidekiq to view jobs

Create the ImportNames job.

rails g job ImportNames

Create a controller to upload files.

rails g controller ImportDataFiles index new

Adding and Using postgres-copy to import.

gem 'postgres-copy'

bundle install

Adding logic to the active job

class ImportNamesJob < ApplicationJob
  queue_as :default

  def perform(data_file = nil)
    return nil unless data_file

    data_file.csv_file.open(tmpdir: 'tmp/') do |file|
      Name.copy_from file
    end
  end
end

Triggering the active job when file is uploaded.

# in the create method in the if @data_file.save block
ImportNamesJob.perform_later(@data_file)

I think this is the interesting part to this app the rest will be just graphs and charts. Look at the code and run the app.

rails s
sidekiq

I guess I can do a part 2 where it is just displaying names.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.