summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGavin Miller <gavingmiller@gmail.com>2014-02-22 19:13:10 -0700
committerGavin Miller <gavingmiller@gmail.com>2014-02-22 19:13:10 -0700
commit18743c5981c59708d4143dfe75a5c111e67355e4 (patch)
tree24901e40807d12df39f1259144f4a9f06127723b
parent1fe046fd801be497f6176a1f882359ffcfaf6ce1 (diff)
parentec7a4537c4559613e65e79ab780041c9666817b9 (diff)
Merge pull request #1 from mokhan/solution
Mergity Mergity Mergity
-rw-r--r--.gitignore18
-rw-r--r--.rspec1
-rw-r--r--.ruby-gemset1
-rw-r--r--.ruby-version1
-rw-r--r--Gemfile19
-rw-r--r--Gemfile.lock114
-rw-r--r--Procfile1
-rw-r--r--README.md2
-rw-r--r--Rakefile6
-rw-r--r--SOLUTION.md35
-rw-r--r--app/controllers/application_controller.rb18
-rw-r--r--app/controllers/concerns/.keep0
-rw-r--r--app/controllers/v1/company_licenses_controller.rb17
-rw-r--r--app/controllers/v1/licenses_controller.rb20
-rw-r--r--app/models/.keep0
-rw-r--r--app/models/company.rb9
-rw-r--r--app/models/concerns/.keep0
-rw-r--r--app/models/license.rb24
-rw-r--r--app/models/license_status.rb16
-rw-r--r--app/models/license_status/active.rb20
-rw-r--r--app/models/license_status/confidential.rb17
-rw-r--r--app/models/license_status/expired.rb18
-rw-r--r--app/models/location.rb3
-rw-r--r--app/models/user.rb11
-rw-r--r--app/models/well_type.rb9
-rw-r--r--app/views/v1/company_licenses/index.jbuilder7
-rw-r--r--app/views/v1/licenses/_company.jbuilder4
-rw-r--r--app/views/v1/licenses/_confidential_company.jbuilder4
-rw-r--r--app/views/v1/licenses/_confidential_well_type.jbuilder5
-rw-r--r--app/views/v1/licenses/_license.jbuilder12
-rw-r--r--app/views/v1/licenses/_location.jbuilder5
-rw-r--r--app/views/v1/licenses/_well_type.jbuilder5
-rw-r--r--app/views/v1/licenses/index.jbuilder7
-rw-r--r--app/views/v1/licenses/show.jbuilder1
-rw-r--r--app/views/v1/shared/_license_statuses.jbuilder5
-rw-r--r--app/views/v1/shared/_well_types.jbuilder7
-rwxr-xr-xbin/acceptance.sh63
-rwxr-xr-xbin/bundle3
-rwxr-xr-xbin/deploy.sh6
-rwxr-xr-xbin/hconsole.sh2
-rwxr-xr-xbin/logs.sh4
-rwxr-xr-xbin/rails4
-rwxr-xr-xbin/rake4
-rwxr-xr-xbin/sample.rb41
-rw-r--r--config.ru4
-rw-r--r--config/application.rb31
-rw-r--r--config/boot.rb4
-rw-r--r--config/database.yml.example13
-rw-r--r--config/environment.rb5
-rw-r--r--config/environments/development.rb25
-rw-r--r--config/environments/production.rb65
-rw-r--r--config/environments/test.rb36
-rw-r--r--config/initializers/backtrace_silencers.rb7
-rw-r--r--config/initializers/filter_parameter_logging.rb4
-rw-r--r--config/initializers/inflections.rb16
-rw-r--r--config/initializers/mime_types.rb5
-rw-r--r--config/initializers/secret_token.rb12
-rw-r--r--config/initializers/session_store.rb3
-rw-r--r--config/initializers/wrap_parameters.rb14
-rw-r--r--config/locales/en.yml23
-rw-r--r--config/routes.rb9
-rw-r--r--config/unicorn.rb20
-rw-r--r--db/migrate/20140221015819_create_licenses.rb7
-rw-r--r--db/migrate/20140221024327_enable_uuid_extension.rb5
-rw-r--r--db/migrate/20140221025310_recreate_licenses.rb8
-rw-r--r--db/migrate/20140221134937_create_companies.rb8
-rw-r--r--db/migrate/20140221135224_add_active_range_to_licenses.rb7
-rw-r--r--db/migrate/20140222032401_add_confidential_to_licenses.rb5
-rw-r--r--db/migrate/20140222051253_create_well_types.rb8
-rw-r--r--db/migrate/20140222052902_add_well_type_to_licenses.rb5
-rw-r--r--db/migrate/20140222053352_create_locations.rb11
-rw-r--r--db/migrate/20140222054248_create_users.rb8
-rw-r--r--db/migrate/20140222055630_add_applicant_to_licenses.rb5
-rw-r--r--db/migrate/20140222145409_add_name_to_users.rb6
-rw-r--r--db/migrate/20140222194718_add_location_id_to_licenses.rb6
-rw-r--r--db/schema.rb59
-rw-r--r--db/seeds.rb7
-rw-r--r--lib/assets/.keep0
-rw-r--r--lib/tasks/.keep0
-rw-r--r--log/.keep0
-rw-r--r--public/404.html58
-rw-r--r--public/422.html58
-rw-r--r--public/500.html57
-rw-r--r--public/favicon.ico0
-rw-r--r--public/robots.txt5
-rw-r--r--spec/controllers/application_controller_spec.rb28
-rw-r--r--spec/controllers/v1/company_licenses_controller_spec.rb40
-rw-r--r--spec/controllers/v1/licenses_controller_spec.rb46
-rw-r--r--spec/models/company_spec.rb31
-rw-r--r--spec/models/license_spec.rb88
-rw-r--r--spec/models/license_status/active_spec.rb17
-rw-r--r--spec/models/license_status/confidential_spec.rb17
-rw-r--r--spec/models/license_status/expired_spec.rb16
-rw-r--r--spec/models/license_status_spec.rb29
-rw-r--r--spec/models/user_spec.rb25
-rw-r--r--spec/routing/company_licenses_routing_spec.rb8
-rw-r--r--spec/routing/licenses_routing_spec.rb12
-rw-r--r--spec/spec_helper.rb45
-rw-r--r--spec/views/v1/company_licenses/index.json.jbuilder_spec.rb58
-rw-r--r--spec/views/v1/licenses/index.json.jbuilder_spec.rb58
-rw-r--r--spec/views/v1/licenses/show.json.jbuilder_spec.rb80
-rw-r--r--vendor/assets/javascripts/.keep0
-rw-r--r--vendor/assets/stylesheets/.keep0
103 files changed, 1795 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..fe31e01
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,18 @@
+# See https://help.github.com/articles/ignoring-files for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile '~/.gitignore_global'
+
+# Ignore bundler config.
+/.bundle
+
+# Ignore the default SQLite database.
+/db/*.sqlite3
+/db/*.sqlite3-journal
+
+# Ignore all logfiles and tempfiles.
+/log/*.log
+/tmp
+database.yml
+vendor/bundle
diff --git a/.rspec b/.rspec
new file mode 100644
index 0000000..4e1e0d2
--- /dev/null
+++ b/.rspec
@@ -0,0 +1 @@
+--color
diff --git a/.ruby-gemset b/.ruby-gemset
new file mode 100644
index 0000000..d86cdc7
--- /dev/null
+++ b/.ruby-gemset
@@ -0,0 +1 @@
+code-challenge
diff --git a/.ruby-version b/.ruby-version
new file mode 100644
index 0000000..9304515
--- /dev/null
+++ b/.ruby-version
@@ -0,0 +1 @@
+ruby-2.1.0
diff --git a/Gemfile b/Gemfile
new file mode 100644
index 0000000..15bdfc8
--- /dev/null
+++ b/Gemfile
@@ -0,0 +1,19 @@
+source 'https://rubygems.org'
+ruby '2.1.0'
+
+gem 'rails', '4.0.3'
+gem 'jbuilder', '~> 1.2'
+gem 'pg'
+
+group :doc do
+ # bundle exec rake doc:rails generates the API under doc/api.
+ gem 'sdoc', require: false
+end
+
+group :development, :test do
+ gem 'rspec-rails'
+end
+
+group :production do
+ gem 'unicorn'
+end
diff --git a/Gemfile.lock b/Gemfile.lock
new file mode 100644
index 0000000..860c002
--- /dev/null
+++ b/Gemfile.lock
@@ -0,0 +1,114 @@
+GEM
+ remote: https://rubygems.org/
+ specs:
+ actionmailer (4.0.3)
+ actionpack (= 4.0.3)
+ mail (~> 2.5.4)
+ actionpack (4.0.3)
+ activesupport (= 4.0.3)
+ builder (~> 3.1.0)
+ erubis (~> 2.7.0)
+ rack (~> 1.5.2)
+ rack-test (~> 0.6.2)
+ activemodel (4.0.3)
+ activesupport (= 4.0.3)
+ builder (~> 3.1.0)
+ activerecord (4.0.3)
+ activemodel (= 4.0.3)
+ activerecord-deprecated_finders (~> 1.0.2)
+ activesupport (= 4.0.3)
+ arel (~> 4.0.0)
+ activerecord-deprecated_finders (1.0.3)
+ activesupport (4.0.3)
+ i18n (~> 0.6, >= 0.6.4)
+ minitest (~> 4.2)
+ multi_json (~> 1.3)
+ thread_safe (~> 0.1)
+ tzinfo (~> 0.3.37)
+ arel (4.0.2)
+ atomic (1.1.14)
+ builder (3.1.4)
+ diff-lcs (1.2.5)
+ erubis (2.7.0)
+ hike (1.2.3)
+ i18n (0.6.9)
+ jbuilder (1.5.3)
+ activesupport (>= 3.0.0)
+ multi_json (>= 1.2.0)
+ json (1.8.1)
+ kgio (2.9.2)
+ mail (2.5.4)
+ mime-types (~> 1.16)
+ treetop (~> 1.4.8)
+ mime-types (1.25.1)
+ minitest (4.7.5)
+ multi_json (1.8.4)
+ pg (0.17.1)
+ polyglot (0.3.4)
+ rack (1.5.2)
+ rack-test (0.6.2)
+ rack (>= 1.0)
+ rails (4.0.3)
+ actionmailer (= 4.0.3)
+ actionpack (= 4.0.3)
+ activerecord (= 4.0.3)
+ activesupport (= 4.0.3)
+ bundler (>= 1.3.0, < 2.0)
+ railties (= 4.0.3)
+ sprockets-rails (~> 2.0.0)
+ railties (4.0.3)
+ actionpack (= 4.0.3)
+ activesupport (= 4.0.3)
+ rake (>= 0.8.7)
+ thor (>= 0.18.1, < 2.0)
+ raindrops (0.13.0)
+ rake (10.1.1)
+ rdoc (4.1.1)
+ json (~> 1.4)
+ rspec-core (2.14.7)
+ rspec-expectations (2.14.5)
+ diff-lcs (>= 1.1.3, < 2.0)
+ rspec-mocks (2.14.6)
+ rspec-rails (2.14.1)
+ actionpack (>= 3.0)
+ activemodel (>= 3.0)
+ activesupport (>= 3.0)
+ railties (>= 3.0)
+ rspec-core (~> 2.14.0)
+ rspec-expectations (~> 2.14.0)
+ rspec-mocks (~> 2.14.0)
+ sdoc (0.4.0)
+ json (~> 1.8)
+ rdoc (~> 4.0, < 5.0)
+ sprockets (2.11.0)
+ hike (~> 1.2)
+ multi_json (~> 1.0)
+ rack (~> 1.0)
+ tilt (~> 1.1, != 1.3.0)
+ sprockets-rails (2.0.1)
+ actionpack (>= 3.0)
+ activesupport (>= 3.0)
+ sprockets (~> 2.8)
+ thor (0.18.1)
+ thread_safe (0.1.3)
+ atomic
+ tilt (1.4.1)
+ treetop (1.4.15)
+ polyglot
+ polyglot (>= 0.3.1)
+ tzinfo (0.3.38)
+ unicorn (4.8.2)
+ kgio (~> 2.6)
+ rack
+ raindrops (~> 0.7)
+
+PLATFORMS
+ ruby
+
+DEPENDENCIES
+ jbuilder (~> 1.2)
+ pg
+ rails (= 4.0.3)
+ rspec-rails
+ sdoc
+ unicorn
diff --git a/Procfile b/Procfile
new file mode 100644
index 0000000..9c82374
--- /dev/null
+++ b/Procfile
@@ -0,0 +1 @@
+web: bundle exec unicorn -p $PORT -c ./config/unicorn.rb
diff --git a/README.md b/README.md
index a10a0e0..c6ec8bb 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-### Problem Description
+### Problem Description [SOLUTION](SOLUTION.md)
#### Background
diff --git a/Rakefile b/Rakefile
new file mode 100644
index 0000000..2ef3c94
--- /dev/null
+++ b/Rakefile
@@ -0,0 +1,6 @@
+# Add your own tasks in files placed in lib/tasks ending in .rake,
+# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
+
+require File.expand_path('../config/application', __FILE__)
+
+CodeChallengeMo::Application.load_tasks
diff --git a/SOLUTION.md b/SOLUTION.md
new file mode 100644
index 0000000..21f2934
--- /dev/null
+++ b/SOLUTION.md
@@ -0,0 +1,35 @@
+### Solution
+
+This solution is hosted on heroku at: [http://damp-scrubland-3368.herokuapp.com](http://damp-scrubland-3368.herokuapp.com)
+
+#### Endpoints
+
+There are 3 different endpoints that serve these requirements. An
+example of how to connect to the endpoints can be found in [bin/acceptance.sh](bin/acceptance.sh)
+
+* GET /licenses - list of all well licenses
+* GET /licenses/:guid - details of a single license
+* GET /companies/:guid/licenses - list of all active licences for company
+* GET /companies/:guid/licenses?township=:township - list of active licenses for township, for company.
+* GET /companies/:guid/licenses?status=expired&township=:township - list of expired licenses for township, for company.
+
+##### Assumptions
+
+* Name of applicant is the name of the employee at the company that submitted the application.
+* Date of license is the date the license was issued.
+* Assume perf isn't the focus, so no need to over-engineer with a denorm read model.
+
+##### TODO
+
+* move secret token to env variable.
+* cache additional payload data.
+* resolve n+1 issues
+* figure out why location doesn't lazy load in jbuilder template.
+* rename license to well license
+
+##### nice to haves
+
+* simplecov
+* factory girl
+* dotenv
+* bullet
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
new file mode 100644
index 0000000..419e9b0
--- /dev/null
+++ b/app/controllers/application_controller.rb
@@ -0,0 +1,18 @@
+class ApplicationController < ActionController::Base
+ # Prevent CSRF attacks by raising an exception.
+ # For APIs, you may want to use :null_session instead.
+ protect_from_forgery with: :null_session
+ before_filter :load_additional_payload_data
+ rescue_from StandardError, with: :return_server_error unless Rails.env.development?
+
+ def load_additional_payload_data
+ @license_statuses = LicenseStatus::ALL
+ @well_types = WellType::ALL
+ end
+
+ private
+
+ def return_server_error
+ render nothing: true, status: :internal_server_error
+ end
+end
diff --git a/app/controllers/concerns/.keep b/app/controllers/concerns/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/controllers/concerns/.keep
diff --git a/app/controllers/v1/company_licenses_controller.rb b/app/controllers/v1/company_licenses_controller.rb
new file mode 100644
index 0000000..e3701d2
--- /dev/null
+++ b/app/controllers/v1/company_licenses_controller.rb
@@ -0,0 +1,17 @@
+class V1::CompanyLicensesController < ApplicationController
+ before_filter :load_company
+
+ def index
+ @licenses = @company.filter_licenses_using(search_filters)
+ end
+
+ private
+
+ def search_filters
+ { status: LicenseStatus.find_match(params[:status]), township: params[:township] }
+ end
+
+ def load_company
+ @company = Company.find(params[:company_id])
+ end
+end
diff --git a/app/controllers/v1/licenses_controller.rb b/app/controllers/v1/licenses_controller.rb
new file mode 100644
index 0000000..8966100
--- /dev/null
+++ b/app/controllers/v1/licenses_controller.rb
@@ -0,0 +1,20 @@
+class V1::LicensesController < ApplicationController
+ PER_PAGE = 10
+ DEFAULT_PAGE = 1
+ before_filter :prepare_pagination
+
+ def index
+ @licenses = License.most_recent(page: @page, per_page: @per_page)
+ end
+
+ def show
+ @license = License.find(params[:id])
+ end
+
+ private
+
+ def prepare_pagination
+ @page = params[:page].present? ? params[:page].to_i : DEFAULT_PAGE
+ @per_page = params[:per_page].present? ? params[:per_page].to_i : PER_PAGE
+ end
+end
diff --git a/app/models/.keep b/app/models/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/models/.keep
diff --git a/app/models/company.rb b/app/models/company.rb
new file mode 100644
index 0000000..c1c2d9f
--- /dev/null
+++ b/app/models/company.rb
@@ -0,0 +1,9 @@
+class Company < ActiveRecord::Base
+ has_many :licenses
+
+ def filter_licenses_using(search_filters)
+ result = self.licenses
+ search_filters.each { |key, value| result = result.public_send(key, value) if value.present? }
+ result
+ end
+end
diff --git a/app/models/concerns/.keep b/app/models/concerns/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/app/models/concerns/.keep
diff --git a/app/models/license.rb b/app/models/license.rb
new file mode 100644
index 0000000..b7e1dff
--- /dev/null
+++ b/app/models/license.rb
@@ -0,0 +1,24 @@
+class License < ActiveRecord::Base
+ belongs_to :company
+ belongs_to :well_type
+ belongs_to :location
+ belongs_to :applicant, class_name: 'User', foreign_key: 'user_id'
+
+ def status
+ LicenseStatus.status_for(self)
+ end
+
+ def self.most_recent(page: 1, per_page: 10)
+ offset = (page - 1) * per_page
+ offset = offset >= 0 ? offset : 0
+ License.order(created_at: :desc).offset(offset).limit(per_page)
+ end
+
+ def self.township(township)
+ joins(:location).where(locations: { township: township })
+ end
+
+ def self.status(status)
+ status.filter(self)
+ end
+end
diff --git a/app/models/license_status.rb b/app/models/license_status.rb
new file mode 100644
index 0000000..d5da68f
--- /dev/null
+++ b/app/models/license_status.rb
@@ -0,0 +1,16 @@
+class LicenseStatus
+ ACTIVE=Active.new
+ EXPIRED=Expired.new
+ CONFIDENTIAL=Confidential.new
+ UNKNOWN=Object.new
+
+ ALL=[ACTIVE, EXPIRED, CONFIDENTIAL]
+
+ def self.find_match(status = "")
+ ALL.find { |x| x.matches?("#{status}".downcase) } || ACTIVE
+ end
+
+ def self.status_for(license)
+ ALL.find { |x| x.best_represents?(license) } || UNKNOWN
+ end
+end
diff --git a/app/models/license_status/active.rb b/app/models/license_status/active.rb
new file mode 100644
index 0000000..f959efb
--- /dev/null
+++ b/app/models/license_status/active.rb
@@ -0,0 +1,20 @@
+class LicenseStatus::Active
+ def filter(licenses)
+ today = Date.today
+ licenses.where('issued_at < ? AND expired_at > ?', today, today)
+ end
+
+ def matches?(name)
+ to_s == name
+ end
+
+ def best_represents?(license)
+ today = Date.today
+ license.issued_at < today && license.expired_at > today
+ end
+
+ def to_s
+ 'active'
+ end
+end
+
diff --git a/app/models/license_status/confidential.rb b/app/models/license_status/confidential.rb
new file mode 100644
index 0000000..b2354cd
--- /dev/null
+++ b/app/models/license_status/confidential.rb
@@ -0,0 +1,17 @@
+class LicenseStatus::Confidential
+ def filter(licenses)
+ licenses.where(confidential: true)
+ end
+
+ def matches?(name)
+ to_s == name
+ end
+
+ def best_represents?(license)
+ license.confidential?
+ end
+
+ def to_s
+ 'confidential'
+ end
+end
diff --git a/app/models/license_status/expired.rb b/app/models/license_status/expired.rb
new file mode 100644
index 0000000..8e24af9
--- /dev/null
+++ b/app/models/license_status/expired.rb
@@ -0,0 +1,18 @@
+class LicenseStatus::Expired
+ def filter(licenses)
+ today = DateTime.now
+ licenses.where('expired_at < ?', today)
+ end
+
+ def matches?(name)
+ to_s == name
+ end
+
+ def best_represents?(license)
+ license.expired_at < Date.today
+ end
+
+ def to_s
+ 'expired'
+ end
+end
diff --git a/app/models/location.rb b/app/models/location.rb
new file mode 100644
index 0000000..5587398
--- /dev/null
+++ b/app/models/location.rb
@@ -0,0 +1,3 @@
+class Location < ActiveRecord::Base
+ has_one :license, autosave: true
+end
diff --git a/app/models/user.rb b/app/models/user.rb
new file mode 100644
index 0000000..c298241
--- /dev/null
+++ b/app/models/user.rb
@@ -0,0 +1,11 @@
+class User < ActiveRecord::Base
+ belongs_to :company
+
+ def full_name
+ "#{first_name} #{last_name}"
+ end
+
+ def apply_for_license(well_type, location)
+ company.licenses.create(well_type: well_type, location: location, applicant: self)
+ end
+end
diff --git a/app/models/well_type.rb b/app/models/well_type.rb
new file mode 100644
index 0000000..361dd99
--- /dev/null
+++ b/app/models/well_type.rb
@@ -0,0 +1,9 @@
+class WellType < ActiveRecord::Base
+ NFW=WellType.find_by_id(1)
+ NPW=WellType.find_by_id(2)
+ DPT=WellType.find_by_id(3)
+ SPT=WellType.find_by_id(4)
+ DEV=WellType.find_by_id(5)
+
+ ALL=[NFW, NPW, DPT, SPT, DEV]
+end
diff --git a/app/views/v1/company_licenses/index.jbuilder b/app/views/v1/company_licenses/index.jbuilder
new file mode 100644
index 0000000..8228f3e
--- /dev/null
+++ b/app/views/v1/company_licenses/index.jbuilder
@@ -0,0 +1,7 @@
+json.licenses do
+ json.array! @licenses do |license|
+ json.partial! 'v1/licenses/license', license: license
+ end
+end
+json.partial! 'v1/shared/well_types', well_types: @well_types
+json.partial! 'v1/shared/license_statuses', license_statuses: @license_statuses
diff --git a/app/views/v1/licenses/_company.jbuilder b/app/views/v1/licenses/_company.jbuilder
new file mode 100644
index 0000000..91a79da
--- /dev/null
+++ b/app/views/v1/licenses/_company.jbuilder
@@ -0,0 +1,4 @@
+json.company do
+ json.name company.name
+ json.applicant_name applicant.full_name
+end
diff --git a/app/views/v1/licenses/_confidential_company.jbuilder b/app/views/v1/licenses/_confidential_company.jbuilder
new file mode 100644
index 0000000..312961a
--- /dev/null
+++ b/app/views/v1/licenses/_confidential_company.jbuilder
@@ -0,0 +1,4 @@
+json.company do
+ json.name "CONFIDENTIAL"
+ json.applicant_name "CONFIDENTIAL"
+end
diff --git a/app/views/v1/licenses/_confidential_well_type.jbuilder b/app/views/v1/licenses/_confidential_well_type.jbuilder
new file mode 100644
index 0000000..43d8f39
--- /dev/null
+++ b/app/views/v1/licenses/_confidential_well_type.jbuilder
@@ -0,0 +1,5 @@
+json.well_type do
+ json.id ""
+ json.acronym ""
+ json.name "CONFIDENTIAL"
+end
diff --git a/app/views/v1/licenses/_license.jbuilder b/app/views/v1/licenses/_license.jbuilder
new file mode 100644
index 0000000..c66fb3f
--- /dev/null
+++ b/app/views/v1/licenses/_license.jbuilder
@@ -0,0 +1,12 @@
+json.id license.id
+json.status license.status.to_s
+json.partial! 'v1/licenses/location', location: license.location
+if license.confidential?
+ json.partial! 'v1/licenses/confidential_well_type', well_type: license.well_type
+ json.partial! 'v1/licenses/confidential_company'
+else
+ json.partial! 'v1/licenses/well_type', well_type: license.well_type
+ json.partial! 'v1/licenses/company', company: license.company, applicant: license.applicant
+end
+json.issued_at license.issued_at.to_s
+json.expired_at license.expired_at.to_s
diff --git a/app/views/v1/licenses/_location.jbuilder b/app/views/v1/licenses/_location.jbuilder
new file mode 100644
index 0000000..5b43756
--- /dev/null
+++ b/app/views/v1/licenses/_location.jbuilder
@@ -0,0 +1,5 @@
+json.location do
+ json.township location.township
+ json.latitude location.latitude
+ json.longitude location.longitude
+end
diff --git a/app/views/v1/licenses/_well_type.jbuilder b/app/views/v1/licenses/_well_type.jbuilder
new file mode 100644
index 0000000..dd5176e
--- /dev/null
+++ b/app/views/v1/licenses/_well_type.jbuilder
@@ -0,0 +1,5 @@
+json.well_type do
+ json.id well_type.id
+ json.acronym well_type.acronym
+ json.name well_type.name
+end
diff --git a/app/views/v1/licenses/index.jbuilder b/app/views/v1/licenses/index.jbuilder
new file mode 100644
index 0000000..8228f3e
--- /dev/null
+++ b/app/views/v1/licenses/index.jbuilder
@@ -0,0 +1,7 @@
+json.licenses do
+ json.array! @licenses do |license|
+ json.partial! 'v1/licenses/license', license: license
+ end
+end
+json.partial! 'v1/shared/well_types', well_types: @well_types
+json.partial! 'v1/shared/license_statuses', license_statuses: @license_statuses
diff --git a/app/views/v1/licenses/show.jbuilder b/app/views/v1/licenses/show.jbuilder
new file mode 100644
index 0000000..7d64d23
--- /dev/null
+++ b/app/views/v1/licenses/show.jbuilder
@@ -0,0 +1 @@
+json.partial! 'v1/licenses/license', license: @license
diff --git a/app/views/v1/shared/_license_statuses.jbuilder b/app/views/v1/shared/_license_statuses.jbuilder
new file mode 100644
index 0000000..76c2ec6
--- /dev/null
+++ b/app/views/v1/shared/_license_statuses.jbuilder
@@ -0,0 +1,5 @@
+json.license_statuses do
+ json.array! license_statuses do |status|
+ json.name status.to_s
+ end
+end
diff --git a/app/views/v1/shared/_well_types.jbuilder b/app/views/v1/shared/_well_types.jbuilder
new file mode 100644
index 0000000..e1b588d
--- /dev/null
+++ b/app/views/v1/shared/_well_types.jbuilder
@@ -0,0 +1,7 @@
+json.well_types do
+ json.array! well_types do |well_type|
+ json.id well_type.id
+ json.acronym well_type.acronym
+ json.name well_type.name
+ end
+end
diff --git a/bin/acceptance.sh b/bin/acceptance.sh
new file mode 100755
index 0000000..4644deb
--- /dev/null
+++ b/bin/acceptance.sh
@@ -0,0 +1,63 @@
+#!/bin/bash
+set -e
+
+TARGET_HOST=http://damp-scrubland-3368.herokuapp.com
+COMPANY_ABC=680fc2c1-9557-49fd-b05f-0f700a67ca0c
+COMPANY_XYZ=04e6b076-41ca-4849-8a94-14e4e505ffe8
+
+PUBLIC_ACTIVE_LICENSE=e4650fd2-2298-463a-bfcd-fb953d996d6e
+PUBLIC_EXPIRED_LICENSE=20d69330-ebc9-40b6-9d25-0174aea3c056
+CONFIDENTIAL_ACTIVE_LICENSE=fd3918dd-6296-49ce-83bb-c518916fb82e
+
+clear
+
+# GET /licenses - list of all well licenses
+echo $TARGET_HOST
+curl $TARGET_HOST
+echo
+echo
+
+echo $TARGET_HOST/v1/licenses
+curl $TARGET_HOST/v1/licenses
+echo
+echo
+
+# GET /licenses/:guid - details of a single license
+echo $TARGET_HOST/v1/licenses/$PUBLIC_ACTIVE_LICENSE
+curl $TARGET_HOST/v1/licenses/$PUBLIC_ACTIVE_LICENSE
+echo
+echo
+
+echo $TARGET_HOST/v1/licenses/$CONFIDENTIAL_ACTIVE_LICENSE
+curl $TARGET_HOST/v1/licenses/$CONFIDENTIAL_ACTIVE_LICENSE
+echo
+echo
+
+#* GET /companies/:guid/licenses - list of all active licences for company
+echo $TARGET_HOST/v1/companies/$COMPANY_ABC/licenses
+curl $TARGET_HOST/v1/companies/$COMPANY_ABC/licenses
+echo
+echo
+
+#* GET /companies/:guid/licenses?township=:township - list of active licenses for township, for company.
+echo $TARGET_HOST/v1/companies/$COMPANY_XYZ/licenses?township=2
+curl $TARGET_HOST/v1/companies/$COMPANY_XYZ/licenses?township=2
+echo
+echo
+
+#* GET /companies/:guid/licenses?township=:township&status=expired - list of active licenses for township, for company.
+echo $TARGET_HOST/v1/companies/$COMPANY_ABC/licenses?status=expired&township=1
+curl $TARGET_HOST/v1/companies/$COMPANY_ABC/licenses?status=expired&township=1
+echo
+echo
+
+#* GET /companies/:guid/licenses?status=confidential - list of confidential licenses for company.
+echo $TARGET_HOST/v1/companies/$COMPANY_XYZ/licenses?status=confidential
+curl $TARGET_HOST/v1/companies/$COMPANY_XYZ/licenses?status=confidential
+echo
+echo
+
+sleep 1
+echo
+echo
+echo "goodbye"
diff --git a/bin/bundle b/bin/bundle
new file mode 100755
index 0000000..66e9889
--- /dev/null
+++ b/bin/bundle
@@ -0,0 +1,3 @@
+#!/usr/bin/env ruby
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+load Gem.bin_path('bundler', 'bundle')
diff --git a/bin/deploy.sh b/bin/deploy.sh
new file mode 100755
index 0000000..06c20da
--- /dev/null
+++ b/bin/deploy.sh
@@ -0,0 +1,6 @@
+#!/bin/bash
+set -e
+
+git push heroku master
+heroku run rake db:migrate
+heroku run rake db:seed
diff --git a/bin/hconsole.sh b/bin/hconsole.sh
new file mode 100755
index 0000000..fb6066f
--- /dev/null
+++ b/bin/hconsole.sh
@@ -0,0 +1,2 @@
+#!/bin/bash
+heroku run bin/rails console
diff --git a/bin/logs.sh b/bin/logs.sh
new file mode 100755
index 0000000..89aa147
--- /dev/null
+++ b/bin/logs.sh
@@ -0,0 +1,4 @@
+#!/bin/bash
+set -e
+
+heroku logs --tail --app damp-scrubland-3368
diff --git a/bin/rails b/bin/rails
new file mode 100755
index 0000000..728cd85
--- /dev/null
+++ b/bin/rails
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+APP_PATH = File.expand_path('../../config/application', __FILE__)
+require_relative '../config/boot'
+require 'rails/commands'
diff --git a/bin/rake b/bin/rake
new file mode 100755
index 0000000..1724048
--- /dev/null
+++ b/bin/rake
@@ -0,0 +1,4 @@
+#!/usr/bin/env ruby
+require_relative '../config/boot'
+require 'rake'
+Rake.application.run
diff --git a/bin/sample.rb b/bin/sample.rb
new file mode 100755
index 0000000..5297ff4
--- /dev/null
+++ b/bin/sample.rb
@@ -0,0 +1,41 @@
+#!/usr/bin/env ruby
+require ::File.expand_path('../../config/environment', __FILE__)
+
+ActiveRecord::Base.transaction do
+ abc_resources = Company.create(id: '680fc2c1-9557-49fd-b05f-0f700a67ca0c', name: 'ABC Resources Ltd.')
+ xyz_resources = Company.create(id: '04e6b076-41ca-4849-8a94-14e4e505ffe8', name: 'XYZ Resources Ltd.')
+
+ jd = User.create(first_name: 'john', last_name: 'dielwart', company: abc_resources)
+ hal = User.create(first_name: 'hal', last_name: 'kvisle', company: xyz_resources)
+
+ township_1 = Location.create(latitude: 51.06, longitude: -114.09, township: '1')
+ township_2 = Location.create(latitude: 40.06, longitude: -100.09, township: '2')
+ township_3 = Location.create(latitude: 30.06, longitude: -90.01, township: '3')
+
+ public_license = abc_resources.licenses.create(
+ id: 'e4650fd2-2298-463a-bfcd-fb953d996d6e',
+ well_type: WellType::NFW,
+ location: township_1,
+ applicant: jd,
+ issued_at: 1.day.ago,
+ expired_at: 1.year.from_now
+ )
+
+ public_expired_license = abc_resources.licenses.create(
+ id: '20d69330-ebc9-40b6-9d25-0174aea3c056',
+ well_type: WellType::DPT,
+ location: township_3,
+ applicant: jd,
+ issued_at: 1.year.ago,
+ expired_at: 1.day.ago
+ )
+
+ confidential_license = xyz_resources.licenses.create(
+ id: 'fd3918dd-6296-49ce-83bb-c518916fb82e',
+ well_type: WellType::SPT,
+ location: township_2,
+ applicant: hal,
+ issued_at: 1.day.ago,
+ expired_at: 1.year.from_now
+ )
+end
diff --git a/config.ru b/config.ru
new file mode 100644
index 0000000..5bc2a61
--- /dev/null
+++ b/config.ru
@@ -0,0 +1,4 @@
+# This file is used by Rack-based servers to start the application.
+
+require ::File.expand_path('../config/environment', __FILE__)
+run Rails.application
diff --git a/config/application.rb b/config/application.rb
new file mode 100644
index 0000000..267e747
--- /dev/null
+++ b/config/application.rb
@@ -0,0 +1,31 @@
+require File.expand_path('../boot', __FILE__)
+
+# Pick the frameworks you want:
+require "active_record/railtie"
+require "action_controller/railtie"
+require "action_mailer/railtie"
+# require "sprockets/railtie"
+# require "rails/test_unit/railtie"
+
+# Require the gems listed in Gemfile, including any gems
+# you've limited to :test, :development, or :production.
+Bundler.require(:default, Rails.env)
+
+module CodeChallengeMo
+ class Application < Rails::Application
+ # Settings in config/environments/* take precedence over those specified here.
+ # Application configuration should go into files in config/initializers
+ # -- all .rb files in that directory are automatically loaded.
+
+ # Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
+ # Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
+ # config.time_zone = 'Central Time (US & Canada)'
+
+ # The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
+ # config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
+ # config.i18n.default_locale = :de
+
+ # Disable the asset pipeline.
+ config.assets.enabled = false
+ end
+end
diff --git a/config/boot.rb b/config/boot.rb
new file mode 100644
index 0000000..3596736
--- /dev/null
+++ b/config/boot.rb
@@ -0,0 +1,4 @@
+# Set up gems listed in the Gemfile.
+ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile', __FILE__)
+
+require 'bundler/setup' if File.exists?(ENV['BUNDLE_GEMFILE'])
diff --git a/config/database.yml.example b/config/database.yml.example
new file mode 100644
index 0000000..e598daf
--- /dev/null
+++ b/config/database.yml.example
@@ -0,0 +1,13 @@
+development:
+ adapter: postgresql
+ database: licenses_dev
+ username: <username>
+ password: <password>
+ host: <hostname or ip address. eg.: localhost>
+
+test:
+ adapter: postgresql
+ database: licenses_test
+ username: <username>
+ password: <password>
+ host: <hostname or ip address. eg.: localhost>
diff --git a/config/environment.rb b/config/environment.rb
new file mode 100644
index 0000000..b13bc26
--- /dev/null
+++ b/config/environment.rb
@@ -0,0 +1,5 @@
+# Load the Rails application.
+require File.expand_path('../application', __FILE__)
+
+# Initialize the Rails application.
+CodeChallengeMo::Application.initialize!
diff --git a/config/environments/development.rb b/config/environments/development.rb
new file mode 100644
index 0000000..b6a245b
--- /dev/null
+++ b/config/environments/development.rb
@@ -0,0 +1,25 @@
+CodeChallengeMo::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # In the development environment your application's code is reloaded on
+ # every request. This slows down response time but is perfect for development
+ # since you don't have to restart the web server when you make code changes.
+ config.cache_classes = false
+
+ # Do not eager load code on boot.
+ config.eager_load = false
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Don't care if the mailer can't send.
+ config.action_mailer.raise_delivery_errors = false
+
+ # Print deprecation notices to the Rails logger.
+ config.active_support.deprecation = :log
+
+ # Raise an error on page load if there are pending migrations
+ config.active_record.migration_error = :page_load
+
+end
diff --git a/config/environments/production.rb b/config/environments/production.rb
new file mode 100644
index 0000000..d162aa3
--- /dev/null
+++ b/config/environments/production.rb
@@ -0,0 +1,65 @@
+CodeChallengeMo::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # Code is not reloaded between requests.
+ config.cache_classes = true
+
+ # Eager load code on boot. This eager loads most of Rails and
+ # your application in memory, allowing both thread web servers
+ # and those relying on copy on write to perform better.
+ # Rake tasks automatically ignore this option for performance.
+ config.eager_load = true
+
+ # Full error reports are disabled and caching is turned on.
+ config.consider_all_requests_local = false
+ config.action_controller.perform_caching = true
+
+ # Enable Rack::Cache to put a simple HTTP cache in front of your application
+ # Add `rack-cache` to your Gemfile before enabling this.
+ # For large-scale production use, consider using a caching reverse proxy like nginx, varnish or squid.
+ # config.action_dispatch.rack_cache = true
+
+ # Disable Rails's static asset server (Apache or nginx will already do this).
+ config.serve_static_assets = false
+
+
+ # Specifies the header that your server uses for sending files.
+ # config.action_dispatch.x_sendfile_header = "X-Sendfile" # for apache
+ # config.action_dispatch.x_sendfile_header = 'X-Accel-Redirect' # for nginx
+
+ # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies.
+ # config.force_ssl = true
+
+ # Set to :debug to see everything in the log.
+ config.log_level = :info
+
+ # Prepend all log lines with the following tags.
+ # config.log_tags = [ :subdomain, :uuid ]
+
+ # Use a different logger for distributed setups.
+ # config.logger = ActiveSupport::TaggedLogging.new(SyslogLogger.new)
+
+ # Use a different cache store in production.
+ # config.cache_store = :mem_cache_store
+
+ # Enable serving of images, stylesheets, and JavaScripts from an asset server.
+ # config.action_controller.asset_host = "http://assets.example.com"
+
+
+ # Ignore bad email addresses and do not raise email delivery errors.
+ # Set this to true and configure the email server for immediate delivery to raise delivery errors.
+ # config.action_mailer.raise_delivery_errors = false
+
+ # Enable locale fallbacks for I18n (makes lookups for any locale fall back to
+ # the I18n.default_locale when a translation can not be found).
+ config.i18n.fallbacks = true
+
+ # Send deprecation notices to registered listeners.
+ config.active_support.deprecation = :notify
+
+ # Disable automatic flushing of the log to improve performance.
+ # config.autoflush_log = false
+
+ # Use default logging formatter so that PID and timestamp are not suppressed.
+ config.log_formatter = ::Logger::Formatter.new
+end
diff --git a/config/environments/test.rb b/config/environments/test.rb
new file mode 100644
index 0000000..89c41db
--- /dev/null
+++ b/config/environments/test.rb
@@ -0,0 +1,36 @@
+CodeChallengeMo::Application.configure do
+ # Settings specified here will take precedence over those in config/application.rb.
+
+ # The test environment is used exclusively to run your application's
+ # test suite. You never need to work with it otherwise. Remember that
+ # your test database is "scratch space" for the test suite and is wiped
+ # and recreated between test runs. Don't rely on the data there!
+ config.cache_classes = true
+
+ # Do not eager load code on boot. This avoids loading your whole application
+ # just for the purpose of running a single test. If you are using a tool that
+ # preloads Rails for running tests, you may have to set it to true.
+ config.eager_load = false
+
+ # Configure static asset server for tests with Cache-Control for performance.
+ config.serve_static_assets = true
+ config.static_cache_control = "public, max-age=3600"
+
+ # Show full error reports and disable caching.
+ config.consider_all_requests_local = true
+ config.action_controller.perform_caching = false
+
+ # Raise exceptions instead of rendering exception templates.
+ config.action_dispatch.show_exceptions = false
+
+ # Disable request forgery protection in test environment.
+ config.action_controller.allow_forgery_protection = false
+
+ # Tell Action Mailer not to deliver emails to the real world.
+ # The :test delivery method accumulates sent emails in the
+ # ActionMailer::Base.deliveries array.
+ config.action_mailer.delivery_method = :test
+
+ # Print deprecation notices to the stderr.
+ config.active_support.deprecation = :stderr
+end
diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb
new file mode 100644
index 0000000..59385cd
--- /dev/null
+++ b/config/initializers/backtrace_silencers.rb
@@ -0,0 +1,7 @@
+# Be sure to restart your server when you modify this file.
+
+# You can add backtrace silencers for libraries that you're using but don't wish to see in your backtraces.
+# Rails.backtrace_cleaner.add_silencer { |line| line =~ /my_noisy_library/ }
+
+# You can also remove all the silencers if you're trying to debug a problem that might stem from framework code.
+# Rails.backtrace_cleaner.remove_silencers!
diff --git a/config/initializers/filter_parameter_logging.rb b/config/initializers/filter_parameter_logging.rb
new file mode 100644
index 0000000..4a994e1
--- /dev/null
+++ b/config/initializers/filter_parameter_logging.rb
@@ -0,0 +1,4 @@
+# Be sure to restart your server when you modify this file.
+
+# Configure sensitive parameters which will be filtered from the log file.
+Rails.application.config.filter_parameters += [:password]
diff --git a/config/initializers/inflections.rb b/config/initializers/inflections.rb
new file mode 100644
index 0000000..ac033bf
--- /dev/null
+++ b/config/initializers/inflections.rb
@@ -0,0 +1,16 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new inflection rules using the following format. Inflections
+# are locale specific, and you may define rules for as many different
+# locales as you wish. All of these examples are active by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.plural /^(ox)$/i, '\1en'
+# inflect.singular /^(ox)en/i, '\1'
+# inflect.irregular 'person', 'people'
+# inflect.uncountable %w( fish sheep )
+# end
+
+# These inflection rules are supported but not enabled by default:
+# ActiveSupport::Inflector.inflections(:en) do |inflect|
+# inflect.acronym 'RESTful'
+# end
diff --git a/config/initializers/mime_types.rb b/config/initializers/mime_types.rb
new file mode 100644
index 0000000..72aca7e
--- /dev/null
+++ b/config/initializers/mime_types.rb
@@ -0,0 +1,5 @@
+# Be sure to restart your server when you modify this file.
+
+# Add new mime types for use in respond_to blocks:
+# Mime::Type.register "text/richtext", :rtf
+# Mime::Type.register_alias "text/html", :iphone
diff --git a/config/initializers/secret_token.rb b/config/initializers/secret_token.rb
new file mode 100644
index 0000000..7c81149
--- /dev/null
+++ b/config/initializers/secret_token.rb
@@ -0,0 +1,12 @@
+# Be sure to restart your server when you modify this file.
+
+# Your secret key is used for verifying the integrity of signed cookies.
+# If you change this key, all old signed cookies will become invalid!
+
+# Make sure the secret is at least 30 characters and all random,
+# no regular words or you'll be exposed to dictionary attacks.
+# You can use `rake secret` to generate a secure secret key.
+
+# Make sure your secret_key_base is kept private
+# if you're sharing your code publicly.
+CodeChallengeMo::Application.config.secret_key_base = '38d3dbb199f442080b87ee04aacdf61ac0cc2640d67647c73f9c26b8d3a57341cac0330d9f0167a8b0d4e89c401597fe58b289e4d9c46da489c6f3c60c1dd552'
diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb
new file mode 100644
index 0000000..6259340
--- /dev/null
+++ b/config/initializers/session_store.rb
@@ -0,0 +1,3 @@
+# Be sure to restart your server when you modify this file.
+
+CodeChallengeMo::Application.config.session_store :cookie_store, key: '_code-challenge-mo_session'
diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb
new file mode 100644
index 0000000..33725e9
--- /dev/null
+++ b/config/initializers/wrap_parameters.rb
@@ -0,0 +1,14 @@
+# Be sure to restart your server when you modify this file.
+
+# This file contains settings for ActionController::ParamsWrapper which
+# is enabled by default.
+
+# Enable parameter wrapping for JSON. You can disable this by setting :format to an empty array.
+ActiveSupport.on_load(:action_controller) do
+ wrap_parameters format: [:json] if respond_to?(:wrap_parameters)
+end
+
+# To enable root element in JSON for ActiveRecord objects.
+# ActiveSupport.on_load(:active_record) do
+# self.include_root_in_json = true
+# end
diff --git a/config/locales/en.yml b/config/locales/en.yml
new file mode 100644
index 0000000..0653957
--- /dev/null
+++ b/config/locales/en.yml
@@ -0,0 +1,23 @@
+# Files in the config/locales directory are used for internationalization
+# and are automatically loaded by Rails. If you want to use locales other
+# than English, add the necessary files in this directory.
+#
+# To use the locales, use `I18n.t`:
+#
+# I18n.t 'hello'
+#
+# In views, this is aliased to just `t`:
+#
+# <%= t('hello') %>
+#
+# To use a different locale, set it with `I18n.locale`:
+#
+# I18n.locale = :es
+#
+# This would use the information in config/locales/es.yml.
+#
+# To learn more, please read the Rails Internationalization guide
+# available at http://guides.rubyonrails.org/i18n.html.
+
+en:
+ hello: "Hello world"
diff --git a/config/routes.rb b/config/routes.rb
new file mode 100644
index 0000000..39fc8ea
--- /dev/null
+++ b/config/routes.rb
@@ -0,0 +1,9 @@
+CodeChallengeMo::Application.routes.draw do
+ namespace :v1, path: 'v1' do
+ resources :licenses, only: [:index, :show]
+ resources :companies, only: [] do
+ resources :licenses, controller: 'company_licenses', only: [:index]
+ end
+ end
+ root to: 'v1/licenses#index'
+end
diff --git a/config/unicorn.rb b/config/unicorn.rb
new file mode 100644
index 0000000..729ff4d
--- /dev/null
+++ b/config/unicorn.rb
@@ -0,0 +1,20 @@
+worker_processes Integer(ENV["WEB_CONCURRENCY"] || 3)
+timeout 15
+preload_app true
+
+before_fork do |server, worker|
+ Signal.trap 'TERM' do
+ puts 'Unicorn master intercepting TERM and sending myself QUIT instead'
+ Process.kill 'QUIT', Process.pid
+ end
+
+ defined?(ActiveRecord::Base) and ActiveRecord::Base.connection.disconnect!
+end
+
+after_fork do |server, worker|
+ Signal.trap 'TERM' do
+ puts 'Unicorn worker intercepting TERM and doing nothing. Wait for master to send QUIT'
+ end
+
+ defined?(ActiveRecord::Base) and ActiveRecord::Base.establish_connection
+end
diff --git a/db/migrate/20140221015819_create_licenses.rb b/db/migrate/20140221015819_create_licenses.rb
new file mode 100644
index 0000000..cc571e1
--- /dev/null
+++ b/db/migrate/20140221015819_create_licenses.rb
@@ -0,0 +1,7 @@
+class CreateLicenses < ActiveRecord::Migration
+ def change
+ create_table :licenses do |t|
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20140221024327_enable_uuid_extension.rb b/db/migrate/20140221024327_enable_uuid_extension.rb
new file mode 100644
index 0000000..876b6aa
--- /dev/null
+++ b/db/migrate/20140221024327_enable_uuid_extension.rb
@@ -0,0 +1,5 @@
+class EnableUuidExtension < ActiveRecord::Migration
+ def change
+ enable_extension 'uuid-ossp'
+ end
+end
diff --git a/db/migrate/20140221025310_recreate_licenses.rb b/db/migrate/20140221025310_recreate_licenses.rb
new file mode 100644
index 0000000..a1229b5
--- /dev/null
+++ b/db/migrate/20140221025310_recreate_licenses.rb
@@ -0,0 +1,8 @@
+class RecreateLicenses < ActiveRecord::Migration
+ def change
+ drop_table :licenses
+ create_table :licenses, id: :uuid do |t|
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20140221134937_create_companies.rb b/db/migrate/20140221134937_create_companies.rb
new file mode 100644
index 0000000..b2fc820
--- /dev/null
+++ b/db/migrate/20140221134937_create_companies.rb
@@ -0,0 +1,8 @@
+class CreateCompanies < ActiveRecord::Migration
+ def change
+ create_table :companies, id: :uuid do |t|
+ t.string :name
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20140221135224_add_active_range_to_licenses.rb b/db/migrate/20140221135224_add_active_range_to_licenses.rb
new file mode 100644
index 0000000..6342f61
--- /dev/null
+++ b/db/migrate/20140221135224_add_active_range_to_licenses.rb
@@ -0,0 +1,7 @@
+class AddActiveRangeToLicenses < ActiveRecord::Migration
+ def change
+ add_column :licenses, :issued_at, :datetime, default: nil
+ add_column :licenses, :expired_at, :datetime, default: nil
+ add_column :licenses, :company_id, :uuid
+ end
+end
diff --git a/db/migrate/20140222032401_add_confidential_to_licenses.rb b/db/migrate/20140222032401_add_confidential_to_licenses.rb
new file mode 100644
index 0000000..7d752c8
--- /dev/null
+++ b/db/migrate/20140222032401_add_confidential_to_licenses.rb
@@ -0,0 +1,5 @@
+class AddConfidentialToLicenses < ActiveRecord::Migration
+ def change
+ add_column :licenses, :confidential, :boolean, default: false
+ end
+end
diff --git a/db/migrate/20140222051253_create_well_types.rb b/db/migrate/20140222051253_create_well_types.rb
new file mode 100644
index 0000000..aa22bca
--- /dev/null
+++ b/db/migrate/20140222051253_create_well_types.rb
@@ -0,0 +1,8 @@
+class CreateWellTypes < ActiveRecord::Migration
+ def change
+ create_table :well_types do |t|
+ t.string :name
+ t.string :acronym
+ end
+ end
+end
diff --git a/db/migrate/20140222052902_add_well_type_to_licenses.rb b/db/migrate/20140222052902_add_well_type_to_licenses.rb
new file mode 100644
index 0000000..bc1dded
--- /dev/null
+++ b/db/migrate/20140222052902_add_well_type_to_licenses.rb
@@ -0,0 +1,5 @@
+class AddWellTypeToLicenses < ActiveRecord::Migration
+ def change
+ add_column :licenses, :well_type_id, :integer
+ end
+end
diff --git a/db/migrate/20140222053352_create_locations.rb b/db/migrate/20140222053352_create_locations.rb
new file mode 100644
index 0000000..fb2bca2
--- /dev/null
+++ b/db/migrate/20140222053352_create_locations.rb
@@ -0,0 +1,11 @@
+class CreateLocations < ActiveRecord::Migration
+ def change
+ create_table :locations, id: :uuid do |t|
+ t.uuid :license_id
+ t.float :latitude
+ t.float :longitude
+ t.string :township
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20140222054248_create_users.rb b/db/migrate/20140222054248_create_users.rb
new file mode 100644
index 0000000..791bf2f
--- /dev/null
+++ b/db/migrate/20140222054248_create_users.rb
@@ -0,0 +1,8 @@
+class CreateUsers < ActiveRecord::Migration
+ def change
+ create_table :users, id: :uuid do |t|
+ t.uuid :company_id
+ t.timestamps
+ end
+ end
+end
diff --git a/db/migrate/20140222055630_add_applicant_to_licenses.rb b/db/migrate/20140222055630_add_applicant_to_licenses.rb
new file mode 100644
index 0000000..ca96b8f
--- /dev/null
+++ b/db/migrate/20140222055630_add_applicant_to_licenses.rb
@@ -0,0 +1,5 @@
+class AddApplicantToLicenses < ActiveRecord::Migration
+ def change
+ add_column :licenses, :user_id, :uuid
+ end
+end
diff --git a/db/migrate/20140222145409_add_name_to_users.rb b/db/migrate/20140222145409_add_name_to_users.rb
new file mode 100644
index 0000000..2f30a88
--- /dev/null
+++ b/db/migrate/20140222145409_add_name_to_users.rb
@@ -0,0 +1,6 @@
+class AddNameToUsers < ActiveRecord::Migration
+ def change
+ add_column :users, :first_name, :string
+ add_column :users, :last_name, :string
+ end
+end
diff --git a/db/migrate/20140222194718_add_location_id_to_licenses.rb b/db/migrate/20140222194718_add_location_id_to_licenses.rb
new file mode 100644
index 0000000..067e7e4
--- /dev/null
+++ b/db/migrate/20140222194718_add_location_id_to_licenses.rb
@@ -0,0 +1,6 @@
+class AddLocationIdToLicenses < ActiveRecord::Migration
+ def change
+ add_column :licenses, :location_id, :uuid
+ remove_column :locations, :license_id
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 0000000..b397f77
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,59 @@
+# encoding: UTF-8
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 20140222194718) do
+
+ # These are extensions that must be enabled in order to support this database
+ enable_extension "plpgsql"
+ enable_extension "uuid-ossp"
+
+ create_table "companies", id: :uuid, default: "uuid_generate_v4()", force: true do |t|
+ t.string "name"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "licenses", id: :uuid, default: "uuid_generate_v4()", force: true do |t|
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.datetime "issued_at"
+ t.datetime "expired_at"
+ t.uuid "company_id"
+ t.boolean "confidential", default: false
+ t.integer "well_type_id"
+ t.uuid "user_id"
+ t.uuid "location_id"
+ end
+
+ create_table "locations", id: :uuid, default: "uuid_generate_v4()", force: true do |t|
+ t.float "latitude"
+ t.float "longitude"
+ t.string "township"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ end
+
+ create_table "users", id: :uuid, default: "uuid_generate_v4()", force: true do |t|
+ t.uuid "company_id"
+ t.datetime "created_at"
+ t.datetime "updated_at"
+ t.string "first_name"
+ t.string "last_name"
+ end
+
+ create_table "well_types", force: true do |t|
+ t.string "name"
+ t.string "acronym"
+ end
+
+end
diff --git a/db/seeds.rb b/db/seeds.rb
new file mode 100644
index 0000000..b9d9ff1
--- /dev/null
+++ b/db/seeds.rb
@@ -0,0 +1,7 @@
+# This file should contain all the record creation needed to seed the database with its default values.
+# The data can then be loaded with the rake db:seed (or created alongside the db with db:setup).
+WellType.create(id: 1, acronym: "NFW", name: "New Field Wildcat") unless WellType.exists?(1)
+WellType.create(id: 2, acronym: "NPW", name: "New Pool Wildcat") unless WellType.exists?(2)
+WellType.create(id: 3, acronym: "DPT", name: "Deeper Pool Test") unless WellType.exists?(3)
+WellType.create(id: 4, acronym: "SPT", name: "Shallower Pool Test") unless WellType.exists?(4)
+WellType.create(id: 5, acronym: "DEV", name: "Development Well") unless WellType.exists?(5)
diff --git a/lib/assets/.keep b/lib/assets/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/assets/.keep
diff --git a/lib/tasks/.keep b/lib/tasks/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/lib/tasks/.keep
diff --git a/log/.keep b/log/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/log/.keep
diff --git a/public/404.html b/public/404.html
new file mode 100644
index 0000000..a0daa0c
--- /dev/null
+++ b/public/404.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The page you were looking for doesn't exist (404)</title>
+ <style>
+ body {
+ background-color: #EFEFEF;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial, sans-serif;
+ }
+
+ div.dialog {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+
+ h1 {
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+
+ body > p {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #F7F7F7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
+ }
+ </style>
+</head>
+
+<body>
+ <!-- This file lives in public/404.html -->
+ <div class="dialog">
+ <h1>The page you were looking for doesn't exist.</h1>
+ <p>You may have mistyped the address or the page may have moved.</p>
+ </div>
+ <p>If you are the application owner check the logs for more information.</p>
+</body>
+</html>
diff --git a/public/422.html b/public/422.html
new file mode 100644
index 0000000..fbb4b84
--- /dev/null
+++ b/public/422.html
@@ -0,0 +1,58 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>The change you wanted was rejected (422)</title>
+ <style>
+ body {
+ background-color: #EFEFEF;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial, sans-serif;
+ }
+
+ div.dialog {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+
+ h1 {
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+
+ body > p {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #F7F7F7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
+ }
+ </style>
+</head>
+
+<body>
+ <!-- This file lives in public/422.html -->
+ <div class="dialog">
+ <h1>The change you wanted was rejected.</h1>
+ <p>Maybe you tried to change something you didn't have access to.</p>
+ </div>
+ <p>If you are the application owner check the logs for more information.</p>
+</body>
+</html>
diff --git a/public/500.html b/public/500.html
new file mode 100644
index 0000000..e9052d3
--- /dev/null
+++ b/public/500.html
@@ -0,0 +1,57 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <title>We're sorry, but something went wrong (500)</title>
+ <style>
+ body {
+ background-color: #EFEFEF;
+ color: #2E2F30;
+ text-align: center;
+ font-family: arial, sans-serif;
+ }
+
+ div.dialog {
+ width: 25em;
+ margin: 4em auto 0 auto;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-left-color: #999;
+ border-bottom-color: #BBB;
+ border-top: #B00100 solid 4px;
+ border-top-left-radius: 9px;
+ border-top-right-radius: 9px;
+ background-color: white;
+ padding: 7px 4em 0 4em;
+ }
+
+ h1 {
+ font-size: 100%;
+ color: #730E15;
+ line-height: 1.5em;
+ }
+
+ body > p {
+ width: 33em;
+ margin: 0 auto 1em;
+ padding: 1em 0;
+ background-color: #F7F7F7;
+ border: 1px solid #CCC;
+ border-right-color: #999;
+ border-bottom-color: #999;
+ border-bottom-left-radius: 4px;
+ border-bottom-right-radius: 4px;
+ border-top-color: #DADADA;
+ color: #666;
+ box-shadow:0 3px 8px rgba(50, 50, 50, 0.17);
+ }
+ </style>
+</head>
+
+<body>
+ <!-- This file lives in public/500.html -->
+ <div class="dialog">
+ <h1>We're sorry, but something went wrong.</h1>
+ </div>
+ <p>If you are the application owner check the logs for more information.</p>
+</body>
+</html>
diff --git a/public/favicon.ico b/public/favicon.ico
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/public/favicon.ico
diff --git a/public/robots.txt b/public/robots.txt
new file mode 100644
index 0000000..1a3a5e4
--- /dev/null
+++ b/public/robots.txt
@@ -0,0 +1,5 @@
+# See http://www.robotstxt.org/wc/norobots.html for documentation on how to use the robots.txt file
+#
+# To ban all spiders from the entire site uncomment the next two lines:
+# User-agent: *
+# Disallow: /
diff --git a/spec/controllers/application_controller_spec.rb b/spec/controllers/application_controller_spec.rb
new file mode 100644
index 0000000..7ccca09
--- /dev/null
+++ b/spec/controllers/application_controller_spec.rb
@@ -0,0 +1,28 @@
+require "spec_helper"
+
+describe ApplicationController do
+ controller do
+ def index
+ render nothing: true
+ end
+
+ def show
+ raise "heck"
+ end
+ end
+
+ it "includes all well statuses with every response" do
+ get :index
+ assigns(:license_statuses).should =~ LicenseStatus::ALL
+ end
+
+ it "includes all well types with every response" do
+ get :index
+ assigns(:well_types).should =~ WellType::ALL
+ end
+
+ it "handles errors gracefully" do
+ get :show, id: 1
+ response.status.should == 500
+ end
+end
diff --git a/spec/controllers/v1/company_licenses_controller_spec.rb b/spec/controllers/v1/company_licenses_controller_spec.rb
new file mode 100644
index 0000000..0ba61eb
--- /dev/null
+++ b/spec/controllers/v1/company_licenses_controller_spec.rb
@@ -0,0 +1,40 @@
+require "spec_helper"
+
+describe V1::CompanyLicensesController do
+ describe :index do
+ let(:company) { Company.new }
+ let(:company_id) { SecureRandom.uuid }
+ let(:active_licenses) { ["active"] }
+ let(:active_licenses_in_township) { ["active township"] }
+
+ before :each do
+ Company.stub(:find).with(company_id).and_return(company)
+ active_licenses.stub(:township).with("123").and_return(active_licenses_in_township)
+ end
+
+ it "returns the active licenses" do
+ company.stub(:filter_licenses_using).with({status: LicenseStatus::ACTIVE, township: nil}).and_return(active_licenses)
+ get :index, company_id: company_id
+ assigns(:licenses).should == active_licenses
+ end
+
+ it "returns the active licenses for a given township" do
+ company.stub(:filter_licenses_using).with({status: LicenseStatus::ACTIVE, township: "123"}).and_return(active_licenses_in_township)
+ get :index, company_id: company_id, township: "123"
+ assigns(:licenses).should == active_licenses_in_township
+ end
+ end
+
+ describe :integration do
+ describe :index do
+ let(:company) { Company.create(name: 'ABC Resources Ltd.') }
+ let(:location) { Location.new(latitude: 51.06, longitude: -114.09, township: '1') }
+ let!(:license) { company.licenses.create(well_type: WellType::DEV, location: location, issued_at: 2.days.ago, expired_at: 1.day.ago) }
+
+ it "finds expired licenses from a specific township" do
+ get :index, company_id: company.id, status: "expired", township: "1"
+ assigns(:licenses).should include(license)
+ end
+ end
+ end
+end
diff --git a/spec/controllers/v1/licenses_controller_spec.rb b/spec/controllers/v1/licenses_controller_spec.rb
new file mode 100644
index 0000000..ca51f95
--- /dev/null
+++ b/spec/controllers/v1/licenses_controller_spec.rb
@@ -0,0 +1,46 @@
+require "spec_helper"
+
+describe V1::LicensesController do
+ describe :index do
+ let(:licenses) { [] }
+
+ it "returns the first page of licenses" do
+ License.stub(:most_recent).with(page: 1, per_page: 10).and_return(licenses)
+
+ get :index
+
+ response.should be_success
+ assigns(:licenses).should == licenses
+ end
+
+ it "returns the second page of licenses" do
+ License.stub(:most_recent).with(page: 2, per_page: 10).and_return(licenses)
+
+ get :index, page: 2
+
+ response.should be_success
+ assigns(:licenses).should == licenses
+ end
+
+ it "returns the specified number of results" do
+ License.stub(:most_recent).with(page: 1, per_page: 100).and_return(licenses)
+
+ get :index, per_page: 100
+ response.should be_success
+ assigns(:licenses).should == licenses
+ end
+ end
+
+ describe :show do
+ let(:license) { License.new(id: SecureRandom.uuid) }
+
+ before :each do
+ License.stub(:find).with(license.id).and_return(license)
+ get :show, id: license.id
+ end
+
+ it "returns the correct license" do
+ assigns(:license).should == license
+ end
+ end
+end
diff --git a/spec/models/company_spec.rb b/spec/models/company_spec.rb
new file mode 100644
index 0000000..4f0a322
--- /dev/null
+++ b/spec/models/company_spec.rb
@@ -0,0 +1,31 @@
+require "spec_helper"
+
+describe Company do
+ describe "#filter_licenses_using" do
+ let(:company) { Company.create }
+ let(:calgary) { Location.create(township: 'calgary') }
+ let(:edmonton) { Location.create(township: 'edmonton') }
+ let!(:active_license) { company.licenses.create(issued_at: 1.day.ago, expired_at: 1.day.from_now) }
+ let!(:expired_license) { company.licenses.create(issued_at: 2.days.ago, expired_at: 1.day.ago, location: calgary) }
+ let!(:other_expired_license) { company.licenses.create(issued_at: 2.days.ago, expired_at: 1.day.ago, location: edmonton) }
+
+ it "returns all the licenses that are active" do
+ results = company.filter_licenses_using(status: LicenseStatus::ACTIVE)
+ results.count.should == 1
+ results.should include(active_license)
+ end
+
+ it "returns all expired licenses" do
+ results = company.filter_licenses_using(status: LicenseStatus::EXPIRED)
+ results.count.should == 2
+ results.should include(expired_license)
+ results.should include(other_expired_license)
+ end
+
+ it "returns expired licenses in township" do
+ results = company.filter_licenses_using(status: LicenseStatus::EXPIRED, township: 'edmonton')
+ results.count.should == 1
+ results.should include(other_expired_license)
+ end
+ end
+end
diff --git a/spec/models/license_spec.rb b/spec/models/license_spec.rb
new file mode 100644
index 0000000..1093d17
--- /dev/null
+++ b/spec/models/license_spec.rb
@@ -0,0 +1,88 @@
+require "spec_helper"
+
+describe License do
+ describe ".most_recent" do
+ let!(:oldest_license) { License.create }
+ let!(:newest_license) { License.create }
+
+ it "returns the most recently created well licenses" do
+ results = License.most_recent(page: 1, per_page: 2)
+ results.first.should == newest_license
+ results.last.should == oldest_license
+ end
+
+ it "returns the first page of results" do
+ results = License.most_recent(page: 1, per_page: 1)
+ results.count.should == 1
+ results.first.should == newest_license
+ end
+
+ it "returns the next page of results" do
+ results = License.most_recent(page: 2, per_page: 1)
+ results.count.should == 1
+ results.first.should == oldest_license
+ end
+
+ it "returns the first page of results when the page is below 1" do
+ results = License.most_recent(page: -1, per_page: 1)
+ results.count.should == 1
+ results.first.should == newest_license
+ end
+ end
+
+ describe ".township" do
+ let(:location) { Location.create(township: "2") }
+ let!(:license) { License.create(location: location) }
+ let(:other_location) { Location.create(township: "1") }
+ let!(:other_license) { License.create(location: other_location) }
+
+ it "returns a license in the township" do
+ results = License.township("2")
+ results.count.should == 1
+ results.should include(license)
+ end
+ end
+
+ describe ".status" do
+ let(:today) { DateTime.now }
+ let!(:active_license) { License.create(issued_at: 1.day.ago, expired_at: 1.day.from_now) }
+ let!(:expired_license) { License.create(issued_at: 2.days.ago, expired_at: 1.day.ago ) }
+ let!(:confidential_license) { License.create(issued_at: 2.days.from_now, expired_at: 3.days.from_now, confidential: true) }
+
+ it "returns all the licenses that are active" do
+ licenses = License.status(LicenseStatus::ACTIVE)
+ licenses.count.should == 1
+ licenses.should include(active_license)
+ end
+
+ it "returns all expired licenses" do
+ licenses = License.status(LicenseStatus::EXPIRED)
+ licenses.count.should == 1
+ licenses.should include(expired_license)
+ end
+
+ it "returns all confidential licenses" do
+ licenses = License.status(LicenseStatus::CONFIDENTIAL)
+ licenses.count.should == 1
+ licenses.should include(confidential_license)
+ end
+ end
+
+ describe "#status" do
+ let!(:active_license) { License.new(issued_at: 1.day.ago, expired_at: 1.day.from_now) }
+ let!(:expired_license) { License.new(issued_at: 2.days.ago, expired_at: 1.day.ago ) }
+ let!(:confidential_license) { License.new(issued_at: 2.days.from_now, expired_at: 3.days.from_now, confidential: true) }
+
+ it "returns an active status" do
+ active_license.status.should == LicenseStatus::ACTIVE
+ end
+
+ it "returns an expired status" do
+ expired_license.status.should == LicenseStatus::EXPIRED
+ end
+
+ it "returns an confidential status" do
+ confidential_license.status.should == LicenseStatus::CONFIDENTIAL
+ end
+ end
+end
diff --git a/spec/models/license_status/active_spec.rb b/spec/models/license_status/active_spec.rb
new file mode 100644
index 0000000..4d44737
--- /dev/null
+++ b/spec/models/license_status/active_spec.rb
@@ -0,0 +1,17 @@
+require "spec_helper"
+
+describe LicenseStatus::Active do
+ let!(:active_license) { License.create(issued_at: 1.day.ago, expired_at: 1.day.from_now) }
+ let!(:expired_license) { License.create(issued_at: 2.days.ago, expired_at: 1.day.ago) }
+ subject { LicenseStatus::Active.new }
+
+ it "returns active results" do
+ results = subject.filter(License)
+ results.should include(active_license)
+ results.should_not include(expired_license)
+ end
+
+ it "returns it's name" do
+ subject.to_s.should == 'active'
+ end
+end
diff --git a/spec/models/license_status/confidential_spec.rb b/spec/models/license_status/confidential_spec.rb
new file mode 100644
index 0000000..2b13449
--- /dev/null
+++ b/spec/models/license_status/confidential_spec.rb
@@ -0,0 +1,17 @@
+require "spec_helper"
+
+describe LicenseStatus::Confidential do
+ let!(:public_license) { License.create(confidential: false) }
+ let!(:confidential_license) { License.create(confidential: true) }
+ subject { LicenseStatus::Confidential.new }
+
+ it "returns confidential results" do
+ results = subject.filter(License)
+ results.should include(confidential_license)
+ results.should_not include(public_license)
+ end
+
+ it "returns it's name" do
+ subject.to_s.should == 'confidential'
+ end
+end
diff --git a/spec/models/license_status/expired_spec.rb b/spec/models/license_status/expired_spec.rb
new file mode 100644
index 0000000..ed5ea5d
--- /dev/null
+++ b/spec/models/license_status/expired_spec.rb
@@ -0,0 +1,16 @@
+require "spec_helper"
+
+describe LicenseStatus::Expired do
+ let!(:active_license) { License.create(issued_at: 1.day.ago, expired_at: 1.day.from_now) }
+ let!(:expired_license) { License.create(issued_at: 2.days.ago, expired_at: 1.day.ago) }
+
+ it "returns expired results" do
+ results = LicenseStatus::Expired.new.filter(License)
+ results.should include(expired_license)
+ results.should_not include(active_license)
+ end
+
+ it "returns it's name" do
+ subject.to_s.should == 'expired'
+ end
+end
diff --git a/spec/models/license_status_spec.rb b/spec/models/license_status_spec.rb
new file mode 100644
index 0000000..09e2319
--- /dev/null
+++ b/spec/models/license_status_spec.rb
@@ -0,0 +1,29 @@
+require "spec_helper"
+
+describe LicenseStatus do
+ describe ".find_match" do
+ it "returns the active status" do
+ LicenseStatus.find_match("active").should == LicenseStatus::ACTIVE
+ LicenseStatus.find_match("ACTIVE").should == LicenseStatus::ACTIVE
+ LicenseStatus.find_match("Active").should == LicenseStatus::ACTIVE
+ end
+
+ it "returns the expired status" do
+ LicenseStatus.find_match("expired").should == LicenseStatus::EXPIRED
+ LicenseStatus.find_match("EXPIRED").should == LicenseStatus::EXPIRED
+ LicenseStatus.find_match("Expired").should == LicenseStatus::EXPIRED
+ end
+
+ it "returns the confidential status" do
+ LicenseStatus.find_match("confidential").should == LicenseStatus::CONFIDENTIAL
+ LicenseStatus.find_match("CONFIDENTIAL").should == LicenseStatus::CONFIDENTIAL
+ LicenseStatus.find_match("Confidential").should == LicenseStatus::CONFIDENTIAL
+ end
+
+ it "returns the active status as the default" do
+ [nil, "", "oh hai"].each do |key|
+ LicenseStatus.find_match(key).should == LicenseStatus::ACTIVE
+ end
+ end
+ end
+end
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
new file mode 100644
index 0000000..1117f00
--- /dev/null
+++ b/spec/models/user_spec.rb
@@ -0,0 +1,25 @@
+require "spec_helper"
+
+describe User do
+ describe "#apply_for_license" do
+ context "when applying for a license" do
+ let(:company) { Company.create(name: 'ABC Resources Ltd.') }
+ let(:user) { User.create(company: company) }
+ let(:location) { Location.new(latitude: 51.06, longitude: -114.09, township: '1') }
+
+ it "creates a new license" do
+ license = user.apply_for_license(WellType::NFW, location)
+ license.company.should == user.company
+ license.well_type.should == WellType::NFW
+ license.location.should == location
+ license.applicant.should == user
+ end
+ end
+ end
+
+ describe "#full_name" do
+ it "returns the full name" do
+ User.new(first_name: "mo", last_name: "khan").full_name.should == "mo khan"
+ end
+ end
+end
diff --git a/spec/routing/company_licenses_routing_spec.rb b/spec/routing/company_licenses_routing_spec.rb
new file mode 100644
index 0000000..d6e5aa4
--- /dev/null
+++ b/spec/routing/company_licenses_routing_spec.rb
@@ -0,0 +1,8 @@
+require "spec_helper"
+
+describe 'v1/companies/:id/licenses' do
+ it "routes to the index action" do
+ company_id = SecureRandom.uuid
+ expect(get: "v1/companies/#{company_id}/licenses").to route_to(controller: 'v1/company_licenses', action: 'index', company_id: company_id)
+ end
+end
diff --git a/spec/routing/licenses_routing_spec.rb b/spec/routing/licenses_routing_spec.rb
new file mode 100644
index 0000000..4491c5b
--- /dev/null
+++ b/spec/routing/licenses_routing_spec.rb
@@ -0,0 +1,12 @@
+require "spec_helper"
+
+describe 'v1/licenses' do
+ it "can route to the index action" do
+ expect({ get: 'v1/licenses' }).to route_to(controller: 'v1/licenses', action: 'index')
+ end
+
+ it "can route to the show action" do
+ uuid = 'aa80f0ee-c6da-4b1d-bd80-3c50c93d083e'
+ expect(get: "v1/licenses/#{uuid}").to route_to(controller: 'v1/licenses', action: 'show', id: uuid)
+ end
+end
diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb
new file mode 100644
index 0000000..09b0309
--- /dev/null
+++ b/spec/spec_helper.rb
@@ -0,0 +1,45 @@
+# This file is copied to spec/ when you run 'rails generate rspec:install'
+ENV["RAILS_ENV"] ||= 'test'
+require File.expand_path("../../config/environment", __FILE__)
+require 'rspec/rails'
+require 'rspec/autorun'
+
+# Requires supporting ruby files with custom matchers and macros, etc,
+# in spec/support/ and its subdirectories.
+Dir[Rails.root.join("spec/support/**/*.rb")].each { |f| require f }
+
+# Checks for pending migrations before tests are run.
+# If you are not using ActiveRecord, you can remove this line.
+ActiveRecord::Migration.check_pending! if defined?(ActiveRecord::Migration)
+
+RSpec.configure do |config|
+ # ## Mock Framework
+ #
+ # If you prefer to use mocha, flexmock or RR, uncomment the appropriate line:
+ #
+ # config.mock_with :mocha
+ # config.mock_with :flexmock
+ # config.mock_with :rr
+
+ # Remove this line if you're not using ActiveRecord or ActiveRecord fixtures
+ config.fixture_path = "#{::Rails.root}/spec/fixtures"
+
+ # If you're not using ActiveRecord, or you'd prefer not to run each of your
+ # examples within a transaction, remove the following line or assign false
+ # instead of true.
+ config.use_transactional_fixtures = true
+
+ # If true, the base class of anonymous controllers will be inferred
+ # automatically. This will be the default behavior in future versions of
+ # rspec-rails.
+ config.infer_base_class_for_anonymous_controllers = false
+
+ # Run specs in random order to surface order dependencies. If you find an
+ # order dependency and want to debug it, you can fix the order by providing
+ # the seed, which is printed after each run.
+ # --seed 1234
+ config.order = "random"
+ config.before(:suite) do
+ require "#{Rails.root}/db/seeds"
+ end
+end
diff --git a/spec/views/v1/company_licenses/index.json.jbuilder_spec.rb b/spec/views/v1/company_licenses/index.json.jbuilder_spec.rb
new file mode 100644
index 0000000..90eefb9
--- /dev/null
+++ b/spec/views/v1/company_licenses/index.json.jbuilder_spec.rb
@@ -0,0 +1,58 @@
+require "spec_helper"
+
+describe 'v1/company_licenses/index' do
+ let(:company) { Company.new(name: 'ABC Resources Ltd.') }
+ let(:user) { User.new(company: company) }
+ let(:location) { Location.new(latitude: 51.06, longitude: -114.09, township: '1') }
+ let(:well_type) { WellType::DEV }
+ let(:license) { License.new(id: SecureRandom.uuid, company: company, applicant: user, location: location, issued_at: 2.days.ago, expired_at: 1.day.from_now, well_type: well_type) }
+
+ before :each do
+ assign(:licenses, [license])
+ assign(:well_types, WellType::ALL)
+ assign(:license_statuses, LicenseStatus::ALL)
+ render
+ end
+
+ let(:result) { JSON.parse(rendered) }
+
+ it "includes the license id" do
+ result["licenses"].first["id"].should == license.id
+ end
+
+ it "includes the license date range" do
+ result["licenses"].first["issued_at"].should == license.issued_at.to_s
+ result["licenses"].first["expired_at"].should == license.expired_at.to_s
+ end
+
+ it "includes the company information" do
+ result["licenses"].first["company"]["name"].should == license.company.name
+ end
+
+ it "includes information on the type of well" do
+ result["licenses"].first["well_type"]["id"].should == well_type.id
+ result["licenses"].first["well_type"]["acronym"].should == well_type.acronym
+ result["licenses"].first["well_type"]["name"].should == well_type.name
+ end
+
+ it "includes location information" do
+ result["licenses"].first["location"]["latitude"].should == location.latitude
+ result["licenses"].first["location"]["longitude"].should == location.longitude
+ result["licenses"].first["location"]["township"].should == location.township
+ end
+
+ it "includes all the well types" do
+ WellType::ALL.each do |well_type|
+ row = result["well_types"].find { |x| x['id'] == well_type.id }
+ row['acronym'].should == well_type.acronym
+ row['name'].should == well_type.name
+ end
+ end
+
+ it "includes all the license statuses" do
+ LicenseStatus::ALL.each do |status|
+ row = result["license_statuses"].find { |x| x['name'] == status.to_s }
+ row.should_not be_nil
+ end
+ end
+end
diff --git a/spec/views/v1/licenses/index.json.jbuilder_spec.rb b/spec/views/v1/licenses/index.json.jbuilder_spec.rb
new file mode 100644
index 0000000..6a17700
--- /dev/null
+++ b/spec/views/v1/licenses/index.json.jbuilder_spec.rb
@@ -0,0 +1,58 @@
+require "spec_helper"
+
+describe 'v1/licenses/index' do
+ let(:company) { Company.new(name: 'ABC Resources Ltd.') }
+ let(:user) { User.new(company: company) }
+ let(:location) { Location.new(latitude: 51.06, longitude: -114.09, township: '1') }
+ let(:well_type) { WellType::DEV }
+ let(:license) { License.new(id: SecureRandom.uuid, company: company, applicant: user, location: location, issued_at: 2.days.ago, expired_at: 1.day.from_now, well_type: well_type) }
+
+ before :each do
+ assign(:licenses, [license])
+ assign(:well_types, WellType::ALL)
+ assign(:license_statuses, LicenseStatus::ALL)
+ render
+ end
+
+ let(:result) { JSON.parse(rendered) }
+
+ it "includes the license id" do
+ result["licenses"].first["id"].should == license.id
+ end
+
+ it "includes the license date range" do
+ result["licenses"].first["issued_at"].should == license.issued_at.to_s
+ result["licenses"].first["expired_at"].should == license.expired_at.to_s
+ end
+
+ it "includes the company information" do
+ result["licenses"].first["company"]["name"].should == license.company.name
+ end
+
+ it "includes information on the type of well" do
+ result["licenses"].first["well_type"]["id"].should == well_type.id
+ result["licenses"].first["well_type"]["acronym"].should == well_type.acronym
+ result["licenses"].first["well_type"]["name"].should == well_type.name
+ end
+
+ it "includes location information" do
+ result["licenses"].first["location"]["latitude"].should == location.latitude
+ result["licenses"].first["location"]["longitude"].should == location.longitude
+ result["licenses"].first["location"]["township"].should == location.township
+ end
+
+ it "includes all the well types" do
+ WellType::ALL.each do |well_type|
+ row = result["well_types"].find { |x| x['id'] == well_type.id }
+ row['acronym'].should == well_type.acronym
+ row['name'].should == well_type.name
+ end
+ end
+
+ it "includes all the license statuses" do
+ LicenseStatus::ALL.each do |status|
+ row = result["license_statuses"].find { |x| x['name'] == status.to_s }
+ row.should_not be_nil
+ end
+ end
+end
diff --git a/spec/views/v1/licenses/show.json.jbuilder_spec.rb b/spec/views/v1/licenses/show.json.jbuilder_spec.rb
new file mode 100644
index 0000000..f000674
--- /dev/null
+++ b/spec/views/v1/licenses/show.json.jbuilder_spec.rb
@@ -0,0 +1,80 @@
+require "spec_helper"
+
+describe 'v1/licenses/show' do
+ let(:company) { Company.new(name: 'ABC Resources Ltd.') }
+ let(:user) { User.new(first_name: 'john', last_name: 'dielwart', company: company) }
+ let(:location) { Location.new(latitude: 51.06, longitude: -114.09, township: '1') }
+ let(:well_type) { WellType::DEV }
+
+ context "for public licenses" do
+ let(:public_license) { License.new(id: SecureRandom.uuid, company: company, applicant: user, location: location, issued_at: 2.days.ago, expired_at: 1.day.from_now, well_type: well_type) }
+
+ before :each do
+ public_license.stub(:status).and_return(LicenseStatus::ACTIVE)
+ assign(:license, public_license)
+ render
+ end
+
+ let(:result) { JSON.parse(rendered) }
+
+ it "includes the license date range" do
+ result["issued_at"].should == public_license.issued_at.to_s
+ result["expired_at"].should == public_license.expired_at.to_s
+ end
+
+ it "includes the license id" do
+ result["id"].should == public_license.id
+ end
+
+ it "includes the company information" do
+ result["company"]["name"].should == public_license.company.name
+ result["company"]["applicant_name"].should == user.full_name
+ end
+
+ it "includes information on the type of well" do
+ result["well_type"]["id"].should == well_type.id
+ result["well_type"]["acronym"].should == well_type.acronym
+ result["well_type"]["name"].should == well_type.name
+ end
+
+ it "includes location information" do
+ result["location"]["latitude"].should == location.latitude
+ result["location"]["longitude"].should == location.longitude
+ result["location"]["township"].should == location.township
+ end
+
+ it "includes the license status" do
+ result['status'].should == 'active'
+ end
+ end
+
+ context "for confidential licenses" do
+ let(:confidential_license) { License.new(confidential: true, company: company, applicant: user, location: location, well_type: well_type) }
+
+ before :each do
+ confidential_license.stub(:status).and_return(LicenseStatus::CONFIDENTIAL)
+ assign(:license, confidential_license)
+ render
+ end
+
+ let(:result) { JSON.parse(rendered) }
+
+ it "should hide the name of the applicant" do
+ result["company"]["applicant_name"].should == "CONFIDENTIAL"
+ end
+
+ it "should hide the type of well" do
+ result['well_type']['id'].should == ''
+ result['well_type']['acronym'].should == ''
+ result['well_type']['name'].should == 'CONFIDENTIAL'
+ end
+
+ it "should hide the company name" do
+ result["company"]["name"].should == "CONFIDENTIAL"
+ end
+
+ it "includes the license status" do
+ result['status'].should == 'confidential'
+ end
+ end
+end
diff --git a/vendor/assets/javascripts/.keep b/vendor/assets/javascripts/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/assets/javascripts/.keep
diff --git a/vendor/assets/stylesheets/.keep b/vendor/assets/stylesheets/.keep
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/vendor/assets/stylesheets/.keep