diff --git a/.gitignore b/.gitignore index 8080f7e6e..f3acc7ce2 100644 --- a/.gitignore +++ b/.gitignore @@ -33,3 +33,5 @@ /config/master.key .rubocop-https* + +/coverage diff --git a/app/concepts/project/operation/create_remix.rb b/app/concepts/project/operation/create_remix.rb index 7a146e348..cb617cec5 100644 --- a/app/concepts/project/operation/create_remix.rb +++ b/app/concepts/project/operation/create_remix.rb @@ -26,14 +26,19 @@ def validate_params(response, params, user_id) def remix_project(response, params, user_id) original_project = Project.find_by!(identifier: params[:phrase_id]) - response[:project] = original_project.dup.tap do |proj| - proj.user_id = user_id - proj.components = original_project.components.map(&:dup) - end + response[:project] = create_remix(original_project, user_id) response[:error] = 'Unable to create project' unless response[:project].save response end + + def create_remix(original_project, user_id) + original_project.dup.tap do |proj| + proj.user_id = user_id + proj.components = original_project.components.map(&:dup) + proj.remixed_from_id = original_project.id + end + end end end end diff --git a/app/models/project.rb b/app/models/project.rb index 23217a0eb..8830427c6 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -5,7 +5,9 @@ class Project < ApplicationRecord before_validation :check_unique_not_null, on: :create validates :identifier, presence: true, uniqueness: true + belongs_to :parent, class_name: 'Project', foreign_key: 'remixed_from_id', optional: true, inverse_of: :children has_many :components, -> { order(:index) }, dependent: :destroy, inverse_of: :project + has_many :children, class_name: 'Project', foreign_key: 'remixed_from_id', dependent: :nullify, inverse_of: :parent private diff --git a/app/views/api/projects/show.json.jbuilder b/app/views/api/projects/show.json.jbuilder index 8449e6128..e4462260b 100644 --- a/app/views/api/projects/show.json.jbuilder +++ b/app/views/api/projects/show.json.jbuilder @@ -2,4 +2,6 @@ json.call(@project, :identifier, :project_type, :name) +json.parent(@project.parent, :name, :identifier) if @project.parent + json.components @project.components, :id, :name, :extension, :content diff --git a/db/migrate/20220228094815_associate_remixed_projects_with_their_parent_project.rb b/db/migrate/20220228094815_associate_remixed_projects_with_their_parent_project.rb new file mode 100644 index 000000000..c7b5f6f78 --- /dev/null +++ b/db/migrate/20220228094815_associate_remixed_projects_with_their_parent_project.rb @@ -0,0 +1,5 @@ +class AssociateRemixedProjectsWithTheirParentProject < ActiveRecord::Migration[7.0] + def change + add_reference :projects, :remixed_from, type: :uuid, references: :projects + end +end diff --git a/db/schema.rb b/db/schema.rb index ec9163cf7..7ebc5b8a1 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: 2022_02_11_102958) do +ActiveRecord::Schema.define(version: 2022_02_28_094815) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" @@ -34,7 +34,9 @@ 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.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" end create_table "words", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 07d217bb6..ab890d4d1 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -5,6 +5,8 @@ RSpec.describe Project, type: :model do describe 'associations' do it { is_expected.to have_many(:components) } + it { is_expected.to have_many(:children) } + it { is_expected.to belong_to(:parent).optional(true) } end describe 'identifier not nil' do