IHP如何实现自定义订单?
How to achieve a user-defined order with IHP?
我需要对页面进行排序(由用户定义,拖放),例如 ("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
这些是我们迄今为止最好的解决方案吗?
我通常使用整数 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
我需要对页面进行排序(由用户定义,拖放),例如 ("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
这些是我们迄今为止最好的解决方案吗?
我通常使用整数 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