Skip to content

Commit

Permalink
Create database infrastructure and related routes
Browse files Browse the repository at this point in the history
  • Loading branch information
soumyaray committed Oct 29, 2017
1 parent f71f0b6 commit 8c59afa
Show file tree
Hide file tree
Showing 27 changed files with 443 additions and 111 deletions.
5 changes: 3 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
config/*.yml
coverage/
config/secrets.yml
coverage/
*.db
8 changes: 8 additions & 0 deletions .pryrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
require 'hirb'

Hirb.enable

old_print = Pry.config.print
Pry.config.print = proc do |*args|
Hirb::View.view_or_page_output(args[1]) || old_print.call(*args)
end
38 changes: 24 additions & 14 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -10,21 +10,31 @@ gem 'econfig'
gem 'puma'
gem 'roda'

# Database related
gem 'hirb'
gem 'sequel'

# Data gems
gem 'dry-struct'
gem 'dry-types'

# Testing gems
gem 'minitest'
gem 'minitest-rg'
gem 'pry'
gem 'rack-test'
gem 'rake'
gem 'simplecov'
gem 'vcr'
gem 'webmock'

# Quality testing gems
gem 'flog'
gem 'reek'
gem 'rubocop'
group :test do
gem 'minitest'
gem 'minitest-rg'
gem 'rack-test'
gem 'rake'
gem 'simplecov'
gem 'vcr'
gem 'webmock'
end

group :development, :test do
gem 'sqlite3'

gem 'pry'
gem 'rerun'

gem 'flog'
gem 'reek'
gem 'rubocop'
end
18 changes: 18 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,13 @@ GEM
inflecto (~> 0.0.0, >= 0.0.2)
econfig (2.0.0)
equalizer (0.0.11)
ffi (1.9.18)
flog (4.6.1)
path_expander (~> 1.0)
ruby_parser (~> 3.1, > 3.1.0)
sexp_processor (~> 4.8)
hashdiff (0.3.7)
hirb (0.7.3)
http (2.2.2)
addressable (~> 2.3)
http-cookie (~> 1.0)
Expand All @@ -66,6 +68,10 @@ GEM
ice_nine (0.11.2)
inflecto (0.0.2)
json (2.1.0)
listen (3.1.5)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
ruby_dep (~> 1.2)
method_source (0.8.2)
minitest (5.10.3)
minitest-rg (5.2.0)
Expand All @@ -86,10 +92,15 @@ GEM
rainbow (2.2.2)
rake
rake (12.1.0)
rb-fsevent (0.10.2)
rb-inotify (0.9.10)
ffi (>= 0.5.0, < 2)
reek (4.7.2)
codeclimate-engine-rb (~> 0.4.0)
parser (>= 2.4.0.0, < 2.5)
rainbow (~> 2.0)
rerun (0.11.0)
listen (~> 3.0)
roda (3.1.0)
rack
rubocop (0.50.0)
Expand All @@ -100,15 +111,18 @@ GEM
ruby-progressbar (~> 1.7)
unicode-display_width (~> 1.0, >= 1.0.1)
ruby-progressbar (1.9.0)
ruby_dep (1.5.0)
ruby_parser (3.10.1)
sexp_processor (~> 4.9)
safe_yaml (1.0.4)
sequel (5.1.0)
sexp_processor (4.10.0)
simplecov (0.15.1)
docile (~> 1.1.0)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-html (0.10.2)
sqlite3 (1.3.13)
thread_safe (0.3.6)
unf (0.1.4)
unf_ext
Expand All @@ -133,6 +147,7 @@ DEPENDENCIES
dry-types
econfig
flog
hirb
http
minitest
minitest-rg
Expand All @@ -141,9 +156,12 @@ DEPENDENCIES
rack-test
rake
reek
rerun
roda
rubocop
sequel
simplecov
sqlite3
vcr
webmock

Expand Down
25 changes: 25 additions & 0 deletions Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,28 @@ namespace :quality do
sh "flog #{CODE}"
end
end

namespace :db do
require_relative 'config/environment.rb' # load config info
require 'sequel' # TODO: remove after create orm

Sequel.extension :migration
app = CodePraise::Api

desc 'Run migrations'
task :migrate do
puts "Migrating #{app.environment} database to latest"
Sequel::Migrator.run(app.DB, 'infrastructure/db/migrations')
end

desc 'Delete dev or test database file'
task :wipe do
if app.environment == :production
puts 'Cannot wipe production database!'
return
end

FileUtils.rm(app.config.db_filename)
puts "Deleted #{app.config.db_filename}"
end
end
40 changes: 18 additions & 22 deletions app.rb
Original file line number Diff line number Diff line change
@@ -1,50 +1,46 @@
# frozen_string_literal: true

require 'roda'
require 'econfig'
require_relative 'lib/init.rb'

module CodePraise
# Web API
class Api < Roda
plugin :environments
plugin :json
plugin :halt

extend Econfig::Shortcut
Econfig.env = environment.to_s
Econfig.root = '.'

route do |routing|
app = Api
config = Api.config

# GET / request
routing.root do
{ 'message' => "CodePraise API v0.1 up in #{app.environment}" }
{ 'message' => "CodePraise API v0.1 up in #{app.environment} mode" }
end

routing.on 'api' do
# /api/v0.1 branch
routing.on 'v0.1' do
# /api/v0.1/:ownername/:repo_name branch
routing.on 'repo', String, String do |ownername, repo_name|
github_api = Github::Api.new(config.gh_token)
repo_mapper = Github::RepoMapper.new(github_api)
begin
repo = repo_mapper.load(ownername, repo_name)
rescue StandardError
routing.halt(404, error: 'Repo not found')
end

# GET /api/v0.1/:ownername/:repo_name request
# GET /api/v0.1/repo/:ownername/:repo_name request
routing.is do
{ repo: { owner: repo.owner.to_h, size: repo.size } }
repo = Database::ORM[Entity::Repo]
.find_full_name(ownername, repo_name)

routing.halt(404, error: 'Repository not found') unless repo
repo.to_h
end

# GET /api/v0.1/:ownername/:repo_name/contributors request
routing.get 'contributors' do
{ contributors: repo.contributors.map(&:to_h) }
# post '/api/v0.1/repo/:ownername/:repo_name
routing.post do
github_repo = Github::RepoMapper.new(app.config)
begin
repo = github_repo.load(ownername, repo_name)
rescue StandardError
routing.halt(404, error: 'Repository not found')
end

stored_repo = Database::ORM[Entity::Repo].find_or_create(repo)
stored_repo.to_h
end
end
end
Expand Down
6 changes: 6 additions & 0 deletions config/app.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
development:
db_filename: infrastructure/db/dev.db

test:
db_filename: infrastructure/db/test.db
39 changes: 39 additions & 0 deletions config/environment.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# frozen_string_literal: true

require 'roda'
require 'econfig'

module CodePraise
# Configuration for the API
class Api < Roda
plugin :environments

extend Econfig::Shortcut
Econfig.env = environment.to_s
Econfig.root = '.'

configure :development do
# Allows running reload! in pry to restart entire app
def self.reload!
exec 'pry -r ./spec/test_load_all'
end
end

configure :development, :test do
ENV['DATABASE_URL'] = 'sqlite://' + config.db_filename
end

configure :production do
# Use Heroku's DATABASE_URL environment variable
end

configure do
require 'sequel'
DB = Sequel.connect(ENV['DATABASE_URL'])

def self.DB
DB
end
end
end
end
3 changes: 3 additions & 0 deletions config/init.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# frozen_string_literal: false

require_relative 'environment.rb'
6 changes: 5 additions & 1 deletion config/secrets.yml.example
Original file line number Diff line number Diff line change
@@ -1,2 +1,6 @@
---
gh_token: <personal access token for github api>
development:
gh_token: <personal token for Github API>

test:
gh_token: <personal token for Github API>
4 changes: 3 additions & 1 deletion entities/contributor.rb → entities/collaborator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
module CodePraise
module Entity
# Domain entity object for git contributors
class Contributor < Dry::Struct
class Collaborator < Dry::Struct
attribute :id, Types::Int.optional
attribute :origin_id, Types::Strict::Int
attribute :username, Types::Strict::String
attribute :email, Types::Strict::String.optional
end
Expand Down
9 changes: 6 additions & 3 deletions entities/repo.rb
Original file line number Diff line number Diff line change
@@ -1,15 +1,18 @@
# frozen_string_literal: false

require_relative 'contributor.rb'
require_relative 'collaborator.rb'

module CodePraise
module Entity
# Domain entity object for any git repos
class Repo < Dry::Struct
attribute :id, Types::Int.optional
attribute :origin_id, Types::Strict::Int
attribute :name, Types::Strict::String
attribute :size, Types::Strict::Int
attribute :owner, Contributor
attribute :git_url, Types::Strict::String
attribute :contributors, Types::Strict::Array.member(Contributor)
attribute :owner, Collaborator
attribute :contributors, Types::Strict::Array.member(Collaborator)
end
end
end
20 changes: 20 additions & 0 deletions infrastructure/db/migrations/001_repos_create.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# frozen_string_literal: true

require 'sequel'

Sequel.migration do
change do
create_table(:repos) do
primary_key :id
Integer :origin_id, unique: true
foreign_key :owner_id, :collaborators

String :name
String :git_url
Integer :size

DateTime :created_at
DateTime :updated_at
end
end
end
17 changes: 17 additions & 0 deletions infrastructure/db/migrations/002_collaborators_create.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
# frozen_string_literal: true

require 'sequel'

Sequel.migration do
change do
create_table(:collaborators) do
primary_key :id
Integer :origin_id, unique: true
String :username, unique: true, null: false
String :email

DateTime :created_at
DateTime :updated_at
end
end
end
14 changes: 14 additions & 0 deletions infrastructure/db/migrations/003_repos_contributors_join_create.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# frozen_string_literal: true

require 'sequel'

Sequel.migration do
change do
create_table(:repos_contributors) do
foreign_key :repo_id, :repos
foreign_key :collaborator_id, :collaborators
primary_key [:repo_id, :collaborator_id]
index [:repo_id, :collaborator_id]
end
end
end
Loading

0 comments on commit 8c59afa

Please sign in to comment.