diff --git a/.gitignore b/.gitignore index 050c9d9..c923c32 100644 --- a/.gitignore +++ b/.gitignore @@ -1,17 +1,17 @@ -# 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/.keep -/tmp +# 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/.keep +/tmp diff --git a/.rspec b/.rspec index 83e16f8..2d868da 100644 --- a/.rspec +++ b/.rspec @@ -1,2 +1,2 @@ ---color ---require spec_helper +--color +--require spec_helper diff --git a/.ruby-version b/.ruby-version index 743af5e..985a8bc 100644 --- a/.ruby-version +++ b/.ruby-version @@ -1 +1 @@ -2.6.8 +2.6.8 diff --git a/2 b/2 new file mode 100644 index 0000000..e69de29 diff --git a/Gemfile b/Gemfile index ca961b3..0833a83 100644 --- a/Gemfile +++ b/Gemfile @@ -1,33 +1,35 @@ -source 'https://rubygems.org' -ruby '2.6.8' - - -# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' -gem 'rails', '~> 5.2.4.4' -# Use sqlite3 as the database for Active Record -gem 'sqlite3', '~> 1.3.13' - -gem 'mimemagic', '~> 0.3.10' -gem 'actionview' -gem 'sprockets', '~>3.0' - -gem "websocket-extensions", ">= 0.1.5" - -# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder -gem 'jbuilder' -# bundle exec rake doc:rails generates the API under doc/api. -gem 'sdoc', '~> 0.4.0', group: :doc - -group :development, :test do - # Call 'byebug' anywhere in the code to stop execution and get a debugger console - gem 'byebug' - gem 'rspec-rails' - gem 'pry' - gem 'bootsnap' -end - -group :development do - # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring - gem 'spring' - gem 'listen' -end +source 'https://rubygems.org' +ruby '2.6.8' + + +# Bundle edge Rails instead: gem 'rails', github: 'rails/rails' +gem 'rails', '~> 5.2.4.5' +# Use sqlite3 as the database for Active Record +gem 'sqlite3', '~> 1.3.13' + +gem 'mimemagic', '~> 0.3.10' +gem 'actionview' +gem 'sprockets', '~>3.0' +gem 'marcel', '~>0.3.3' +gem 'nokogiri', '~>1.13.10' +gem "websocket-extensions", ">= 0.1.5" + +# Build JSON APIs with ease. Read more: https://github.com/rails/jbuilder +gem 'jbuilder' +# bundle exec rake doc:rails generates the API under doc/api. +gem 'sdoc', '~> 0.4.0', group: :doc + +group :development, :test do + # Call 'byebug' anywhere in the code to stop execution and get a debugger console + gem 'byebug' + gem 'rspec-rails' + gem 'pry' + gem 'bootsnap' + gem 'shoulda-matchers', '~> 5.0' +end + +group :development do + # Spring speeds up development by keeping your application running in the background. Read more: https://github.com/rails/spring + gem 'spring' + gem 'listen' +end diff --git a/Gemfile.lock b/Gemfile.lock index 9af1ffe..c602107 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,165 +1,181 @@ GEM remote: https://rubygems.org/ specs: - actioncable (5.2.4.5) - actionpack (= 5.2.4.5) + actioncable (5.2.4.6) + actionpack (= 5.2.4.6) nio4r (~> 2.0) websocket-driver (>= 0.6.1) - actionmailer (5.2.4.5) - actionpack (= 5.2.4.5) - actionview (= 5.2.4.5) - activejob (= 5.2.4.5) + actionmailer (5.2.4.6) + actionpack (= 5.2.4.6) + actionview (= 5.2.4.6) + activejob (= 5.2.4.6) mail (~> 2.5, >= 2.5.4) rails-dom-testing (~> 2.0) - actionpack (5.2.4.5) - actionview (= 5.2.4.5) - activesupport (= 5.2.4.5) + actionpack (5.2.4.6) + actionview (= 5.2.4.6) + activesupport (= 5.2.4.6) rack (~> 2.0, >= 2.0.8) rack-test (>= 0.6.3) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.2) - actionview (5.2.4.5) - activesupport (= 5.2.4.5) + actionview (5.2.4.6) + activesupport (= 5.2.4.6) builder (~> 3.1) erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.0, >= 1.0.3) - activejob (5.2.4.5) - activesupport (= 5.2.4.5) + activejob (5.2.4.6) + activesupport (= 5.2.4.6) globalid (>= 0.3.6) - activemodel (5.2.4.5) - activesupport (= 5.2.4.5) - activerecord (5.2.4.5) - activemodel (= 5.2.4.5) - activesupport (= 5.2.4.5) + activemodel (5.2.4.6) + activesupport (= 5.2.4.6) + activerecord (5.2.4.6) + activemodel (= 5.2.4.6) + activesupport (= 5.2.4.6) arel (>= 9.0) - activestorage (5.2.4.5) - actionpack (= 5.2.4.5) - activerecord (= 5.2.4.5) + activestorage (5.2.4.6) + actionpack (= 5.2.4.6) + activerecord (= 5.2.4.6) marcel (~> 0.3.1) - activesupport (5.2.4.5) + activesupport (5.2.4.6) concurrent-ruby (~> 1.0, >= 1.0.2) i18n (>= 0.7, < 2) minitest (~> 5.1) tzinfo (~> 1.1) arel (9.0.0) - bootsnap (1.7.2) - msgpack (~> 1.0) - builder (3.2.4) + base64 (0.2.0) + bootsnap (1.18.4) + msgpack (~> 1.2) + builder (3.3.0) byebug (11.1.3) coderay (1.1.3) - concurrent-ruby (1.1.8) + concurrent-ruby (1.3.5) crass (1.0.6) - diff-lcs (1.4.4) - erubi (1.10.0) - ffi (1.14.2) - globalid (0.4.2) - activesupport (>= 4.2.0) - i18n (1.8.9) + date (3.4.1) + diff-lcs (1.6.0) + erubi (1.13.1) + ffi (1.17.1) + globalid (1.1.0) + activesupport (>= 5.0) + i18n (1.14.7) concurrent-ruby (~> 1.0) - jbuilder (2.11.2) + jbuilder (2.13.0) + actionview (>= 5.0.0) activesupport (>= 5.0.0) json (1.8.6) - listen (3.4.1) + listen (3.9.0) rb-fsevent (~> 0.10, >= 0.10.3) rb-inotify (~> 0.9, >= 0.9.10) - loofah (2.9.0) + loofah (2.24.0) crass (~> 1.0.2) - nokogiri (>= 1.5.9) - mail (2.7.1) + nokogiri (>= 1.12.0) + mail (2.8.1) mini_mime (>= 0.1.1) + net-imap + net-pop + net-smtp marcel (0.3.3) mimemagic (~> 0.3.2) - method_source (1.0.0) + method_source (1.1.0) mimemagic (0.3.10) nokogiri (~> 1) rake - mini_mime (1.0.2) - mini_portile2 (2.5.0) - minitest (5.14.3) - msgpack (1.4.2) - nio4r (2.5.5) - nokogiri (1.11.1) - mini_portile2 (~> 2.5.0) + mini_mime (1.1.5) + minitest (5.25.4) + msgpack (1.8.0) + net-imap (0.3.8) + date + net-protocol + net-pop (0.1.2) + net-protocol + net-protocol (0.2.2) + timeout + net-smtp (0.5.1) + net-protocol + nio4r (2.7.4) + nokogiri (1.13.10-x86_64-linux) racc (~> 1.4) - nokogiri (1.11.1-x86_64-darwin) - racc (~> 1.4) - pry (0.14.0) + pry (0.15.2) coderay (~> 1.1) method_source (~> 1.0) - racc (1.5.2) - rack (2.2.3) - rack-test (1.1.0) - rack (>= 1.0, < 3) - rails (5.2.4.5) - actioncable (= 5.2.4.5) - actionmailer (= 5.2.4.5) - actionpack (= 5.2.4.5) - actionview (= 5.2.4.5) - activejob (= 5.2.4.5) - activemodel (= 5.2.4.5) - activerecord (= 5.2.4.5) - activestorage (= 5.2.4.5) - activesupport (= 5.2.4.5) + racc (1.8.1) + rack (2.2.12) + rack-test (2.2.0) + rack (>= 1.3) + rails (5.2.4.6) + actioncable (= 5.2.4.6) + actionmailer (= 5.2.4.6) + actionpack (= 5.2.4.6) + actionview (= 5.2.4.6) + activejob (= 5.2.4.6) + activemodel (= 5.2.4.6) + activerecord (= 5.2.4.6) + activestorage (= 5.2.4.6) + activesupport (= 5.2.4.6) bundler (>= 1.3.0) - railties (= 5.2.4.5) + railties (= 5.2.4.6) sprockets-rails (>= 2.0.0) - rails-dom-testing (2.0.3) - activesupport (>= 4.2.0) + rails-dom-testing (2.2.0) + activesupport (>= 5.0.0) + minitest nokogiri (>= 1.6) - rails-html-sanitizer (1.3.0) - loofah (~> 2.3) - railties (5.2.4.5) - actionpack (= 5.2.4.5) - activesupport (= 5.2.4.5) + rails-html-sanitizer (1.5.0) + loofah (~> 2.19, >= 2.19.1) + railties (5.2.4.6) + actionpack (= 5.2.4.6) + activesupport (= 5.2.4.6) method_source rake (>= 0.8.7) thor (>= 0.19.0, < 2.0) - rake (13.0.3) - rb-fsevent (0.10.4) - rb-inotify (0.10.1) + rake (13.2.1) + rb-fsevent (0.11.2) + rb-inotify (0.11.1) ffi (~> 1.0) rdoc (4.3.0) - rspec-core (3.10.1) - rspec-support (~> 3.10.0) - rspec-expectations (3.10.1) + rspec-core (3.13.3) + rspec-support (~> 3.13.0) + rspec-expectations (3.13.3) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-mocks (3.10.2) + rspec-support (~> 3.13.0) + rspec-mocks (3.13.2) diff-lcs (>= 1.2.0, < 2.0) - rspec-support (~> 3.10.0) - rspec-rails (4.0.2) - actionpack (>= 4.2) - activesupport (>= 4.2) - railties (>= 4.2) + rspec-support (~> 3.13.0) + rspec-rails (5.1.2) + actionpack (>= 5.2) + activesupport (>= 5.2) + railties (>= 5.2) rspec-core (~> 3.10) rspec-expectations (~> 3.10) rspec-mocks (~> 3.10) rspec-support (~> 3.10) - rspec-support (3.10.2) + rspec-support (3.13.2) sdoc (0.4.2) json (~> 1.7, >= 1.7.7) rdoc (~> 4.0) - spring (2.1.1) - sprockets (3.7.2) + shoulda-matchers (5.3.0) + activesupport (>= 5.2.0) + spring (3.1.1) + sprockets (3.7.5) + base64 concurrent-ruby (~> 1.0) rack (> 1, < 3) - sprockets-rails (3.2.2) - actionpack (>= 4.0) - activesupport (>= 4.0) + sprockets-rails (3.4.2) + actionpack (>= 5.2) + activesupport (>= 5.2) sprockets (>= 3.0.0) sqlite3 (1.3.13) - thor (1.1.0) + thor (1.3.2) thread_safe (0.3.6) - tzinfo (1.2.9) + timeout (0.4.3) + tzinfo (1.2.11) thread_safe (~> 0.1) - websocket-driver (0.7.3) + websocket-driver (0.7.7) + base64 websocket-extensions (>= 0.1.0) websocket-extensions (0.1.5) PLATFORMS - ruby - x86_64-darwin-18 + x86_64-linux DEPENDENCIES actionview @@ -167,11 +183,14 @@ DEPENDENCIES byebug jbuilder listen + marcel (~> 0.3.3) mimemagic (~> 0.3.10) + nokogiri (~> 1.13.10) pry - rails (~> 5.2.4.4) + rails (~> 5.2.4.5) rspec-rails sdoc (~> 0.4.0) + shoulda-matchers (~> 5.0) spring sprockets (~> 3.0) sqlite3 (~> 1.3.13) @@ -181,4 +200,4 @@ RUBY VERSION ruby 2.6.8p205 BUNDLED WITH - 2.3.10 + 2.4.22 diff --git a/Jenkinsfile b/Jenkinsfile index c34bd0b..a655b45 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -1,34 +1,34 @@ -pipeline { - // Removal or Modification of the following Jenkins file for the integration of WizCLI is a violation of company policy and can result in disciplinary action. If you have any questions or issues, please reach out to Cloud Security Engineering Cloud Security Engineering(https://onemain.atlassian.net/wiki/spaces/CE/pages/19352388162/Cloud+Security+Engineering). We appreciate your support in ensuring we operate safely and securely. - agent any - stages { - stage('Download_WizCLI') { - steps { - // Download_WizCLI - - sh 'echo "Downloading wizcli..."' - sh 'curl -o wizcli https://wizcli.app.wiz.io/wizcli' - sh 'chmod +x wizcli' - } - } - stage('Auth_With_Wiz') { - steps { - // Auth with Wiz - sh 'echo "Authenticating to the Wiz API..."' - withCredentials([usernamePassword(credentialsId: 'wizcli', usernameVariable: 'ID', passwordVariable: 'SECRET')]) { - sh './wizcli auth --id $ID --secret $SECRET'} - } - } - stage('Wiz IAC scan') { - steps { - script { - // Wiz IAC scan - // Removal or Modification of the following Jenkins file for the integration of WizCLI is a violation of company policy and can result in disciplinary action. If you have any questions or issues, please reach out to Cloud Security Engineering Cloud Security Engineering(https://onemain.atlassian.net/wiki/spaces/CE/pages/19352388162/Cloud+Security+Engineering). We appreciate your support in ensuring we operate safely and securely. - env.GIT_REPO_NAME = env.GIT_URL.replaceFirst(/^.*\/([^\/]+?).git$/, '$1') - sh "./wizcli iac scan --path . --tag repo=springleaf-$GIT_REPO_NAME --tag branch=$GIT_BRANCH --tag commit=$GIT_COMMIT -p custom-policy-secrets --policy-hits-only " - sh "./wizcli iac scan --path . --tag repo=springleaf-$GIT_REPO_NAME --tag branch=$GIT_BRANCH --tag commit=$GIT_COMMIT -p custom-policy-high-critical-severity-misconfigurations --policy-hits-only " - } - } - } - } -} +pipeline { + // Removal or Modification of the following Jenkins file for the integration of WizCLI is a violation of company policy and can result in disciplinary action. If you have any questions or issues, please reach out to Cloud Security Engineering Cloud Security Engineering(https://onemain.atlassian.net/wiki/spaces/CE/pages/19352388162/Cloud+Security+Engineering). We appreciate your support in ensuring we operate safely and securely. + agent any + stages { + stage('Download_WizCLI') { + steps { + // Download_WizCLI + + sh 'echo "Downloading wizcli..."' + sh 'curl -o wizcli https://wizcli.app.wiz.io/wizcli' + sh 'chmod +x wizcli' + } + } + stage('Auth_With_Wiz') { + steps { + // Auth with Wiz + sh 'echo "Authenticating to the Wiz API..."' + withCredentials([usernamePassword(credentialsId: 'wizcli', usernameVariable: 'ID', passwordVariable: 'SECRET')]) { + sh './wizcli auth --id $ID --secret $SECRET'} + } + } + stage('Wiz IAC scan') { + steps { + script { + // Wiz IAC scan + // Removal or Modification of the following Jenkins file for the integration of WizCLI is a violation of company policy and can result in disciplinary action. If you have any questions or issues, please reach out to Cloud Security Engineering Cloud Security Engineering(https://onemain.atlassian.net/wiki/spaces/CE/pages/19352388162/Cloud+Security+Engineering). We appreciate your support in ensuring we operate safely and securely. + env.GIT_REPO_NAME = env.GIT_URL.replaceFirst(/^.*\/([^\/]+?).git$/, '$1') + sh "./wizcli iac scan --path . --tag repo=springleaf-$GIT_REPO_NAME --tag branch=$GIT_BRANCH --tag commit=$GIT_COMMIT -p custom-policy-secrets --policy-hits-only " + sh "./wizcli iac scan --path . --tag repo=springleaf-$GIT_REPO_NAME --tag branch=$GIT_BRANCH --tag commit=$GIT_COMMIT -p custom-policy-high-critical-severity-misconfigurations --policy-hits-only " + } + } + } + } +} diff --git a/README.md b/README.md index e5586c4..d5f95e6 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -# Payments Exercise - -Add in the ability to create payments for a given loan using a JSON API call. You should store the payment date and amount. Expose the outstanding balance for a given loan in the JSON vended for `LoansController#show` and `LoansController#index`. The outstanding balance should be calculated as the `funded_amount` minus all of the payment amounts. - -A payment should not be able to be created that exceeds the outstanding balance of a loan. You should return validation errors if a payment can not be created. Expose endpoints for seeing all payments for a given loan as well as seeing an individual payment. +# Payments Exercise + +Add in the ability to create payments for a given loan using a JSON API call. You should store the payment date and amount. Expose the outstanding balance for a given loan in the JSON vended for `LoansController#show` and `LoansController#index`. The outstanding balance should be calculated as the `funded_amount` minus all of the payment amounts. + +A payment should not be able to be created that exceeds the outstanding balance of a loan. You should return validation errors if a payment can not be created. Expose endpoints for seeing all payments for a given loan as well as seeing an individual payment. diff --git a/Rakefile b/Rakefile index ba6b733..6ea7d63 100644 --- a/Rakefile +++ b/Rakefile @@ -1,6 +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__) - -Rails.application.load_tasks +# 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__) + +Rails.application.load_tasks diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb index 09705d1..5a16f9d 100644 --- a/app/controllers/application_controller.rb +++ b/app/controllers/application_controller.rb @@ -1,2 +1,2 @@ -class ApplicationController < ActionController::Base -end +class ApplicationController < ActionController::Base +end diff --git a/app/controllers/loans_controller.rb b/app/controllers/loans_controller.rb index ec98cfa..246e89d 100644 --- a/app/controllers/loans_controller.rb +++ b/app/controllers/loans_controller.rb @@ -1,14 +1,19 @@ -class LoansController < ActionController::API - - rescue_from ActiveRecord::RecordNotFound do |exception| - render json: 'not_found', status: :not_found - end - - def index - render json: Loan.all - end - - def show - render json: Loan.find(params[:id]) - end -end +class LoansController < ApplicationController + rescue_from ActiveRecord::RecordNotFound, with: :not_found + + def index + loans = Loan.all + render json: loans.as_json(methods: :outstanding_balance, include: :payments) + end + + def show + loan = Loan.find(params[:id]) + render json: loan.as_json(methods: :outstanding_balance, include: :payments) + end + + private + + def not_found(exception) + render json: { error: "Not Found" }, status: :not_found + end +end \ No newline at end of file diff --git a/app/controllers/payments_controller.rb b/app/controllers/payments_controller.rb new file mode 100644 index 0000000..ead968b --- /dev/null +++ b/app/controllers/payments_controller.rb @@ -0,0 +1,28 @@ +class PaymentsController < ApplicationController + def create + loan = Loan.find(params[:loan_id]) + payment = loan.payments.build(payment_params) + + if payment.save + render json: payment, status: :created + else + render json: { errors: payment.errors.full_messages }, status: :unprocessable_entity + end + end + + def index + loan = Loan.find(params[:loan_id]) + render json: loan.payments + end + + def show + payment = Payment.find(params[:id]) + render json: payment + end + + private + + def payment_params + params.require(:payment).permit(:amount, :payment_date) + end + end \ No newline at end of file diff --git a/app/models/application_record.rb b/app/models/application_record.rb new file mode 100644 index 0000000..c3236e2 --- /dev/null +++ b/app/models/application_record.rb @@ -0,0 +1,3 @@ +class ApplicationRecord < ActiveRecord::Base + self.abstract_class = true +end \ No newline at end of file diff --git a/app/models/loan.rb b/app/models/loan.rb index aa46eda..8ef9ad7 100644 --- a/app/models/loan.rb +++ b/app/models/loan.rb @@ -1,2 +1,7 @@ -class Loan < ActiveRecord::Base -end +class Loan < ActiveRecord::Base + has_many :payments, dependent: :destroy + + def outstanding_balance + (funded_amount - payments.sum(:amount)).to_f + end +end \ No newline at end of file diff --git a/app/models/payment.rb b/app/models/payment.rb new file mode 100644 index 0000000..b29ac04 --- /dev/null +++ b/app/models/payment.rb @@ -0,0 +1,15 @@ +class Payment < ApplicationRecord + belongs_to :loan + + validates :amount, presence: true, numericality: { greater_than: 0 } + validates :payment_date, presence: true + validate :not_exceed_loan_balance + + private + + def not_exceed_loan_balance + if loan && (loan.outstanding_balance - amount) < 0 + errors.add(:amount, "cannot exceed the outstanding loan balance") + end + end +end \ No newline at end of file diff --git a/bin/bundle b/bin/bundle index f19acf5..b48d3a0 100755 --- a/bin/bundle +++ b/bin/bundle @@ -1,3 +1,3 @@ -#!/usr/bin/env ruby -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) -load Gem.bin_path('bundler', 'bundle') +#!/usr/bin/env ruby +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) +load Gem.bin_path('bundler', 'bundle') diff --git a/bin/rails b/bin/rails index 0739660..a017658 100755 --- a/bin/rails +++ b/bin/rails @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby -APP_PATH = File.expand_path('../config/application', __dir__) -require_relative '../config/boot' -require 'rails/commands' +#!/usr/bin/env ruby +APP_PATH = File.expand_path('../config/application', __dir__) +require_relative '../config/boot' +require 'rails/commands' diff --git a/bin/rake b/bin/rake index 1724048..8704afd 100755 --- a/bin/rake +++ b/bin/rake @@ -1,4 +1,4 @@ -#!/usr/bin/env ruby -require_relative '../config/boot' -require 'rake' -Rake.application.run +#!/usr/bin/env ruby +require_relative '../config/boot' +require 'rake' +Rake.application.run diff --git a/bin/setup b/bin/setup index a334d86..86e68a8 100755 --- a/bin/setup +++ b/bin/setup @@ -1,33 +1,33 @@ -#!/usr/bin/env ruby -require 'fileutils' -include FileUtils - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a starting point to setup your application. - # Add necessary setup steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - # puts "\n== Copying sample files ==" - # unless File.exist?('config/database.yml') - # cp 'config/database.yml.sample', 'config/database.yml' - # end - - puts "\n== Preparing database ==" - system! 'bin/rails db:setup' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a starting point to setup your application. + # Add necessary setup steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + # puts "\n== Copying sample files ==" + # unless File.exist?('config/database.yml') + # cp 'config/database.yml.sample', 'config/database.yml' + # end + + puts "\n== Preparing database ==" + system! 'bin/rails db:setup' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/bin/spring b/bin/spring index 7b45d37..e8830da 100755 --- a/bin/spring +++ b/bin/spring @@ -1,15 +1,15 @@ -#!/usr/bin/env ruby - -# This file loads spring without using Bundler, in order to be fast. -# It gets overwritten when you run the `spring binstub` command. - -unless defined?(Spring) - require "rubygems" - require "bundler" - - if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) - Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } - gem "spring", match[1] - require "spring/binstub" - end -end +#!/usr/bin/env ruby + +# This file loads spring without using Bundler, in order to be fast. +# It gets overwritten when you run the `spring binstub` command. + +unless defined?(Spring) + require "rubygems" + require "bundler" + + if match = Bundler.default_lockfile.read.match(/^GEM$.*?^ (?: )*spring \((.*?)\)$.*?^$/m) + Gem.paths = { "GEM_PATH" => [Bundler.bundle_path.to_s, *Gem.path].uniq } + gem "spring", match[1] + require "spring/binstub" + end +end diff --git a/bin/update b/bin/update index 67d0d49..2dfdb3b 100755 --- a/bin/update +++ b/bin/update @@ -1,28 +1,28 @@ -#!/usr/bin/env ruby -require 'fileutils' -include FileUtils - -# path to your application root. -APP_ROOT = File.expand_path('..', __dir__) - -def system!(*args) - system(*args) || abort("\n== Command #{args} failed ==") -end - -chdir APP_ROOT do - # This script is a way to update your development environment automatically. - # Add necessary update steps to this file. - - puts '== Installing dependencies ==' - system! 'gem install bundler --conservative' - system('bundle check') || system!('bundle install') - - puts "\n== Updating database ==" - system! 'bin/rails db:migrate' - - puts "\n== Removing old logs and tempfiles ==" - system! 'bin/rails log:clear tmp:clear' - - puts "\n== Restarting application server ==" - system! 'bin/rails restart' -end +#!/usr/bin/env ruby +require 'fileutils' +include FileUtils + +# path to your application root. +APP_ROOT = File.expand_path('..', __dir__) + +def system!(*args) + system(*args) || abort("\n== Command #{args} failed ==") +end + +chdir APP_ROOT do + # This script is a way to update your development environment automatically. + # Add necessary update steps to this file. + + puts '== Installing dependencies ==' + system! 'gem install bundler --conservative' + system('bundle check') || system!('bundle install') + + puts "\n== Updating database ==" + system! 'bin/rails db:migrate' + + puts "\n== Removing old logs and tempfiles ==" + system! 'bin/rails log:clear tmp:clear' + + puts "\n== Restarting application server ==" + system! 'bin/rails restart' +end diff --git a/config.ru b/config.ru index bd83b25..faf3aba 100644 --- a/config.ru +++ b/config.ru @@ -1,4 +1,4 @@ -# This file is used by Rack-based servers to start the application. - -require ::File.expand_path('../config/environment', __FILE__) -run Rails.application +# 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 index dcd5f6b..8dcf3c5 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,20 +1,20 @@ -require_relative 'boot' - -require 'rails/all' - -# Require the gems listed in Gemfile, including any gems -# you've limited to :test, :development, or :production. -Bundler.require(*Rails.groups) - -module PaymentsExercise - class Application < Rails::Application - config.api_only = true - - # Initialize configuration defaults for originally generated Rails version. - config.load_defaults 5.1 - - # 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. - end -end +require_relative 'boot' +require 'nokogiri' +require 'rails/all' + +# Require the gems listed in Gemfile, including any gems +# you've limited to :test, :development, or :production. +Bundler.require(*Rails.groups) + +module PaymentsExercise + class Application < Rails::Application + config.api_only = true + + # Initialize configuration defaults for originally generated Rails version. + config.load_defaults 5.1 + + # 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. + end +end diff --git a/config/boot.rb b/config/boot.rb index b9e460c..5343f6c 100644 --- a/config/boot.rb +++ b/config/boot.rb @@ -1,4 +1,4 @@ -ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) - -require 'bundler/setup' # Set up gems listed in the Gemfile. -require 'bootsnap/setup' # Speed up boot time by caching expensive operations. +ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__) + +require 'bundler/setup' # Set up gems listed in the Gemfile. +require 'bootsnap/setup' # Speed up boot time by caching expensive operations. diff --git a/config/cable.yml b/config/cable.yml index d692818..430e775 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,10 +1,10 @@ -development: - adapter: async - -test: - adapter: async - -production: - adapter: redis - url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> - channel_prefix: payments_exercise_production +development: + adapter: async + +test: + adapter: async + +production: + adapter: redis + url: <%= ENV.fetch("REDIS_URL") { "redis://localhost:6379/1" } %> + channel_prefix: payments_exercise_production diff --git a/config/database.yml b/config/database.yml index 1c1a37c..3608801 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,25 +1,25 @@ -# SQLite version 3.x -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem 'sqlite3' -# -default: &default - adapter: sqlite3 - pool: 5 - timeout: 5000 - -development: - <<: *default - database: db/development.sqlite3 - -# Warning: The database defined as "test" will be erased and -# re-generated from your development database when you run "rake". -# Do not set this db to the same as development or production. -test: - <<: *default - database: db/test.sqlite3 - -production: - <<: *default - database: db/production.sqlite3 +# SQLite version 3.x +# gem install sqlite3 +# +# Ensure the SQLite 3 gem is defined in your Gemfile +# gem 'sqlite3' +# +default: &default + adapter: sqlite3 + pool: 5 + timeout: 5000 + +development: + <<: *default + database: db/development.sqlite3 + +# Warning: The database defined as "test" will be erased and +# re-generated from your development database when you run "rake". +# Do not set this db to the same as development or production. +test: + <<: *default + database: db/test.sqlite3 + +production: + <<: *default + database: db/production.sqlite3 diff --git a/config/environment.rb b/config/environment.rb index 426333b..d59d63f 100644 --- a/config/environment.rb +++ b/config/environment.rb @@ -1,5 +1,5 @@ -# Load the Rails application. -require_relative 'application' - -# Initialize the Rails application. -Rails.application.initialize! +# Load the Rails application. +require_relative 'application' + +# Initialize the Rails application. +Rails.application.initialize! diff --git a/config/environments/development.rb b/config/environments/development.rb index d52ec9e..595e03e 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -1,54 +1,54 @@ -Rails.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. - config.consider_all_requests_local = true - - # Enable/disable caching. By default caching is disabled. - # Run rails dev:cache to toggle caching. - if Rails.root.join('tmp', 'caching-dev.txt').exist? - config.action_controller.perform_caching = true - - config.cache_store = :memory_store - config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{2.days.to_i}" - } - else - config.action_controller.perform_caching = false - - config.cache_store = :null_store - end - - # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = :local - - # Don't care if the mailer can't send. - config.action_mailer.raise_delivery_errors = false - - config.action_mailer.perform_caching = 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 - - # Highlight code that triggered database queries in logs. - config.active_record.verbose_query_logs = true - - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true - - # Use an evented file watcher to asynchronously detect changes in source code, - # routes, locales, etc. This feature depends on the listen gem. - config.file_watcher = ActiveSupport::EventedFileUpdateChecker -end +Rails.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. + config.consider_all_requests_local = true + + # Enable/disable caching. By default caching is disabled. + # Run rails dev:cache to toggle caching. + if Rails.root.join('tmp', 'caching-dev.txt').exist? + config.action_controller.perform_caching = true + + config.cache_store = :memory_store + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{2.days.to_i}" + } + else + config.action_controller.perform_caching = false + + config.cache_store = :null_store + end + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Don't care if the mailer can't send. + config.action_mailer.raise_delivery_errors = false + + config.action_mailer.perform_caching = 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 + + # Highlight code that triggered database queries in logs. + config.active_record.verbose_query_logs = true + + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true + + # Use an evented file watcher to asynchronously detect changes in source code, + # routes, locales, etc. This feature depends on the listen gem. + config.file_watcher = ActiveSupport::EventedFileUpdateChecker +end diff --git a/config/environments/production.rb b/config/environments/production.rb index 8c87df2..b293aa3 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -1,85 +1,85 @@ -Rails.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 threaded 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 - - # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] - # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). - # config.require_master_key = true - - # Disable serving static files from the `/public` folder by default since - # Apache or NGINX already handles this. - config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? - - # Enable serving of images, stylesheets, and JavaScripts from an asset server. - # config.action_controller.asset_host = 'http://assets.example.com' - - # 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 - - # Store uploaded files on the local file system (see config/storage.yml for options) - config.active_storage.service = :local - - # Mount Action Cable outside main process or domain - # config.action_cable.mount_path = nil - # config.action_cable.url = 'wss://example.com/cable' - # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] - - # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. - # config.force_ssl = true - - # Use the lowest log level to ensure availability of diagnostic information - # when problems arise. - config.log_level = :debug - - # Prepend all log lines with the following tags. - config.log_tags = [ :request_id ] - - # Use a different cache store in production. - # config.cache_store = :mem_cache_store - - # Use a real queuing backend for Active Job (and separate queues per environment) - # config.active_job.queue_adapter = :resque - # config.active_job.queue_name_prefix = "payments_exercise_#{Rails.env}" - - config.action_mailer.perform_caching = false - - # 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 cannot be found). - config.i18n.fallbacks = true - - # Send deprecation notices to registered listeners. - config.active_support.deprecation = :notify - - # Use default logging formatter so that PID and timestamp are not suppressed. - config.log_formatter = ::Logger::Formatter.new - - # Use a different logger for distributed setups. - # require 'syslog/logger' - # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') - - if ENV["RAILS_LOG_TO_STDOUT"].present? - logger = ActiveSupport::Logger.new(STDOUT) - logger.formatter = config.log_formatter - config.logger = ActiveSupport::TaggedLogging.new(logger) - end - - # Do not dump schema after migrations. - config.active_record.dump_schema_after_migration = false -end +Rails.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 threaded 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 + + # Ensures that a master key has been made available in either ENV["RAILS_MASTER_KEY"] + # or in config/master.key. This key is used to decrypt credentials (and other encrypted files). + # config.require_master_key = true + + # Disable serving static files from the `/public` folder by default since + # Apache or NGINX already handles this. + config.public_file_server.enabled = ENV['RAILS_SERVE_STATIC_FILES'].present? + + # Enable serving of images, stylesheets, and JavaScripts from an asset server. + # config.action_controller.asset_host = 'http://assets.example.com' + + # 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 + + # Store uploaded files on the local file system (see config/storage.yml for options) + config.active_storage.service = :local + + # Mount Action Cable outside main process or domain + # config.action_cable.mount_path = nil + # config.action_cable.url = 'wss://example.com/cable' + # config.action_cable.allowed_request_origins = [ 'http://example.com', /http:\/\/example.*/ ] + + # Force all access to the app over SSL, use Strict-Transport-Security, and use secure cookies. + # config.force_ssl = true + + # Use the lowest log level to ensure availability of diagnostic information + # when problems arise. + config.log_level = :debug + + # Prepend all log lines with the following tags. + config.log_tags = [ :request_id ] + + # Use a different cache store in production. + # config.cache_store = :mem_cache_store + + # Use a real queuing backend for Active Job (and separate queues per environment) + # config.active_job.queue_adapter = :resque + # config.active_job.queue_name_prefix = "payments_exercise_#{Rails.env}" + + config.action_mailer.perform_caching = false + + # 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 cannot be found). + config.i18n.fallbacks = true + + # Send deprecation notices to registered listeners. + config.active_support.deprecation = :notify + + # Use default logging formatter so that PID and timestamp are not suppressed. + config.log_formatter = ::Logger::Formatter.new + + # Use a different logger for distributed setups. + # require 'syslog/logger' + # config.logger = ActiveSupport::TaggedLogging.new(Syslog::Logger.new 'app-name') + + if ENV["RAILS_LOG_TO_STDOUT"].present? + logger = ActiveSupport::Logger.new(STDOUT) + logger.formatter = config.log_formatter + config.logger = ActiveSupport::TaggedLogging.new(logger) + end + + # Do not dump schema after migrations. + config.active_record.dump_schema_after_migration = false +end diff --git a/config/environments/test.rb b/config/environments/test.rb index 0a38fd3..fe10bbc 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -1,46 +1,46 @@ -Rails.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 public file server for tests with Cache-Control for performance. - config.public_file_server.enabled = true - config.public_file_server.headers = { - 'Cache-Control' => "public, max-age=#{1.hour.to_i}" - } - - # 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 - - # Store uploaded files on the local file system in a temporary directory - config.active_storage.service = :test - - config.action_mailer.perform_caching = 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 - - # Raises error for missing translations - # config.action_view.raise_on_missing_translations = true -end +Rails.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 public file server for tests with Cache-Control for performance. + config.public_file_server.enabled = true + config.public_file_server.headers = { + 'Cache-Control' => "public, max-age=#{1.hour.to_i}" + } + + # 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 + + # Store uploaded files on the local file system in a temporary directory + config.active_storage.service = :test + + config.action_mailer.perform_caching = 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 + + # Raises error for missing translations + # config.action_view.raise_on_missing_translations = true +end diff --git a/config/initializers/application_controller_renderer.rb b/config/initializers/application_controller_renderer.rb index 89d2efa..14419c7 100644 --- a/config/initializers/application_controller_renderer.rb +++ b/config/initializers/application_controller_renderer.rb @@ -1,8 +1,8 @@ -# Be sure to restart your server when you modify this file. - -# ActiveSupport::Reloader.to_prepare do -# ApplicationController.renderer.defaults.merge!( -# http_host: 'example.org', -# https: false -# ) -# end +# Be sure to restart your server when you modify this file. + +# ActiveSupport::Reloader.to_prepare do +# ApplicationController.renderer.defaults.merge!( +# http_host: 'example.org', +# https: false +# ) +# end diff --git a/config/initializers/backtrace_silencers.rb b/config/initializers/backtrace_silencers.rb index 59385cd..803738d 100644 --- a/config/initializers/backtrace_silencers.rb +++ b/config/initializers/backtrace_silencers.rb @@ -1,7 +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! +# 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 index 4a994e1..180af8a 100644 --- a/config/initializers/filter_parameter_logging.rb +++ b/config/initializers/filter_parameter_logging.rb @@ -1,4 +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] +# 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 index ac033bf..d173fb9 100644 --- a/config/initializers/inflections.rb +++ b/config/initializers/inflections.rb @@ -1,16 +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 +# 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 index dc18996..b9979aa 100644 --- a/config/initializers/mime_types.rb +++ b/config/initializers/mime_types.rb @@ -1,4 +1,4 @@ -# 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 +# 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 diff --git a/config/initializers/new_framework_defaults_5_1.rb b/config/initializers/new_framework_defaults_5_1.rb index 9010abd..3e1e868 100644 --- a/config/initializers/new_framework_defaults_5_1.rb +++ b/config/initializers/new_framework_defaults_5_1.rb @@ -1,14 +1,14 @@ -# Be sure to restart your server when you modify this file. -# -# This file contains migration options to ease your Rails 5.1 upgrade. -# -# Once upgraded flip defaults one by one to migrate to the new default. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. - -# Make `form_with` generate non-remote forms. -Rails.application.config.action_view.form_with_generates_remote_forms = false - -# Unknown asset fallback will return the path passed in when the given -# asset is not present in the asset pipeline. -# Rails.application.config.assets.unknown_asset_fallback = false +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.1 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make `form_with` generate non-remote forms. +Rails.application.config.action_view.form_with_generates_remote_forms = false + +# Unknown asset fallback will return the path passed in when the given +# asset is not present in the asset pipeline. +# Rails.application.config.assets.unknown_asset_fallback = false diff --git a/config/initializers/new_framework_defaults_5_2.rb b/config/initializers/new_framework_defaults_5_2.rb index 5132a0b..8a92a7e 100644 --- a/config/initializers/new_framework_defaults_5_2.rb +++ b/config/initializers/new_framework_defaults_5_2.rb @@ -1,38 +1,38 @@ -# Be sure to restart your server when you modify this file. -# -# This file contains migration options to ease your Rails 5.2 upgrade. -# -# Once upgraded flip defaults one by one to migrate to the new default. -# -# Read the Guide for Upgrading Ruby on Rails for more info on each option. - -# Make Active Record use stable #cache_key alongside new #cache_version method. -# This is needed for recyclable cache keys. -# Rails.application.config.active_record.cache_versioning = true - -# Use AES-256-GCM authenticated encryption for encrypted cookies. -# Also, embed cookie expiry in signed or encrypted cookies for increased security. -# -# This option is not backwards compatible with earlier Rails versions. -# It's best enabled when your entire app is migrated and stable on 5.2. -# -# Existing cookies will be converted on read then written with the new scheme. -# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true - -# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages -# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. -# Rails.application.config.active_support.use_authenticated_message_encryption = true - -# Add default protection from forgery to ActionController::Base instead of in -# ApplicationController. -# Rails.application.config.action_controller.default_protect_from_forgery = true - -# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and -# 'f' after migrating old data. -Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true - -# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. -# Rails.application.config.active_support.use_sha1_digests = true - -# Make `form_with` generate id attributes for any generated HTML tags. -# Rails.application.config.action_view.form_with_generates_ids = true +# Be sure to restart your server when you modify this file. +# +# This file contains migration options to ease your Rails 5.2 upgrade. +# +# Once upgraded flip defaults one by one to migrate to the new default. +# +# Read the Guide for Upgrading Ruby on Rails for more info on each option. + +# Make Active Record use stable #cache_key alongside new #cache_version method. +# This is needed for recyclable cache keys. +# Rails.application.config.active_record.cache_versioning = true + +# Use AES-256-GCM authenticated encryption for encrypted cookies. +# Also, embed cookie expiry in signed or encrypted cookies for increased security. +# +# This option is not backwards compatible with earlier Rails versions. +# It's best enabled when your entire app is migrated and stable on 5.2. +# +# Existing cookies will be converted on read then written with the new scheme. +# Rails.application.config.action_dispatch.use_authenticated_cookie_encryption = true + +# Use AES-256-GCM authenticated encryption as default cipher for encrypting messages +# instead of AES-256-CBC, when use_authenticated_message_encryption is set to true. +# Rails.application.config.active_support.use_authenticated_message_encryption = true + +# Add default protection from forgery to ActionController::Base instead of in +# ApplicationController. +# Rails.application.config.action_controller.default_protect_from_forgery = true + +# Store boolean values are in sqlite3 databases as 1 and 0 instead of 't' and +# 'f' after migrating old data. +Rails.application.config.active_record.sqlite3.represent_boolean_as_integer = true + +# Use SHA-1 instead of MD5 to generate non-sensitive digests, such as the ETag header. +# Rails.application.config.active_support.use_sha1_digests = true + +# Make `form_with` generate id attributes for any generated HTML tags. +# Rails.application.config.action_view.form_with_generates_ids = true diff --git a/config/initializers/session_store.rb b/config/initializers/session_store.rb index d0387b4..7280c35 100644 --- a/config/initializers/session_store.rb +++ b/config/initializers/session_store.rb @@ -1,3 +1,3 @@ -# Be sure to restart your server when you modify this file. - -Rails.application.config.session_store :cookie_store, key: '_payments_exercise_session' +# Be sure to restart your server when you modify this file. + +Rails.application.config.session_store :cookie_store, key: '_payments_exercise_session' diff --git a/config/initializers/wrap_parameters.rb b/config/initializers/wrap_parameters.rb index bbfc396..be2540b 100644 --- a/config/initializers/wrap_parameters.rb +++ b/config/initializers/wrap_parameters.rb @@ -1,14 +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] -end - -# To enable root element in JSON for ActiveRecord objects. -# ActiveSupport.on_load(:active_record) do -# self.include_root_in_json = true -# end +# 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] +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 index decc5a8..6d5b682 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1,33 +1,33 @@ -# 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. -# -# The following keys must be escaped otherwise they will not be retrieved by -# the default I18n backend: -# -# true, false, on, off, yes, no -# -# Instead, surround them with single quotes. -# -# en: -# 'true': 'foo' -# -# To learn more, please read the Rails Internationalization guide -# available at http://guides.rubyonrails.org/i18n.html. - -en: - hello: "Hello world" +# 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. +# +# The following keys must be escaped otherwise they will not be retrieved by +# the default I18n backend: +# +# true, false, on, off, yes, no +# +# Instead, surround them with single quotes. +# +# en: +# 'true': 'foo' +# +# 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/puma.rb b/config/puma.rb index 1e19380..c1c1fc4 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,56 +1,56 @@ -# Puma can serve each request in a thread from an internal thread pool. -# The `threads` method setting takes two numbers: a minimum and maximum. -# Any libraries that use thread pools should be configured to match -# the maximum value specified for Puma. Default is set to 5 threads for minimum -# and maximum; this matches the default thread size of Active Record. -# -threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } -threads threads_count, threads_count - -# Specifies the `port` that Puma will listen on to receive requests; default is 3000. -# -port ENV.fetch("PORT") { 3000 } - -# Specifies the `environment` that Puma will run in. -# -environment ENV.fetch("RAILS_ENV") { "development" } - -# Specifies the number of `workers` to boot in clustered mode. -# Workers are forked webserver processes. If using threads and workers together -# the concurrency of the application would be max `threads` * `workers`. -# Workers do not work on JRuby or Windows (both of which do not support -# processes). -# -# workers ENV.fetch("WEB_CONCURRENCY") { 2 } - -# Use the `preload_app!` method when specifying a `workers` number. -# This directive tells Puma to first boot the application and load code -# before forking the application. This takes advantage of Copy On Write -# process behavior so workers use less memory. If you use this option -# you need to make sure to reconnect any threads in the `on_worker_boot` -# block. -# -# preload_app! - -# If you are preloading your application and using Active Record, it's -# recommended that you close any connections to the database before workers -# are forked to prevent connection leakage. -# -# before_fork do -# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) -# end - -# The code in the `on_worker_boot` will be called if you are using -# clustered mode by specifying a number of `workers`. After each worker -# process is booted, this block will be run. If you are using the `preload_app!` -# option, you will want to use this block to reconnect to any threads -# or connections that may have been created at application boot, as Ruby -# cannot share connections between processes. -# -# on_worker_boot do -# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) -# end -# - -# Allow puma to be restarted by `rails restart` command. -plugin :tmp_restart +# Puma can serve each request in a thread from an internal thread pool. +# The `threads` method setting takes two numbers: a minimum and maximum. +# Any libraries that use thread pools should be configured to match +# the maximum value specified for Puma. Default is set to 5 threads for minimum +# and maximum; this matches the default thread size of Active Record. +# +threads_count = ENV.fetch("RAILS_MAX_THREADS") { 5 } +threads threads_count, threads_count + +# Specifies the `port` that Puma will listen on to receive requests; default is 3000. +# +port ENV.fetch("PORT") { 3000 } + +# Specifies the `environment` that Puma will run in. +# +environment ENV.fetch("RAILS_ENV") { "development" } + +# Specifies the number of `workers` to boot in clustered mode. +# Workers are forked webserver processes. If using threads and workers together +# the concurrency of the application would be max `threads` * `workers`. +# Workers do not work on JRuby or Windows (both of which do not support +# processes). +# +# workers ENV.fetch("WEB_CONCURRENCY") { 2 } + +# Use the `preload_app!` method when specifying a `workers` number. +# This directive tells Puma to first boot the application and load code +# before forking the application. This takes advantage of Copy On Write +# process behavior so workers use less memory. If you use this option +# you need to make sure to reconnect any threads in the `on_worker_boot` +# block. +# +# preload_app! + +# If you are preloading your application and using Active Record, it's +# recommended that you close any connections to the database before workers +# are forked to prevent connection leakage. +# +# before_fork do +# ActiveRecord::Base.connection_pool.disconnect! if defined?(ActiveRecord) +# end + +# The code in the `on_worker_boot` will be called if you are using +# clustered mode by specifying a number of `workers`. After each worker +# process is booted, this block will be run. If you are using the `preload_app!` +# option, you will want to use this block to reconnect to any threads +# or connections that may have been created at application boot, as Ruby +# cannot share connections between processes. +# +# on_worker_boot do +# ActiveRecord::Base.establish_connection if defined?(ActiveRecord) +# end +# + +# Allow puma to be restarted by `rails restart` command. +plugin :tmp_restart diff --git a/config/routes.rb b/config/routes.rb index 89db866..d75b1da 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,3 +1,5 @@ -Rails.application.routes.draw do - resources :loans, defaults: {format: :json} -end +Rails.application.routes.draw do + resources :loans, only: [:index, :show] do + resources :payments, only: [:index, :create, :show] + end +end \ No newline at end of file diff --git a/config/secrets.yml b/config/secrets.yml index 0ae3672..860569a 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -1,32 +1,32 @@ -# 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 `rails secret` to generate a secure secret key. - -# Make sure the secrets in this file are kept private -# if you're sharing your code publicly. - -# Shared secrets are available across all environments. - -# shared: -# api_key: a1B2c3D4e5F6 - -# Environmental secrets are only available for that specific environment. - -development: - secret_key_base: 1b24effe3982ffe71f045974c6345efa21f8a40c48041a6cb9dd4dfdbbf55cc29600769c37a57253916f2ea1ffa053d1818e0c884b85195440b26698c53e30c7 - -test: - secret_key_base: 0a1eeacb01d08f3805c8f8331d94d994d6cc7b7de95368f88f2f707d9630aec438ae284501267e579a5aa1758f03c310275c359f66fbffb081c4be5d69ad45da - -# Do not keep production secrets in the unencrypted secrets file. -# Instead, either read values from the environment. -# Or, use `bin/rails secrets:setup` to configure encrypted secrets -# and move the `production:` environment over there. - -production: - secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> +# 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 `rails secret` to generate a secure secret key. + +# Make sure the secrets in this file are kept private +# if you're sharing your code publicly. + +# Shared secrets are available across all environments. + +# shared: +# api_key: a1B2c3D4e5F6 + +# Environmental secrets are only available for that specific environment. + +development: + secret_key_base: 1b24effe3982ffe71f045974c6345efa21f8a40c48041a6cb9dd4dfdbbf55cc29600769c37a57253916f2ea1ffa053d1818e0c884b85195440b26698c53e30c7 + +test: + secret_key_base: 0a1eeacb01d08f3805c8f8331d94d994d6cc7b7de95368f88f2f707d9630aec438ae284501267e579a5aa1758f03c310275c359f66fbffb081c4be5d69ad45da + +# Do not keep production secrets in the unencrypted secrets file. +# Instead, either read values from the environment. +# Or, use `bin/rails secrets:setup` to configure encrypted secrets +# and move the `production:` environment over there. + +production: + secret_key_base: <%= ENV["SECRET_KEY_BASE"] %> diff --git a/config/spring.rb b/config/spring.rb index c9119b4..5c651dc 100644 --- a/config/spring.rb +++ b/config/spring.rb @@ -1,6 +1,6 @@ -%w( - .ruby-version - .rbenv-vars - tmp/restart.txt - tmp/caching-dev.txt -).each { |path| Spring.watch(path) } +%w( + .ruby-version + .rbenv-vars + tmp/restart.txt + tmp/caching-dev.txt +).each { |path| Spring.watch(path) } diff --git a/config/storage.yml b/config/storage.yml index d32f76e..a6cba44 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -1,34 +1,34 @@ -test: - service: Disk - root: <%= Rails.root.join("tmp/storage") %> - -local: - service: Disk - root: <%= Rails.root.join("storage") %> - -# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) -# amazon: -# service: S3 -# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> -# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> -# region: us-east-1 -# bucket: your_own_bucket - -# Remember not to checkin your GCS keyfile to a repository -# google: -# service: GCS -# project: your_project -# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> -# bucket: your_own_bucket - -# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) -# microsoft: -# service: AzureStorage -# storage_account_name: your_account_name -# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> -# container: your_container_name - -# mirror: -# service: Mirror -# primary: local -# mirrors: [ amazon, google, microsoft ] +test: + service: Disk + root: <%= Rails.root.join("tmp/storage") %> + +local: + service: Disk + root: <%= Rails.root.join("storage") %> + +# Use rails credentials:edit to set the AWS secrets (as aws:access_key_id|secret_access_key) +# amazon: +# service: S3 +# access_key_id: <%= Rails.application.credentials.dig(:aws, :access_key_id) %> +# secret_access_key: <%= Rails.application.credentials.dig(:aws, :secret_access_key) %> +# region: us-east-1 +# bucket: your_own_bucket + +# Remember not to checkin your GCS keyfile to a repository +# google: +# service: GCS +# project: your_project +# credentials: <%= Rails.root.join("path/to/gcs.keyfile") %> +# bucket: your_own_bucket + +# Use rails credentials:edit to set the Azure Storage secret (as azure_storage:storage_access_key) +# microsoft: +# service: AzureStorage +# storage_account_name: your_account_name +# storage_access_key: <%= Rails.application.credentials.dig(:azure_storage, :storage_access_key) %> +# container: your_container_name + +# mirror: +# service: Mirror +# primary: local +# mirrors: [ amazon, google, microsoft ] diff --git a/db/migrate/20150903195334_create_loans.rb b/db/migrate/20150903195334_create_loans.rb index 37865a3..1a4d67b 100644 --- a/db/migrate/20150903195334_create_loans.rb +++ b/db/migrate/20150903195334_create_loans.rb @@ -1,8 +1,8 @@ -class CreateLoans < ActiveRecord::Migration[5.1] - def change - create_table :loans do |t| - t.decimal :funded_amount, precision: 8, scale: 2 - t.timestamps null: false - end - end -end +class CreateLoans < ActiveRecord::Migration[5.1] + def change + create_table :loans do |t| + t.decimal :funded_amount, precision: 8, scale: 2 + t.timestamps null: false + end + end +end diff --git a/db/migrate/20250305164657_create_payments.rb b/db/migrate/20250305164657_create_payments.rb new file mode 100644 index 0000000..8e43e0e --- /dev/null +++ b/db/migrate/20250305164657_create_payments.rb @@ -0,0 +1,11 @@ +class CreatePayments < ActiveRecord::Migration[5.2] + def change + create_table :payments do |t| + t.references :loan, null: false, foreign_key: true + t.decimal :amount, precision: 10, scale: 2, null: false + t.date :payment_date, null: false + + t.timestamps + end + end +end \ No newline at end of file diff --git a/db/schema.rb b/db/schema.rb index 3b0f090..87f1f72 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 20150903195334) do +ActiveRecord::Schema.define(version: 2025_03_05_164657) do create_table "loans", force: :cascade do |t| t.decimal "funded_amount", precision: 8, scale: 2 @@ -18,4 +18,13 @@ t.datetime "updated_at", null: false end + create_table "payments", force: :cascade do |t| + t.integer "loan_id", null: false + t.decimal "amount", precision: 10, scale: 2, null: false + t.date "payment_date", null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["loan_id"], name: "index_payments_on_loan_id" + end + end diff --git a/db/seeds.rb b/db/seeds.rb index 2cc36d8..cbea5b1 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -1 +1,3 @@ -Loan.create!(funded_amount: 100.0) +loan = Loan.create(funded_amount: 100.0) +loan.payments.create(amount: 20.0, payment_date: Date.today) +loan.payments.create(amount: 30.0, payment_date: Date.today) \ No newline at end of file diff --git a/public/404.html b/public/404.html index b612547..00431b8 100644 --- a/public/404.html +++ b/public/404.html @@ -1,67 +1,67 @@ - - - - The page you were looking for doesn't exist (404) - - - - - - -
-
-

