Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Migrates from ranked-model to positioning gem #2430

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/models/blueprint.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ def set_rooms

def add_furniture(room, room_attributes)
furnitures = room_attributes.fetch(:furnitures, {})
furnitures.each.with_index do |(furniture_kind, settings), slot|
furnitures.each.with_index do |(furniture_kind, settings), position|
furniture = room.gizmos
.find_or_initialize_by(slot: slot)
.find_or_initialize_by(position: position)
furniture
.update!(settings: merge_non_empty(settings, furniture.settings),
furniture_kind: furniture_kind)
Expand Down
8 changes: 3 additions & 5 deletions app/models/furniture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,9 @@
# as JSON, so that {Furniture} can be tweaked and configured as appropriate for
# it's particular use case.
class Furniture < ApplicationRecord
include RankedModel
location(parent: :room)

ranks :slot, with_same: [:room_id]
positioned on: :room

belongs_to :room, inverse_of: :gizmos
has_one :space, through: :room, inverse_of: :gizmos
Expand All @@ -17,9 +16,6 @@ class Furniture < ApplicationRecord

attribute :settings, :json, default: -> { {} }

# The order in which {Furniture} is rendered in a Room. Lower is higher.
attribute :slot, :integer

delegate :attributes=, to: :gizmo, prefix: true

validates :furniture_kind, presence: true
Expand All @@ -28,6 +24,8 @@ class Furniture < ApplicationRecord
# for a Marketplace
has_encrypted :secrets, type: :json

scope :by_position, -> { order(position: :asc) }

# Setting `secrets` to an empty hash after initialization will force consistent access for developers, rather than having to code around a potential nil value
after_initialize do
# The `RankedModel` gem uses
Expand Down
2 changes: 1 addition & 1 deletion app/policies/furniture_policy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def update?
alias_method :destroy?, :update?

def permitted_attributes(_params)
[:furniture_kind, :slot, gizmo_attributes: furniture_params]
[:furniture_kind, :position, gizmo_attributes: furniture_params]
end

def furniture_params
Expand Down
1 change: 0 additions & 1 deletion app/views/furnitures/_new.html.erb
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
<div id="new_furniture">
<h3><%= t('rooms.place_furniture_heading') %></h3>
<%= form_with model: furniture.location do | form | %>
<%= form.hidden_field :slot, value: furniture.room.gizmos.count %>
<%= render SelectComponent.new({
choices: Furniture.registry.keys.map { |k| [k.to_s.titleize, k] },
attribute: :furniture_kind,
Expand Down
3 changes: 1 addition & 2 deletions app/views/rooms/_room.html.erb
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
<%- if room.hero_image&.upload.present? %>
<%= image_tag room.hero_image&.upload&.variant(resize_to_fill: Media::FULL_WIDTH_SHORT), class: "w-full" %>
<%- end %>

<div class="grow mx-auto w-full">
<section id="furnitures">
<%= render room.gizmos.rank(:slot) %>
<%= render room.gizmos.by_position %>
</section>
</div>
2 changes: 1 addition & 1 deletion app/views/rooms/edit.html.erb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<h2>Gizmos</h2>
<div id="furnitures">
<% if room.gizmos.present? %>
<%= render room.gizmos.rank(:slot), editing: true %>
<%= render room.gizmos.by_position, editing: true %>
<% else %>
<p class="text-gray-500"><%= t('rooms.no_furniture_notice') %></p>
<% end %>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
class RenamingFurnitureSlotToPosition < ActiveRecord::Migration[7.1]
def change
safety_assured do
rename_column :furnitures, :slot, :position
change_column_default :furnitures, :position, from: nil, to: 0
change_column_null :furnitures, :position, false
end
end
end
7 changes: 7 additions & 0 deletions db/migrate/20240530010707_add_position_index_to_furnitures.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
class AddPositionIndexToFurnitures < ActiveRecord::Migration[7.1]
disable_ddl_transaction!

def change
add_index :furnitures, [:room_id, :position], unique: true, algorithm: :concurrently
end
end
5 changes: 3 additions & 2 deletions db/schema.rb
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.

ActiveRecord::Schema[7.1].define(version: 2024_05_24_021224) do
ActiveRecord::Schema[7.1].define(version: 2024_05_30_010707) do
# These are extensions that must be enabled in order to support this database
enable_extension "pgcrypto"
enable_extension "plpgsql"
Expand Down Expand Up @@ -94,13 +94,14 @@
end

create_table "furnitures", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
t.integer "slot"
t.integer "position", default: 0, null: false
t.string "furniture_kind"
t.jsonb "settings"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.uuid "room_id"
t.text "secrets_ciphertext"
t.index ["room_id", "position"], name: "index_furnitures_on_room_id_and_position", unique: true
t.index ["room_id"], name: "index_furnitures_on_room_id"
end

Expand Down
1 change: 0 additions & 1 deletion spec/factories/furniture.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,5 @@
room
furniture_kind { "markdown_text_block" }
settings { {content: "# Original Content"} }
slot_position { :last }
end
end
1 change: 0 additions & 1 deletion spec/factories/furniture/markdown_text_block.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
room
furniture_kind { "markdown_text_block" }
settings { {content: content} }
slot_position { :last }
end
end
30 changes: 0 additions & 30 deletions spec/models/furniture_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,36 +13,6 @@
end
end

describe "#slot" do
let(:room) { create(:room) }
let(:placements) { create_list(:furniture, 3, room: room) }
# rubocop:disable RSpec/IndexedLet
let(:placement1) { placements[0] }
let(:placement2) { placements[1] }
let(:placement3) { placements[2] }
# rubocop:enable RSpec/IndexedLet

before {
placement1
placement2
placement3
}

it "inserts new placement between existing slots" do
new_placement = create(:furniture, room: room, slot_position: 1)
expect(placement1.slot_rank).to eq(0)
expect(new_placement.slot_rank).to eq(1)
expect(placement2.slot_rank).to eq(2)
expect(placement3.slot_rank).to eq(3)
end

it "gets placed last without an explicit position" do
new_placement = create(:furniture, room: room, slot_position: nil)
expect(new_placement).to be_valid
expect(new_placement.slot_position).to eq(3)
end
end

describe "#setting" do
class TestFurniture < described_class # rubocop:disable Lint/ConstantDefinitionInBlock, RSpec/LeakyConstantDeclaration
setting :name, default: "some default value"
Expand Down
1 change: 0 additions & 1 deletion spec/requests/furnitures_controller_request_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@
perform_request
placement = room.gizmos.last
expect(placement.furniture).to be_a(MarkdownTextBlock)
expect(placement.slot).to be(0)
expect(response).to redirect_to([space, room])
end
end
Expand Down