From 99e8b9c6f269d7d95444b5d5e8944edb95fa3fd2 Mon Sep 17 00:00:00 2001 From: Bilal Date: Fri, 4 Sep 2020 04:07:43 +0300 Subject: [PATCH] handle chip and chip values operations --- app/controllers/chip_values_controller.rb | 40 ++++++++++++++ app/controllers/chips_controller.rb | 29 ++++++++++ app/models/chip.rb | 23 ++++++++ app/models/chip_value.rb | 53 +++++++++++++++++++ config/routes.rb | 8 +-- db/migrate/20200827113649_create_chips.rb | 12 +++++ .../20200827142428_create_chip_values.rb | 12 +++++ db/schema.rb | 24 ++++++++- 8 files changed, 197 insertions(+), 4 deletions(-) create mode 100644 app/controllers/chip_values_controller.rb create mode 100644 app/controllers/chips_controller.rb create mode 100644 app/models/chip.rb create mode 100644 app/models/chip_value.rb create mode 100644 db/migrate/20200827113649_create_chips.rb create mode 100644 db/migrate/20200827142428_create_chip_values.rb diff --git a/app/controllers/chip_values_controller.rb b/app/controllers/chip_values_controller.rb new file mode 100644 index 0000000..928359d --- /dev/null +++ b/app/controllers/chip_values_controller.rb @@ -0,0 +1,40 @@ +class ChipValuesController < ApplicationController + + def create + if ChipValue.create_full_chip_value(chip_value_params) + json_response all_chips_response + else + error_response :bad_request + end + rescue StandardError + error_response :bad_request + end + + def update + if ChipValue.update_full_chip_value(chip_value_params) + json_response all_chips_response + end + rescue StandardError + error_response :bad_request + end + + def destroy + if ChipValue.destroy_full_chip_value(params[:id]) + json_response all_chips_response + else + error_response :bad_request + end + rescue StandardError + error_response :bad_request + end + + private + + def chip_value_params + params.require(:chip_value).permit(:id, :base_chip_id, :secondary_chip_id, :value) + end + + def all_chips_response + Chip.all.order(:name).to_json(include: :base_chip_values) + end +end \ No newline at end of file diff --git a/app/controllers/chips_controller.rb b/app/controllers/chips_controller.rb new file mode 100644 index 0000000..2f70b67 --- /dev/null +++ b/app/controllers/chips_controller.rb @@ -0,0 +1,29 @@ +class ChipsController < ApplicationController + def index + json_response Chip.all.order(:name).to_json(include: :base_chip_values) + end + + def create + chip = Chip.new(chip_params) + if chip.save + json_response chip + else + error_response :bad_request + end + end + + def destroy + chip_id = params[:id] + if chip_id.present? && Chip.destroy(chip_id) + index + else + error_response :bad_request + end + end + + private + + def chip_params + params.require(:chip).permit(:id, :name, :symbol, :enabled) + end +end \ No newline at end of file diff --git a/app/models/chip.rb b/app/models/chip.rb new file mode 100644 index 0000000..9fb244f --- /dev/null +++ b/app/models/chip.rb @@ -0,0 +1,23 @@ +class Chip < ApplicationRecord + has_many :base_chip_values, class_name: "ChipValue", foreign_key: "base_chip_id", dependent: :delete_all + has_many :secondary_chip_values, class_name: "ChipValue", foreign_key: "secondary_chip_id", dependent: :delete_all + + validates :name, uniqueness: true + validates :name, :symbol, presence: true + + after_create :add_chip_values + + private + + # When new chip(currency) is added, add new record to the chip_values table for every existing chip(currency) + def add_chip_values + Chip.all.each do |chip| + next if chip.name == name + + transaction do + ChipValue.new(base_chip: self, secondary_chip: chip, value: 0).save + ChipValue.new(base_chip: chip, secondary_chip: self, value: 0).save + end + end + end +end \ No newline at end of file diff --git a/app/models/chip_value.rb b/app/models/chip_value.rb new file mode 100644 index 0000000..fc2040e --- /dev/null +++ b/app/models/chip_value.rb @@ -0,0 +1,53 @@ +class ChipValue < ApplicationRecord + belongs_to :base_chip, class_name: 'Chip' + belongs_to :secondary_chip, class_name: 'Chip' + + validates :base_chip_id, uniqueness: { scope: :secondary_chip_id } + + def self.create_full_chip_value(params) + base_chip_id = params[:base_chip_id] + secondary_chip_id = params[:secondary_chip_id] + value = params[:value].to_f + + chips = Chip.where(id: [base_chip_id, secondary_chip_id]) + base_chip = chips.first + secondary_chip = chips.second + + mirrored_value = value.zero? ? 0 : (1 / value) + + base_chip_value = ChipValue.new(base_chip: base_chip, secondary_chip: secondary_chip, value: value) + mirrored_chip_value = ChipValue.new(base_chip: secondary_chip, secondary_chip: base_chip, value: mirrored_value) + + transaction do + base_chip_value.save + mirrored_chip_value.save + end + end + + def self.update_full_chip_value(params) + id = params[:id] + new_value = params[:value].to_f + mirrored_value = new_value.zero? ? 0 : (1 / new_value) + + chip_value = ChipValue.find(id) + mirrored_chip_value = ChipValue.where(base_chip_id: chip_value.secondary_chip_id, secondary_chip_id: chip_value.base_chip_id).first + + chip_value.value = new_value + mirrored_chip_value.value = mirrored_value + + transaction do + chip_value.save + mirrored_chip_value.save + end + end + + def self.destroy_full_chip_value(id) + chip_value = ChipValue.find(id) + mirrored_chip_value = ChipValue.where(base_chip_id: chip_value.secondary_chip_id, secondary_chip_id: chip_value.base_chip_id).first + + transaction do + chip_value.destroy + mirrored_chip_value.destroy + end + end +end \ No newline at end of file diff --git a/config/routes.rb b/config/routes.rb index 89da8c0..3021c35 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,8 +1,10 @@ Rails.application.routes.draw do constraints format: :json do - resources :money_moves - resources :homies do - collection do + resources :money_moves + resources :chips, only: %i[index create destroy] + resources :chip_values, only: %i[create update destroy] + resources :homies do + collection do get 'cash' end end diff --git a/db/migrate/20200827113649_create_chips.rb b/db/migrate/20200827113649_create_chips.rb new file mode 100644 index 0000000..989a694 --- /dev/null +++ b/db/migrate/20200827113649_create_chips.rb @@ -0,0 +1,12 @@ +class CreateChips < ActiveRecord::Migration[5.2] + def change + create_table :chips do |t| + t.text :name, null: false + t.text :symbol, null: false + t.boolean :enabled, default: true + t.timestamps + end + + add_index :chips, :name, unique: true + end +end diff --git a/db/migrate/20200827142428_create_chip_values.rb b/db/migrate/20200827142428_create_chip_values.rb new file mode 100644 index 0000000..2d391bd --- /dev/null +++ b/db/migrate/20200827142428_create_chip_values.rb @@ -0,0 +1,12 @@ +class CreateChipValues < ActiveRecord::Migration[5.2] + def change + create_table :chip_values do |t| + t.references :base_chip, foreign_key: { to_table: :chips } + t.references :secondary_chip, foreign_key: { to_table: :chips } + t.decimal :value, precision: 12, scale: 3, null: false + t.timestamps + + t.index [:base_chip_id, :secondary_chip_id], unique: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 0a594d1..babee0e 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,11 +10,31 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2019_06_20_200006) do +ActiveRecord::Schema.define(version: 2020_08_27_142428) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" + create_table "chip_values", force: :cascade do |t| + t.bigint "base_chip_id" + t.bigint "secondary_chip_id" + t.decimal "value", precision: 12, scale: 3, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["base_chip_id", "secondary_chip_id"], name: "index_chip_values_on_base_chip_id_and_secondary_chip_id", unique: true + t.index ["base_chip_id"], name: "index_chip_values_on_base_chip_id" + t.index ["secondary_chip_id"], name: "index_chip_values_on_secondary_chip_id" + end + + create_table "chips", force: :cascade do |t| + t.text "name", null: false + t.text "symbol", null: false + t.boolean "enabled", default: true + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["name"], name: "index_chips_on_name", unique: true + end + create_table "homies", force: :cascade do |t| t.text "name", null: false t.integer "importance", default: 5, null: false @@ -31,4 +51,6 @@ ActiveRecord::Schema.define(version: 2019_06_20_200006) do t.datetime "updated_at", null: false end + add_foreign_key "chip_values", "chips", column: "base_chip_id" + add_foreign_key "chip_values", "chips", column: "secondary_chip_id" end