The page you were looking for doesn't exist.

-

You may have mistyped the address or the page may have moved.

-
-

If you are the application owner check the logs for more information.

-
- - + + + + The page you were looking for doesn't exist (404) + + + + + + +
+
+

The page you were looking for doesn't exist.

+

You may have mistyped the address or the page may have moved.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/422.html b/public/422.html index a21f82b..f313786 100644 --- a/public/422.html +++ b/public/422.html @@ -1,67 +1,67 @@ - - - - The change you wanted was rejected (422) - - - - - - -
-
-

The change you wanted was rejected.

-

Maybe you tried to change something you didn't have access to.

-
-

If you are the application owner check the logs for more information.

-
- - + + + + The change you wanted was rejected (422) + + + + + + +
+
+

The change you wanted was rejected.

+

Maybe you tried to change something you didn't have access to.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/500.html b/public/500.html index 061abc5..860aefd 100644 --- a/public/500.html +++ b/public/500.html @@ -1,66 +1,66 @@ - - - - We're sorry, but something went wrong (500) - - - - - - -
-
-

We're sorry, but something went wrong.

-
-

If you are the application owner check the logs for more information.

-
- - + + + + We're sorry, but something went wrong (500) + + + + + + +
+
+

We're sorry, but something went wrong.

+
+

