diff --git a/app/models/bubble.rb b/app/models/bubble.rb index 2a2d2c214..c4a0d780f 100644 --- a/app/models/bubble.rb +++ b/app/models/bubble.rb @@ -1,5 +1,5 @@ class Bubble < ApplicationRecord - include Assignable, Colored, Searchable, Taggable + include Assignable, Colored, Poppable, Searchable, Taggable belongs_to :bucket belongs_to :creator, class_name: "User", default: -> { Current.user } diff --git a/app/models/bubble/poppable.rb b/app/models/bubble/poppable.rb new file mode 100644 index 000000000..30e6cde65 --- /dev/null +++ b/app/models/bubble/poppable.rb @@ -0,0 +1,22 @@ +module Bubble::Poppable + extend ActiveSupport::Concern + + included do + has_one :pop, dependent: :destroy + + scope :popped, -> { joins(:pop) } + scope :not_popped, -> { where.missing(:pop) } + end + + def popped? + pop.present? + end + + def pop!(user: Current.user) + create_pop!(user: user) unless popped? + end + + def unpop + pop&.destroy + end +end diff --git a/app/models/pop.rb b/app/models/pop.rb new file mode 100644 index 000000000..059336c67 --- /dev/null +++ b/app/models/pop.rb @@ -0,0 +1,4 @@ +class Pop < ApplicationRecord + belongs_to :bubble + belongs_to :user, optional: true +end diff --git a/app/models/user.rb b/app/models/user.rb index 643f0f7c5..140959d8e 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -7,6 +7,7 @@ class User < ApplicationRecord has_many :accesses, dependent: :destroy has_many :buckets, through: :accesses has_many :bubbles, through: :buckets + has_many :pops, dependent: :nullify has_many :assignments, foreign_key: :assignee_id, dependent: :destroy has_many :assignings, foreign_key: :assigner_id, class_name: "Assignment" diff --git a/db/migrate/20241002125904_create_pops.rb b/db/migrate/20241002125904_create_pops.rb new file mode 100644 index 000000000..6424fcf1f --- /dev/null +++ b/db/migrate/20241002125904_create_pops.rb @@ -0,0 +1,10 @@ +class CreatePops < ActiveRecord::Migration[8.0] + def change + create_table :pops do |t| + t.references :bubble, null: false, foreign_key: true, index: { unique: true } + t.references :user, null: true, foreign_key: true + + t.timestamps + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 0a6fc6d23..4724af881 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -105,6 +105,15 @@ ActiveRecord::Schema[8.0].define(version: 2024_10_02_163242) do t.datetime "updated_at", null: false end + create_table "pops", force: :cascade do |t| + t.integer "bubble_id", null: false + t.integer "user_id" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["bubble_id"], name: "index_pops_on_bubble_id", unique: true + t.index ["user_id"], name: "index_pops_on_user_id" + end + create_table "sessions", force: :cascade do |t| t.integer "user_id", null: false t.string "ip_address" @@ -145,6 +154,8 @@ ActiveRecord::Schema[8.0].define(version: 2024_10_02_163242) do add_foreign_key "active_storage_attachments", "active_storage_blobs", column: "blob_id" add_foreign_key "active_storage_variant_records", "active_storage_blobs", column: "blob_id" + add_foreign_key "pops", "bubbles" + add_foreign_key "pops", "users" add_foreign_key "sessions", "users" add_foreign_key "taggings", "bubbles" add_foreign_key "taggings", "tags" diff --git a/test/fixtures/bubbles.yml b/test/fixtures/bubbles.yml index 327dc367a..23ad32219 100644 --- a/test/fixtures/bubbles.yml +++ b/test/fixtures/bubbles.yml @@ -16,3 +16,9 @@ text: creator: kevin title: The text is too small color: "#3B4B59" + +shipping: + bucket: writebook + creator: kevin + title: We need to ship the app + color: "#ED8008" diff --git a/test/fixtures/pops.yml b/test/fixtures/pops.yml new file mode 100644 index 000000000..cbb58be3f --- /dev/null +++ b/test/fixtures/pops.yml @@ -0,0 +1,3 @@ +shipping: + bubble: shipping + user: kevin diff --git a/test/models/bubble/poppable_test.rb b/test/models/bubble/poppable_test.rb new file mode 100644 index 000000000..a452d594e --- /dev/null +++ b/test/models/bubble/poppable_test.rb @@ -0,0 +1,16 @@ +require "test_helper" + +class Bubble::PoppableTest < ActiveSupport::TestCase + test "popped scope" do + assert_equal [ bubbles(:shipping) ], Bubble.popped + assert_not_includes Bubble.not_popped, bubbles(:shipping) + end + + test "popping" do + assert_not bubbles(:logo).popped? + + bubbles(:logo).pop! + + assert bubbles(:logo).popped? + end +end diff --git a/test/models/pop_test.rb b/test/models/pop_test.rb new file mode 100644 index 000000000..608906ef2 --- /dev/null +++ b/test/models/pop_test.rb @@ -0,0 +1,7 @@ +require "test_helper" + +class PopTest < ActiveSupport::TestCase + # test "the truth" do + # assert true + # end +end