diff --git a/Dockerfile b/Dockerfile index 4ee13d4..958515f 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,6 +1,6 @@ FROM ruby:3.2.2 -RUN mkdir -p /var/app -COPY . /app WORKDIR /app +COPY Gemfile Gemfile RUN bundle install -CMD rails server -e development -b 0.0.0.0 --log-to-stdout +COPY . /app +CMD rails server -b 0.0.0.0 --log-to-stdout diff --git a/Gemfile b/Gemfile index f0ccb28..2baef91 100644 --- a/Gemfile +++ b/Gemfile @@ -13,16 +13,7 @@ gem "sqlite3", "~> 1.4" gem "puma", "~> 5.0" # Build JSON APIs with ease [https://github.com/rails/jbuilder] -# gem "jbuilder" - -# Use Redis adapter to run Action Cable in production -# gem "redis", "~> 4.0" - -# Use Kredis to get higher-level data types in Redis [https://github.com/rails/kredis] -# gem "kredis" - -# Use Active Model has_secure_password [https://guides.rubyonrails.org/active_model_basics.html#securepassword] -# gem "bcrypt", "~> 3.1.7" +gem "jbuilder" # Windows does not include zoneinfo files, so bundle the tzinfo-data gem gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] @@ -30,11 +21,10 @@ gem "tzinfo-data", platforms: %i[ mingw mswin x64_mingw jruby ] # Reduces boot times through caching; required in config/boot.rb gem "bootsnap", require: false -# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images] -# gem "image_processing", "~> 1.2" - -# Use Rack CORS for handling Cross-Origin Resource Sharing (CORS), making cross-origin AJAX possible -# gem "rack-cors" +# From Neo4J.rb documentation +gem 'activegraph', '~> 11.3' +gem 'neo4j-ruby-driver', '~> 4.4.3' +gem 'neo4j-rake_tasks' group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem diff --git a/Gemfile.lock b/Gemfile.lock index 222290a..7873b09 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -46,6 +46,13 @@ GEM erubi (~> 1.4) rails-dom-testing (~> 2.0) rails-html-sanitizer (~> 1.1, >= 1.2.0) + activegraph (11.3.1) + activemodel (>= 4.0) + activesupport (>= 4.0) + i18n (!= 1.8.8) + neo4j-ruby-driver (>= 4.4.1) + orm_adapter (~> 0.5.0) + sorted_set activejob (7.0.4.3) activesupport (= 7.0.4.3) globalid (>= 0.3.6) @@ -66,23 +73,37 @@ GEM i18n (>= 1.6, < 2) minitest (>= 5.1) tzinfo (~> 2.0) + async (2.5.1) + console (~> 1.10) + io-event (~> 1.1) + timers (~> 4.1) + async-io (1.34.3) + async bootsnap (1.16.0) msgpack (~> 1.2) builder (3.2.4) concurrent-ruby (1.2.2) + connection_pool (2.4.1) + console (1.16.2) + fiber-local crass (1.0.6) date (3.3.3) debug (1.8.0) irb (>= 1.5.0) reline (>= 0.3.1) erubi (1.12.0) + fiber-local (1.0.0) globalid (1.1.0) activesupport (>= 5.0) i18n (1.13.0) concurrent-ruby (~> 1.0) io-console (0.6.0) + io-event (1.2.2) irb (1.6.4) reline (>= 0.3.0) + jbuilder (2.11.5) + actionview (>= 5.0.0) + activesupport (>= 5.0.0) loofah (2.21.3) crass (~> 1.0.2) nokogiri (>= 1.12.0) @@ -96,6 +117,16 @@ GEM mini_mime (1.1.2) minitest (5.18.0) msgpack (1.7.1) + neo4j-rake_tasks (0.7.19) + os + rake + ruby-progressbar + rubyzip (>= 1.1.7) + neo4j-ruby-driver (4.4.4) + activesupport + async-io + connection_pool + zeitwerk (>= 2.1.10) net-imap (0.3.4) date net-protocol @@ -106,8 +137,14 @@ GEM net-smtp (0.3.3) net-protocol nio4r (2.5.9) + nokogiri (1.15.1-aarch64-linux) + racc (~> 1.4) nokogiri (1.15.1-arm64-darwin) racc (~> 1.4) + nokogiri (1.15.1-x86_64-linux) + racc (~> 1.4) + orm_adapter (0.5.0) + os (1.1.4) puma (5.6.5) nio4r (~> 2.0) racc (1.6.2) @@ -141,11 +178,21 @@ GEM thor (~> 1.0) zeitwerk (~> 2.5) rake (13.0.6) + rbtree (0.4.6) reline (0.3.4) io-console (~> 0.5) + ruby-progressbar (1.13.0) + rubyzip (2.3.2) + set (1.0.3) + sorted_set (1.0.3) + rbtree + set (~> 1.0) + sqlite3 (1.6.3-aarch64-linux) sqlite3 (1.6.3-arm64-darwin) + sqlite3 (1.6.3-x86_64-linux) thor (1.2.2) timeout (0.3.2) + timers (4.3.5) tzinfo (2.0.6) concurrent-ruby (~> 1.0) websocket-driver (0.7.5) @@ -154,11 +201,17 @@ GEM zeitwerk (2.6.8) PLATFORMS + aarch64-linux arm64-darwin-22 + x86_64-linux DEPENDENCIES + activegraph (~> 11.3) bootsnap debug + jbuilder + neo4j-rake_tasks + neo4j-ruby-driver (~> 4.4.3) puma (~> 5.0) rails (~> 7.0.4, >= 7.0.4.3) sqlite3 (~> 1.4) diff --git a/app/controllers/metrics_controller.rb b/app/controllers/metrics_controller.rb index 431eb0c..94f71c9 100644 --- a/app/controllers/metrics_controller.rb +++ b/app/controllers/metrics_controller.rb @@ -1,26 +1,38 @@ class MetricsController < ActionController::API - # GET /metric - def index - render json: {} - end - # POST /metric/:key def create key = params[:key] - render json: {} + value = JSON.parse(request.body.read)["value"] + + metric = Metric.find_or_create_by(key: key) + metric.value = value + + if metric.save() + render json: {} + else + render json: { error: "Unable to save" }, status: :unprocessable_entity + end end - # GET /metric/:key - def show - # Return an empty JSON response - render json: {} + # GET /metric/ + def index + returnable = [] + Metric.all.each do |metric| + returnable << MetricOutput.new(metric.key, metric.value) + end + render json: returnable.to_json end # DELETE /metric/:key def delete key = params[:key] - render json: {} + metric = Metric.find_by(key: key) + if metric.destroy + render json: {} + else + render json: { error: "Unable to delete" }, status: :unprocessable_entity + end end end diff --git a/app/helpers/MetricOutput.rb b/app/helpers/MetricOutput.rb new file mode 100644 index 0000000..2a45c6f --- /dev/null +++ b/app/helpers/MetricOutput.rb @@ -0,0 +1,10 @@ +class MetricOutput + attr_reader :key, :value + + def initialize(key, value) + @key = key + @value = value + end +end + + diff --git a/app/models/metric.rb b/app/models/metric.rb new file mode 100644 index 0000000..3df65a7 --- /dev/null +++ b/app/models/metric.rb @@ -0,0 +1,7 @@ +class Metric + include ActiveGraph::Node + property :key, type: String + property :value, type: Integer, default: 0 + validates :key, :presence => true + +end diff --git a/config/application.rb b/config/application.rb index 86dc546..04bcccd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -1,6 +1,7 @@ require_relative "boot" require "rails/all" +require 'active_graph/railtie' # Require the gems listed in Gemfile, including any gems # you've limited to :test, :development, or :production. @@ -10,7 +11,7 @@ module GrilloTest class Application < Rails::Application # Initialize configuration defaults for originally generated Rails version. config.load_defaults 7.0 - + config.generators { |g| g.orm :active_graph } # Configuration for the application, engines, and railties goes here. # # These settings can be overridden in specific environments using the files diff --git a/db/neo4j/migrate/20230524023145_create_metric.rb b/db/neo4j/migrate/20230524023145_create_metric.rb new file mode 100644 index 0000000..bb7d768 --- /dev/null +++ b/db/neo4j/migrate/20230524023145_create_metric.rb @@ -0,0 +1,11 @@ +class CreateMetric < ActiveGraph::Migrations::Base + disable_transactions! + + def up + add_constraint :Metric, :uuid + end + + def down + drop_constraint :Metric, :uuid + end +end diff --git a/db/neo4j/schema.yml b/db/neo4j/schema.yml new file mode 100644 index 0000000..d10784e --- /dev/null +++ b/db/neo4j/schema.yml @@ -0,0 +1,21 @@ +# This file is auto-generated from the current state of the database. Instead +# of editing this file, please use the migrations feature of Node to +# incrementally modify your database, and then regenerate this schema definition. +# +# Note that this schema.yml definition is the authoritative source for your +# database schema. If you need to create the application database on another +# system, you should be using neo4j:schema:load, not running all the migrations +# from scratch. The latter is a flawed and unsustainable approach (the more migrations +# you'll amass, the slower it'll run and the greater likelihood for issues). +# +# It's strongly recommended that you check this file into your version control system. + +--- +:constraints: +- 'CREATE CONSTRAINT `constraint_3d18f4d7` FOR (n:`Metric`) REQUIRE (n.`uuid`) IS + UNIQUE OPTIONS {indexConfig: {}, indexProvider: ''range-1.0''}' +- 'CREATE CONSTRAINT `constraint_dbcee0a4` FOR (n:`ActiveGraph::Migrations::SchemaMigration`) + REQUIRE (n.`migration_id`) IS UNIQUE OPTIONS {indexConfig: {}, indexProvider: ''range-1.0''}' +:indexes: [] +:versions: +- '20230524023145' diff --git a/docker-compose.yaml b/docker-compose.yaml index 88e79e8..70ce01a 100644 --- a/docker-compose.yaml +++ b/docker-compose.yaml @@ -9,5 +9,23 @@ services: - "3000:3000" volumes: - "./:/app" + depends_on: + - neo4j environment: + - NEO4J_URL=bolt://neo4j:7687 - ENVIRONMENT=development + platform: linux/amd64 + + neo4j: + image: neo4j + ports: + - "7474:7474" + - "7687:7687" + volumes: + - ./neo4j:/data + - ./neo4j/logs:/logs + environment: + - NEO4J_AUTH=none + #- dbms.connector.bolt.listen_address=:7687 + #- dbms.connector.bolt.advertised_address=:7687 + diff --git a/justfile b/justfile new file mode 100644 index 0000000..be39825 --- /dev/null +++ b/justfile @@ -0,0 +1,18 @@ +build: + docker compose build + +run: + docker compose up + +shell: + docker compose run app bash + +migrate: + docker compose run app rails neo4j:migrate + +clean-db: + rm -rf neo4j + +clean: + rm -rf tmp/pids/server.pid + diff --git a/test/fixtures/metrics.yml b/test/fixtures/metrics.yml new file mode 100644 index 0000000..d7a3329 --- /dev/null +++ b/test/fixtures/metrics.yml @@ -0,0 +1,11 @@ +# Read about fixtures at https://api.rubyonrails.org/classes/ActiveRecord/FixtureSet.html + +# This model initially had no columns defined. If you add columns to the +# model remove the "{}" from the fixture names and add the columns immediately +# below each fixture, per the syntax in the comments below +# +one: {} +# column: value +# +two: {} +# column: value diff --git a/test/models/metric_test.rb b/test/models/metric_test.rb new file mode 100644 index 0000000..9e1ddd1 --- /dev/null +++ b/test/models/metric_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class MetricTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end