If you are the application owner check the logs for more information.

+
+ + diff --git a/public/robots.txt b/public/robots.txt index 3c9c7c0..33838cd 100644 --- a/public/robots.txt +++ b/public/robots.txt @@ -1,5 +1,5 @@ -# See http://www.robotstxt.org/robotstxt.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: / +# See http://www.robotstxt.org/robotstxt.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/loans_controller_spec.rb b/spec/controllers/loans_controller_spec.rb index 312463a..fa6658a 100644 --- a/spec/controllers/loans_controller_spec.rb +++ b/spec/controllers/loans_controller_spec.rb @@ -1,26 +1,21 @@ -require 'rails_helper' - -RSpec.describe LoansController, type: :controller do - describe '#index' do - it 'responds with a 200' do - get :index - expect(response).to have_http_status(:ok) - end - end - - describe '#show' do - let(:loan) { Loan.create!(funded_amount: 100.0) } - - it 'responds with a 200' do - get :show, params: { id: loan.id } - expect(response).to have_http_status(:ok) - end - - context 'if the loan is not found' do - it 'responds with a 404' do - get :show, params: { id: 10000 } - expect(response).to have_http_status(:not_found) - end - end - end -end +require 'rails_helper' + +RSpec.describe LoansController, type: :controller do + let!(:loan) { Loan.create!(funded_amount: 100.0) } + + describe '#index' do + it 'responds with a 200' do + get :index + expect(response).to have_http_status(:ok) + end + end + + describe '#show' do + it 'returns a specific loan' do + get :show, params: { id: loan.id } + + json_response = JSON.parse(response.body) + expect(json_response['funded_amount']).to eq(loan.funded_amount.to_s) + end + end +end \ No newline at end of file diff --git a/spec/controllers/payments_controller_spec.rb b/spec/controllers/payments_controller_spec.rb new file mode 100644 index 0000000..df75d3a --- /dev/null +++ b/spec/controllers/payments_controller_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +RSpec.describe PaymentsController, type: :controller do + let!(:loan) { Loan.create!(funded_amount: 100.0) } + + describe '#index' do + it 'returns all payments for a loan' do + Payment.create!(loan: loan, amount: 20, payment_date: Date.today) + Payment.create!(loan: loan, amount: 30, payment_date: Date.today) + + get :index, params: { loan_id: loan.id } + + json_response = JSON.parse(response.body) + expect(json_response.size).to eq(2) + end + end + + describe '#show' do + it 'returns a specific payment' do + payment = Payment.create!(loan: loan, amount: 25, payment_date: Date.today) + + get :show, params: { loan_id: loan.id, id: payment.id } + + json_response = JSON.parse(response.body) + expect(json_response['amount']).to eq(payment.amount.to_s) + end + end +end \ No newline at end of file diff --git a/spec/models/payment_spec.rb b/spec/models/payment_spec.rb new file mode 100644 index 0000000..61d43b7 --- /dev/null +++ b/spec/models/payment_spec.rb @@ -0,0 +1,28 @@ +require 'rails_helper' + +RSpec.describe Payment, type: :model do + describe 'associations' do + it 'belongs to loan' do + loan = Loan.create!(funded_amount: 100.0) + payment = Payment.create!(loan: loan, amount: 50, payment_date: Date.today) + expect(payment.loan).to eq(loan) + end + end + + describe 'validations' do + it 'validates presence of amount' do + payment = Payment.new(amount: nil) + expect(payment.valid?).to be false + end + + it 'validates numericality of amount' do + payment = Payment.new(amount: -10) + expect(payment.valid?).to be false + end + + it 'validates presence of payment_date' do + payment = Payment.new(payment_date: nil) + expect(payment.valid?).to be false + end + end +end \ No newline at end of file diff --git a/spec/rails_helper.rb b/spec/rails_helper.rb index 88ff2d0..8791071 100644 --- a/spec/rails_helper.rb +++ b/spec/rails_helper.rb @@ -1,52 +1,66 @@ -# This file is copied to spec/ when you run 'rails generate rspec:install' -ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../../config/environment', __FILE__) -# Prevent database truncation if the environment is production -abort("The Rails environment is running in production mode!") if Rails.env.production? -require 'spec_helper' -require 'rspec/rails' -# Add additional requires below this line. Rails is not loaded until this point! - -# Requires supporting ruby files with custom matchers and macros, etc, in -# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are -# run as spec files by default. This means that files in spec/support that end -# in _spec.rb will both be required and run as specs, causing the specs to be -# run twice. It is recommended that you do not name files matching this glob to -# end with _spec.rb. You can configure this pattern with the --pattern -# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. -# -# The following line is provided for convenience purposes. It has the downside -# of increasing the boot-up time by auto-requiring all files in the support -# directory. Alternatively, in the individual `*_spec.rb` files, manually -# require only the support files necessary. -# -# 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.maintain_test_schema! - -RSpec.configure do |config| - # 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 - - # RSpec Rails can automatically mix in different behaviours to your tests - # based on their file location, for example enabling you to call `get` and - # `post` in specs under `spec/controllers`. - # - # You can disable this behaviour by removing the line below, and instead - # explicitly tag your specs with their type, e.g.: - # - # RSpec.describe UsersController, :type => :controller do - # # ... - # end - # - # The different available types are documented in the features, such as in - # https://relishapp.com/rspec/rspec-rails/docs - config.infer_spec_type_from_file_location! -end +# This file is copied to spec/ when you run 'rails generate rspec:install' +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) +# Prevent database truncation if the environment is production +abort("The Rails environment is running in production mode!") if Rails.env.production? +require 'spec_helper' +require 'rspec/rails' + +# Add additional requires below this line. Rails is not loaded until this point! + +# Requires supporting ruby files with custom matchers and macros, etc, in +# spec/support/ and its subdirectories. Files matching `spec/**/*_spec.rb` are +# run as spec files by default. This means that files in spec/support that end +# in _spec.rb will both be required and run as specs, causing the specs to be +# run twice. It is recommended that you do not name files matching this glob to +# end with _spec.rb. You can configure this pattern with the --pattern +# option on the command line or in ~/.rspec, .rspec or `.rspec-local`. +# +# The following line is provided for convenience purposes. It has the downside +# of increasing the boot-up time by auto-requiring all files in the support +# directory. Alternatively, in the individual `*_spec.rb` files, manually +# require only the support files necessary. +# +# 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.maintain_test_schema! + + + + + +RSpec.configure do |config| + # 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 + + # RSpec Rails can automatically mix in different behaviours to your tests + # based on their file location, for example enabling you to call `get` and + # `post` in specs under `spec/controllers`. + # + # You can disable this behaviour by removing the line below, and instead + # explicitly tag your specs with their type, e.g.: + # + # RSpec.describe UsersController, :type => :controller do + # # ... + # end + # + # The different available types are documented in the features, such as in + # https://relishapp.com/rspec/rspec-rails/docs + config.infer_spec_type_from_file_location! + + Shoulda::Matchers.configure do |config| + config.integrate do |with| + with.test_framework :rspec + with.library :active_record + with.library :active_model + with.library :action_controller + end + end +end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 913e28a..b6d0024 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,92 +1,92 @@ -# This file was generated by the `rails generate rspec:install` command. Conventionally, all -# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. -# The generated `.rspec` file contains `--require spec_helper` which will cause -# this file to always be loaded, without a need to explicitly require it in any -# files. -# -# Given that it is always loaded, you are encouraged to keep this file as -# light-weight as possible. Requiring heavyweight dependencies from this file -# will add to the boot time of your test suite on EVERY test run, even for an -# individual file that may not need all of that loaded. Instead, consider making -# a separate helper file that requires the additional dependencies and performs -# the additional setup, and require it from the spec files that actually need -# it. -# -# The `.rspec` file also contains a few flags that are not defaults but that -# users commonly want. -# -# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration -RSpec.configure do |config| - # rspec-expectations config goes here. You can use an alternate - # assertion/expectation library such as wrong or the stdlib/minitest - # assertions if you prefer. - config.expect_with :rspec do |expectations| - # This option will default to `true` in RSpec 4. It makes the `description` - # and `failure_message` of custom matchers include text for helper methods - # defined using `chain`, e.g.: - # be_bigger_than(2).and_smaller_than(4).description - # # => "be bigger than 2 and smaller than 4" - # ...rather than: - # # => "be bigger than 2" - expectations.include_chain_clauses_in_custom_matcher_descriptions = true - end - - # rspec-mocks config goes here. You can use an alternate test double - # library (such as bogus or mocha) by changing the `mock_with` option here. - config.mock_with :rspec do |mocks| - # Prevents you from mocking or stubbing a method that does not exist on - # a real object. This is generally recommended, and will default to - # `true` in RSpec 4. - mocks.verify_partial_doubles = true - end - -# The settings below are suggested to provide a good initial experience -# with RSpec, but feel free to customize to your heart's content. -=begin - # These two settings work together to allow you to limit a spec run - # to individual examples or groups you care about by tagging them with - # `:focus` metadata. When nothing is tagged with `:focus`, all examples - # get run. - config.filter_run :focus - config.run_all_when_everything_filtered = true - - # Allows RSpec to persist some state between runs in order to support - # the `--only-failures` and `--next-failure` CLI options. We recommend - # you configure your source control system to ignore this file. - config.example_status_persistence_file_path = "spec/examples.txt" - - # Limits the available syntax to the non-monkey patched syntax that is - # recommended. For more details, see: - # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax - # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ - # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching - config.disable_monkey_patching! - - # Many RSpec users commonly either run the entire suite or an individual - # file, and it's useful to allow more verbose output when running an - # individual spec file. - if config.files_to_run.one? - # Use the documentation formatter for detailed output, - # unless a formatter has already been configured - # (e.g. via a command-line flag). - config.default_formatter = 'doc' - end - - # Print the 10 slowest examples and example groups at the - # end of the spec run, to help surface which specs are running - # particularly slow. - config.profile_examples = 10 - - # 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 - - # Seed global randomization in this process using the `--seed` CLI option. - # Setting this allows you to use `--seed` to deterministically reproduce - # test failures related to randomization by passing the same `--seed` value - # as the one that triggered the failure. - Kernel.srand config.seed -=end -end +# This file was generated by the `rails generate rspec:install` command. Conventionally, all +# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`. +# The generated `.rspec` file contains `--require spec_helper` which will cause +# this file to always be loaded, without a need to explicitly require it in any +# files. +# +# Given that it is always loaded, you are encouraged to keep this file as +# light-weight as possible. Requiring heavyweight dependencies from this file +# will add to the boot time of your test suite on EVERY test run, even for an +# individual file that may not need all of that loaded. Instead, consider making +# a separate helper file that requires the additional dependencies and performs +# the additional setup, and require it from the spec files that actually need +# it. +# +# The `.rspec` file also contains a few flags that are not defaults but that +# users commonly want. +# +# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration +RSpec.configure do |config| + # rspec-expectations config goes here. You can use an alternate + # assertion/expectation library such as wrong or the stdlib/minitest + # assertions if you prefer. + config.expect_with :rspec do |expectations| + # This option will default to `true` in RSpec 4. It makes the `description` + # and `failure_message` of custom matchers include text for helper methods + # defined using `chain`, e.g.: + # be_bigger_than(2).and_smaller_than(4).description + # # => "be bigger than 2 and smaller than 4" + # ...rather than: + # # => "be bigger than 2" + expectations.include_chain_clauses_in_custom_matcher_descriptions = true + end + + # rspec-mocks config goes here. You can use an alternate test double + # library (such as bogus or mocha) by changing the `mock_with` option here. + config.mock_with :rspec do |mocks| + # Prevents you from mocking or stubbing a method that does not exist on + # a real object. This is generally recommended, and will default to + # `true` in RSpec 4. + mocks.verify_partial_doubles = true + end + +# The settings below are suggested to provide a good initial experience +# with RSpec, but feel free to customize to your heart's content. +=begin + # These two settings work together to allow you to limit a spec run + # to individual examples or groups you care about by tagging them with + # `:focus` metadata. When nothing is tagged with `:focus`, all examples + # get run. + config.filter_run :focus + config.run_all_when_everything_filtered = true + + # Allows RSpec to persist some state between runs in order to support + # the `--only-failures` and `--next-failure` CLI options. We recommend + # you configure your source control system to ignore this file. + config.example_status_persistence_file_path = "spec/examples.txt" + + # Limits the available syntax to the non-monkey patched syntax that is + # recommended. For more details, see: + # - http://myronmars.to/n/dev-blog/2012/06/rspecs-new-expectation-syntax + # - http://www.teaisaweso.me/blog/2013/05/27/rspecs-new-message-expectation-syntax/ + # - http://myronmars.to/n/dev-blog/2014/05/notable-changes-in-rspec-3#new__config_option_to_disable_rspeccore_monkey_patching + config.disable_monkey_patching! + + # Many RSpec users commonly either run the entire suite or an individual + # file, and it's useful to allow more verbose output when running an + # individual spec file. + if config.files_to_run.one? + # Use the documentation formatter for detailed output, + # unless a formatter has already been configured + # (e.g. via a command-line flag). + config.default_formatter = 'doc' + end + + # Print the 10 slowest examples and example groups at the + # end of the spec run, to help surface which specs are running + # particularly slow. + config.profile_examples = 10 + + # 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 + + # Seed global randomization in this process using the `--seed` CLI option. + # Setting this allows you to use `--seed` to deterministically reproduce + # test failures related to randomization by passing the same `--seed` value + # as the one that triggered the failure. + Kernel.srand config.seed +=end +end diff --git a/test/test_helper.rb b/test/test_helper.rb index 92e39b2..0fc64bd 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -1,10 +1,10 @@ -ENV['RAILS_ENV'] ||= 'test' -require File.expand_path('../../config/environment', __FILE__) -require 'rails/test_help' - -class ActiveSupport::TestCase - # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. - fixtures :all - - # Add more helper methods to be used by all tests here... -end +ENV['RAILS_ENV'] ||= 'test' +require File.expand_path('../../config/environment', __FILE__) +require 'rails/test_help' + +class ActiveSupport::TestCase + # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order. + fixtures :all + + # Add more helper methods to be used by all tests here... +end