diff --git a/examples/blog/db/migrate/20260907000009_add_index_on_posts_user_id.rb b/examples/blog/db/migrate/20260907000009_add_index_on_posts_user_id.rb new file mode 100644 index 0000000..ed83888 --- /dev/null +++ b/examples/blog/db/migrate/20260907000009_add_index_on_posts_user_id.rb @@ -0,0 +1,9 @@ +class AddIndexOnPostsUserId < Prism::Orm::Migration + def up + add_index :posts, :user_id + end + + def down + remove_index :posts, :user_id + end +end diff --git a/examples/blog/db/migrate/20260907000010_add_slug_to_posts.rb b/examples/blog/db/migrate/20260907000010_add_slug_to_posts.rb new file mode 100644 index 0000000..4e3c968 --- /dev/null +++ b/examples/blog/db/migrate/20260907000010_add_slug_to_posts.rb @@ -0,0 +1,41 @@ +class AddSlugToPosts < Prism::Orm::Migration + def up + # add_column's own default ('') would leave every existing row with the + # SAME empty slug, which the unique index below would reject the moment + # a second existing post tried to keep it - so every existing row gets + # a real, distinct slug backfilled BEFORE the index goes on, the same + # slugify Post.create_with_unique_slug uses for new rows (this runs at + # the store level, not through the Post model - db:migrate does not + # load app/models, see Prism::Cli#db_migrate). + add_column :posts, :slug, default: '' + backfill_unique_slugs + add_index :posts, :slug, unique: true + end + + def down + remove_index :posts, :slug + remove_column :posts, :slug + end + + private + + def backfill_unique_slugs + seen = {} + store.all(:posts).each do |row| + base = slugify(row['title']) + slug = base + suffix = 1 + while seen.key?(slug) + suffix += 1 + slug = "#{base}-#{suffix}" + end + seen[slug] = true + store.update(:posts, row['id'], 'slug' => slug) + end + end + + def slugify(title) + base = title.to_s.downcase.gsub(/[^a-z0-9]+/, '-').gsub(/\A-+|-+\z/, '') + base.empty? ? 'post' : base + end +end diff --git a/examples/blog/db/migrate/20260907000011_add_featured_to_posts.rb b/examples/blog/db/migrate/20260907000011_add_featured_to_posts.rb new file mode 100644 index 0000000..8afb128 --- /dev/null +++ b/examples/blog/db/migrate/20260907000011_add_featured_to_posts.rb @@ -0,0 +1,9 @@ +class AddFeaturedToPosts < Prism::Orm::Migration + def up + add_column :posts, :featured, default: false + end + + def down + remove_column :posts, :featured + end +end diff --git a/examples/blog/db/migrate/20260907000012_add_confirmed_at_to_users.rb b/examples/blog/db/migrate/20260907000012_add_confirmed_at_to_users.rb new file mode 100644 index 0000000..1fda9c4 --- /dev/null +++ b/examples/blog/db/migrate/20260907000012_add_confirmed_at_to_users.rb @@ -0,0 +1,9 @@ +class AddConfirmedAtToUsers < Prism::Orm::Migration + def up + add_column :users, :confirmed_at, :datetime, default: nil + end + + def down + remove_column :users, :confirmed_at + end +end diff --git a/examples/blog/db/migrate/20260907000013_add_position_to_posts.rb b/examples/blog/db/migrate/20260907000013_add_position_to_posts.rb new file mode 100644 index 0000000..c5b0078 --- /dev/null +++ b/examples/blog/db/migrate/20260907000013_add_position_to_posts.rb @@ -0,0 +1,9 @@ +class AddPositionToPosts < Prism::Orm::Migration + def up + add_column :posts, :position + end + + def down + remove_column :posts, :position + end +end diff --git a/examples/blog/db/migrate/20260908000001_add_composite_index_on_posts_featured_and_position.rb b/examples/blog/db/migrate/20260908000001_add_composite_index_on_posts_featured_and_position.rb new file mode 100644 index 0000000..96697b3 --- /dev/null +++ b/examples/blog/db/migrate/20260908000001_add_composite_index_on_posts_featured_and_position.rb @@ -0,0 +1,9 @@ +class AddCompositeIndexOnPostsFeaturedAndPosition < Prism::Orm::Migration + def up + add_index :posts, %i[featured position] + end + + def down + remove_index :posts, %i[featured position] + end +end diff --git a/examples/blog/db/migrate/20260908000002_add_giveaway_slots_to_posts.rb b/examples/blog/db/migrate/20260908000002_add_giveaway_slots_to_posts.rb new file mode 100644 index 0000000..abfc8b9 --- /dev/null +++ b/examples/blog/db/migrate/20260908000002_add_giveaway_slots_to_posts.rb @@ -0,0 +1,13 @@ +class AddGiveawaySlotsToPosts < Prism::Orm::Migration + def up + # No default (nil) on purpose - nil means "not a giveaway post" (see + # Post#giveaway?), distinct from 0 ("was a giveaway, now sold out + # forever"). A post created before this migration, or one nobody ever + # opted into the giveaway field for, reads back as nil either way. + add_column :posts, :giveaway_slots, :integer + end + + def down + remove_column :posts, :giveaway_slots + end +end diff --git a/examples/blog/db/migrate/20260908000003_create_claims.rb b/examples/blog/db/migrate/20260908000003_create_claims.rb new file mode 100644 index 0000000..ce5baf3 --- /dev/null +++ b/examples/blog/db/migrate/20260908000003_create_claims.rb @@ -0,0 +1,22 @@ +class CreateClaims < Prism::Orm::Migration + def up + create_table :claims do |t| + t.integer :post_id + t.integer :user_id + t.datetime :deleted_at + t.timestamps + end + # Belt and braces with Claim's own `validates :user_id, uniqueness: + # { scope: :post_id }`: the model-level check only ever sees rows this + # same process/transaction can already read, whereas this unique index + # is enforced by Store#validate_unique_indexes inside the very same + # transaction the insert itself runs in (see Store#insert), so it + # still catches a duplicate claim even in the hypothetical case of two + # inserts racing without going through Post#with_lock first. + add_index :claims, %i[post_id user_id], unique: true + end + + def down + drop_table :claims + end +end diff --git a/examples/blog/db/migrate/20260908000004_add_claims_count_to_posts.rb b/examples/blog/db/migrate/20260908000004_add_claims_count_to_posts.rb new file mode 100644 index 0000000..d216a69 --- /dev/null +++ b/examples/blog/db/migrate/20260908000004_add_claims_count_to_posts.rb @@ -0,0 +1,9 @@ +class AddClaimsCountToPosts < Prism::Orm::Migration + def up + add_column :posts, :claims_count, :integer, default: 0 + end + + def down + remove_column :posts, :claims_count + end +end