我需要訂購頁面(由用戶定義,拖放),例如("Hello", order 1), ("Bye", order 2)然后插入,比如說("Good", order 1),所以集合將更改為("Good", order 1), ("Hello", order 2), ("Bye", order 3). 任何想法如何通過 IHP/Postgres 實作這一目標?
我看過
https://begriffs.com/posts/2018-03-20-user-defined-order.html
這些是我們迄今為止最好的解決方案嗎?
uj5u.com熱心網友回復:
我通常使用整數position列方法。以下是來自真實世界 IHP 應用程式的示例代碼:
在這種情況下,我們有offers一個帶有position整數列的列,如下所示:
CREATE TABLE offers (
id UUID DEFAULT uuid_generate_v4() PRIMARY KEY NOT NULL,
created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW() NOT NULL,
name TEXT NOT NULL,
"location" TEXT NOT NULL,
contact TEXT NOT NULL,
description TEXT NOT NULL,
"position" INT NOT NULL
);
控制器如下所示:
module Web.Controller.Offers where
import Web.Controller.Prelude
import Web.View.Offers.Edit
import Web.View.Offers.Show
import Web.View.Offers.New
import Web.View.Offers.Index
import qualified Application.Offer as Offer
import qualified Control.Monad.State.Lazy as State
instance Controller OffersController where
beforeAction = ensureIsUser
action NewOfferAction = do
let backField :: Offer = newRecord
render NewView { .. }
action OffersAction = do
backFields <- query @Offer |> orderBy #position |> fetch
render IndexView { .. }
action ShowOfferAction { .. } = do
backField <- fetch backFieldId
render ShowView { .. }
action EditOfferAction { .. } = do
backField <- fetch backFieldId
render EditView { .. }
action UpdateOfferAction { .. } = do
backField <- fetch backFieldId
backField
|> buildOffer
|> ifValid \case
Left backField -> render EditView { .. }
Right backField -> do
backField <- updateRecord backField
setSuccessMessage "Offer updated"
redirectTo EditOfferAction { .. }
action CreateOfferAction = do
nextPosition <- Offer.nextPosition
newRecord @Offer
|> buildOffer
|> ifValid \case
Left backField -> render NewView { .. }
Right backField -> do
backField <- backField
|> createRecord
setSuccessMessage "Angebot erstellt"
redirectTo OffersAction
action DeleteOfferAction { .. } = do
backField <- fetch backFieldId
deleteRecord backField
setSuccessMessage "Deleted Offer successfully"
redirectTo OffersAction
action OfferMoveUpAction { .. } = do
backField <- fetch backFieldId
prevOffer <- backField |> Offer.prevOffer
case prevOffer of
Just prevOffer -> do
let backFieldPosition = get #position backField
let prevOfferPosition = get #position prevOffer
updateRecord (backField |> set #position prevOfferPosition)
updateRecord (prevOffer |> set #position backFieldPosition)
return ()
Nothing -> return ()
redirectTo OffersAction
action OfferMoveDownAction { .. } = do
backField <- fetch backFieldId
nextOffer <- backField |> Offer.nextOffer
case nextOffer of
Just nextOffer -> do
let backFieldPosition = get #position backField
let nextOfferPosition = get #position nextOffer
updateRecord (backField |> set #position nextOfferPosition)
updateRecord (nextOffer |> set #position backFieldPosition)
return ()
Nothing -> return ()
redirectTo OffersAction
buildOffer :: _ => backField -> backField
buildOffer backField =
backField
|> fill @'["name", "description", "position", "location", "contact"]
|> validateField #name nonEmpty
控制器使用的一些輔助函式是在另一個模塊中定義的(但如果需要,您可以將它們放入控制器中):
module Application.Offer (nextPosition, prevOffer, nextOffer) where
import IHP.Prelude
import IHP.ModelSupport
import IHP.QueryBuilder
import Generated.Types
import qualified Database.PostgreSQL.Simple as PG
instance DefaultScope "offers" where
defaultScope = orderBy #position
nextPosition :: (?modelContext :: ModelContext) => IO Int
nextPosition = sqlQueryScalar "SELECT COUNT(*) FROM offers" ()
prevOffer :: (?modelContext :: ModelContext) => Offer -> IO (Maybe Offer)
prevOffer offer = do
results <- sqlQuery "SELECT * FROM offers WHERE position < ? ORDER BY position DESC LIMIT 1" (PG.Only (get #position offer))
return $ headMay results
nextOffer :: (?modelContext :: ModelContext) => Offer -> IO (Maybe Offer)
nextOffer offer = do
results <- sqlQuery "SELECT * FROM offers WHERE position > ? ORDER BY position ASC LIMIT 1" (PG.Only (get #position offer))
return $ headMay results
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/406348.html
標籤:
