From 731b91baa279a19304b1ac7f48b172fdd70d2bb1 Mon Sep 17 00:00:00 2001 From: loiswells97 Date: Fri, 22 Jul 2022 08:37:11 +0000 Subject: [PATCH 1/6] Create draft PR for #65 From 275a7dfcd8c2d4398c9f45e996c6787f8660f459 Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Fri, 22 Jul 2022 08:38:54 +0000 Subject: [PATCH 2/6] Add ability to create non-blank projects --- app/concepts/project/operation/create.rb | 38 ++++++++++++++++------ app/controllers/api/projects_controller.rb | 7 ++-- db/schema.rb | 15 ++++----- 3 files changed, 38 insertions(+), 22 deletions(-) diff --git a/app/concepts/project/operation/create.rb b/app/concepts/project/operation/create.rb index 7fd25a6a..e7ab8bbe 100644 --- a/app/concepts/project/operation/create.rb +++ b/app/concepts/project/operation/create.rb @@ -5,16 +5,34 @@ module Operation class Create require 'operation_response' - def self.call(user_id:) - response = OperationResponse.new - response[:project] = Project.new(user_id: user_id, project_type: 'python') - response[:project].components.build(name: 'main', extension: 'py', default: true, index: 0) - response[:project].save! - response - rescue StandardError - # TODO: log error - response[:error] = 'Error creating project' - response + DEFAULT_COMPONENT = { 'name' => 'main', 'extension' => 'py', 'default' => true, 'index' => 0 }.freeze + DEFAULT_PROJECT = { 'type' => 'python', 'name' => 'Untitled project', 'components' => [DEFAULT_COMPONENT], + 'image_list' => [] }.freeze + + class << self + def call(user_id:, params:) + response = OperationResponse.new + + project = DEFAULT_PROJECT.merge(params) + new_project = Project.new(project_type: project['type'], user_id: user_id, name: project['name']) + new_project.components.build(project['components']) + + response[:project] = new_project + response[:project].save! + response + rescue StandardError + # TODO: log error + response[:error] = 'Error creating project' + response + end + + private + + def create_with_content(project, user_id) + new_project = Project.new(project_type: project[:type], user_id: user_id, name: 'Untitled Project') + new_project.components.build(project[:components]) + new_project + end end end end diff --git a/app/controllers/api/projects_controller.rb b/app/controllers/api/projects_controller.rb index 16ff795a..bca398d9 100644 --- a/app/controllers/api/projects_controller.rb +++ b/app/controllers/api/projects_controller.rb @@ -17,7 +17,7 @@ def show end def create - result = Project::Operation::Create.call(user_id: current_user) + result = Project::Operation::Create.call(params: project_params, user_id: current_user) if result.success? @project = result[:project] @@ -53,9 +53,8 @@ def load_projects end def project_params - params.require(:project) - .permit(:name, - components: %i[id name extension content index]) + params.permit(project: [:name, :type, :image_list, + { components: %i[id name extension content index default] }]).fetch(:project) end end end diff --git a/db/schema.rb b/db/schema.rb index bfbd2fb2..468f8e24 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,8 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema.define(version: 2022_03_11_121518) do - +ActiveRecord::Schema[7.0].define(version: 2022_03_11_121518) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -21,7 +20,7 @@ t.string "record_type", null: false t.uuid "record_id", null: false t.uuid "blob_id", null: false - t.datetime "created_at", precision: 6, null: false + t.datetime "created_at", null: false t.index ["blob_id"], name: "index_active_storage_attachments_on_blob_id" t.index ["record_type", "record_id", "name", "blob_id"], name: "index_active_storage_attachments_uniqueness", unique: true end @@ -34,7 +33,7 @@ t.string "service_name", null: false t.bigint "byte_size", null: false t.string "checksum" - t.datetime "created_at", precision: 6, null: false + t.datetime "created_at", null: false t.index ["key"], name: "index_active_storage_blobs_on_key", unique: true end @@ -49,8 +48,8 @@ t.string "name", null: false t.string "extension", null: false t.string "content" - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.integer "index" t.boolean "default", default: false, null: false t.index ["index", "project_id"], name: "index_components_on_index_and_project_id", unique: true @@ -62,8 +61,8 @@ t.string "name" t.string "identifier", null: false t.string "project_type", default: "python", null: false - t.datetime "created_at", precision: 6, null: false - t.datetime "updated_at", precision: 6, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false t.uuid "remixed_from_id" t.index ["identifier"], name: "index_projects_on_identifier", unique: true t.index ["remixed_from_id"], name: "index_projects_on_remixed_from_id" From 117bf58ebefec8038a3d00df63bdfd3308d0ddc9 Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Fri, 22 Jul 2022 11:17:32 +0000 Subject: [PATCH 3/6] Testing create operation and fixing failing tests --- app/concepts/project/operation/create.rb | 20 ++++-------- app/controllers/api/projects_controller.rb | 2 +- .../concepts/project/operation/create_spec.rb | 32 ++++++++++++++++++- 3 files changed, 38 insertions(+), 16 deletions(-) diff --git a/app/concepts/project/operation/create.rb b/app/concepts/project/operation/create.rb index e7ab8bbe..25d2600a 100644 --- a/app/concepts/project/operation/create.rb +++ b/app/concepts/project/operation/create.rb @@ -5,17 +5,17 @@ module Operation class Create require 'operation_response' - DEFAULT_COMPONENT = { 'name' => 'main', 'extension' => 'py', 'default' => true, 'index' => 0 }.freeze - DEFAULT_PROJECT = { 'type' => 'python', 'name' => 'Untitled project', 'components' => [DEFAULT_COMPONENT], - 'image_list' => [] }.freeze + DEFAULT_COMPONENT = { name: 'main', extension: 'py', default: true, index: 0 }.freeze + DEFAULT_PROJECT = { type: 'python', name: 'Untitled project', components: [DEFAULT_COMPONENT], + image_list: [] }.freeze class << self def call(user_id:, params:) response = OperationResponse.new - project = DEFAULT_PROJECT.merge(params) - new_project = Project.new(project_type: project['type'], user_id: user_id, name: project['name']) - new_project.components.build(project['components']) + project = DEFAULT_PROJECT.merge(params.deep_symbolize_keys) + new_project = Project.new(project_type: project[:type], user_id: user_id, name: project[:name]) + new_project.components.build(project[:components]) response[:project] = new_project response[:project].save! @@ -25,14 +25,6 @@ def call(user_id:, params:) response[:error] = 'Error creating project' response end - - private - - def create_with_content(project, user_id) - new_project = Project.new(project_type: project[:type], user_id: user_id, name: 'Untitled Project') - new_project.components.build(project[:components]) - new_project - end end end end diff --git a/app/controllers/api/projects_controller.rb b/app/controllers/api/projects_controller.rb index bca398d9..76799e48 100644 --- a/app/controllers/api/projects_controller.rb +++ b/app/controllers/api/projects_controller.rb @@ -54,7 +54,7 @@ def load_projects def project_params params.permit(project: [:name, :type, :image_list, - { components: %i[id name extension content index default] }]).fetch(:project) + { components: %i[id name extension content index default] }]).fetch(:project, {}) end end end diff --git a/spec/concepts/project/operation/create_spec.rb b/spec/concepts/project/operation/create_spec.rb index d6823c95..9f142272 100644 --- a/spec/concepts/project/operation/create_spec.rb +++ b/spec/concepts/project/operation/create_spec.rb @@ -3,9 +3,12 @@ require 'rails_helper' RSpec.describe Project::Operation::Create, type: :unit do - subject(:create_project) { described_class.call(user_id: user_id) } + subject(:create_project) { described_class.call(user_id: user_id, params: project_params) } let(:user_id) { 'e0675b6c-dc48-4cd6-8c04-0f7ac05af51a' } + let(:project_params) do + {} + end before do mock_phrase_generation @@ -37,6 +40,33 @@ expect(attrs).to eq(expected) end + context 'when initial project present' do + subject(:create_project_with_content) { described_class.call(user_id: user_id, params: project_params) } + let(:project_params) do + { + type: 'python', + components: [ + { + name: 'main', + extension: 'py', + content: 'print("hello world")', + index: 0, + default: true + } + ] + } + end + + it 'returns success' do + expect(create_project_with_content.success?).to eq(true) + end + + it 'returns project with correct component content', focus: true do + new_project = create_project_with_content[:project] + expect(new_project.components.first.content).to eq('print("hello world")') + end + end + context 'when creation fails' do before do mock_project = instance_double(Project) From 8cdc0324d52b1a9ce1ddab5a2956424107eab36e Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Fri, 22 Jul 2022 11:56:23 +0000 Subject: [PATCH 4/6] Fixing deep_symbolize_keys --- app/concepts/project/operation/create.rb | 6 +++++- spec/concepts/project/operation/create_spec.rb | 7 ++++--- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/concepts/project/operation/create.rb b/app/concepts/project/operation/create.rb index 25d2600a..846ce5f3 100644 --- a/app/concepts/project/operation/create.rb +++ b/app/concepts/project/operation/create.rb @@ -13,7 +13,11 @@ class << self def call(user_id:, params:) response = OperationResponse.new - project = DEFAULT_PROJECT.merge(params.deep_symbolize_keys) + project = DEFAULT_PROJECT.merge(params.deep_transform_keys do |key| + key.to_sym + rescue StandardError + key + end) new_project = Project.new(project_type: project[:type], user_id: user_id, name: project[:name]) new_project.components.build(project[:components]) diff --git a/spec/concepts/project/operation/create_spec.rb b/spec/concepts/project/operation/create_spec.rb index 9f142272..13fb17c5 100644 --- a/spec/concepts/project/operation/create_spec.rb +++ b/spec/concepts/project/operation/create_spec.rb @@ -6,7 +6,7 @@ subject(:create_project) { described_class.call(user_id: user_id, params: project_params) } let(:user_id) { 'e0675b6c-dc48-4cd6-8c04-0f7ac05af51a' } - let(:project_params) do + let(:project_params) do {} end @@ -42,7 +42,8 @@ context 'when initial project present' do subject(:create_project_with_content) { described_class.call(user_id: user_id, params: project_params) } - let(:project_params) do + + let(:project_params) do { type: 'python', components: [ @@ -61,7 +62,7 @@ expect(create_project_with_content.success?).to eq(true) end - it 'returns project with correct component content', focus: true do + it 'returns project with correct component content' do new_project = create_project_with_content[:project] expect(new_project.components.first.content).to eq('print("hello world")') end From e7f86705b73a769c064b4886d49b2a15e6189cc3 Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Fri, 22 Jul 2022 13:08:05 +0000 Subject: [PATCH 5/6] Tidying --- spec/concepts/project/operation/create_spec.rb | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/spec/concepts/project/operation/create_spec.rb b/spec/concepts/project/operation/create_spec.rb index 13fb17c5..afd19fa0 100644 --- a/spec/concepts/project/operation/create_spec.rb +++ b/spec/concepts/project/operation/create_spec.rb @@ -6,9 +6,7 @@ subject(:create_project) { described_class.call(user_id: user_id, params: project_params) } let(:user_id) { 'e0675b6c-dc48-4cd6-8c04-0f7ac05af51a' } - let(:project_params) do - {} - end + let(:project_params) { {} } before do mock_phrase_generation From 3a3b11dfb36479f3bdcc978fe3e84035202efcd9 Mon Sep 17 00:00:00 2001 From: Lois Wells Date: Mon, 1 Aug 2022 09:43:32 +0000 Subject: [PATCH 6/6] Removing weird whitespace --- app/concepts/project/operation/create.rb | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/app/concepts/project/operation/create.rb b/app/concepts/project/operation/create.rb index 846ce5f3..2fa9da92 100644 --- a/app/concepts/project/operation/create.rb +++ b/app/concepts/project/operation/create.rb @@ -13,11 +13,13 @@ class << self def call(user_id:, params:) response = OperationResponse.new - project = DEFAULT_PROJECT.merge(params.deep_transform_keys do |key| - key.to_sym - rescue StandardError - key - end) + project = DEFAULT_PROJECT.merge( + params.deep_transform_keys do |key| + key.to_sym + rescue StandardError + key + end + ) new_project = Project.new(project_type: project[:type], user_id: user_id, name: project[:name]) new_project.components.build(project[:components])