私はYesodに完全に慣れていません(そしてhaskellの経験はあまりありません)。そして、最初のハンドラーを構築しようとしています。デフォルトのパラメーターを使用してアプリをスクラフフォールドし(Yesod 0.9.4.1バージョンを使用しており、スクラフフォールディングでpostgresqlを選択しています)、selectListを使用してテーブルからデータを取得しようとしています。モデル構成ファイルで新しいテーブル(Fooと呼びましょう)を定義しました。
Foo
xStart Int
yStart Int
FooIdと他のいくつかのFoo属性のリストを渡したいので、ルートを定義しました。
/foos/#Int/#Int/*FooId FoosReturnR GET
およびハンドラー:
module Handler.FoosReturn where
import Import
selectWindowSize :: Int
selectWindowSize = 10000
getFoosReturnR :: Int -> Int -> [FooId] -> Handler RepPlain
getFoosReturnR x y withoutIds = do
foos <- runDB $ selectList [FooId /<-. withoutIds,
FooXStart <. x + selectWindowSize,
FooXStart >=. x - selectWindowSize,
FooYStart <. y + selectWindowSize,
FooYStart >=. y - selectWindowSize] []
return $ RepPlain $ toContent $ show foos
Application.hsにハンドラーをインポートし、それをcabalファイルに追加しました。これを実行しようとすると、FooIdはMultiPieceのインスタンスではないというエラーが表示されますが、インスタンスにしようとすると、 FooIdは型の同義語であり、MultiPieceのインスタンスにはできないというエラー-この問題を解決するにはどうすればよいですか?
編集:ダニエル:ええと、実際にはFooIdが正確に何であるかはわかりません-これは、これまで完全には理解していないYesodの魔法の一部です-テーブル定義から自動的に生成されます-しかし、それはある種の数値です。
MultiPieceの使用方法がわからないため、より単純なソリューションに切り替えて変更しました。
ルート:/foos/#Int/#Int/#String FoosReturnR GET
ハンドラー:[ログも追加]
module Handler.FoosReturn where
import Import
import Data.List.Split
import qualified Data.Text.Lazy as TL
selectWindowSize :: Int
selectWindowSize = 10000
getFoosReturnR :: Int -> Int -> String -> Handler RepPlain
getFoosReturnR x y withoutIds = do
app <- getYesod
liftIO $ logLazyText (getLogger app) ("getFoosReturnR('" `TL.append` (TL.pack $ (show x) ++ "', '" ++ (show y) ++ "', '" ++ withoutIds ++ "') "))
foos <- runDB $ selectList [FooId /<-. (map (\a -> read a :: FooId) $ splitOn "," withoutIds),
FooXStart <. x + selectWindowSize,
FooXStart >=. x - selectWindowSize,
FooYStart <. y + selectWindowSize,
FooYStart >=. y - selectWindowSize] []
return $ RepPlain $ toContent $ show foos
コンパイル中ですが、http:// localhost:3000 /ectors / 1/1 / 1,2を参照すると、次のページのみが表示されます。内部サーバーエラーPrelude.read:解析なし
さて、私はここでFooIdが何であるかを完全には理解していません-数字を含む文字列のリストからFooIdのそのようなリストを作成する方法は?
そしてもちろん、FooIdをMultiPieceのインスタンスにする方法の解決策が最も望まれています。
編集:
ダニエルとsvachalek、あなたの投稿に感謝します-私はあなたの(ダニエルの)解決策を試しましたが、[FooId]が期待されているというエラーを受け取りました(ハンドラー関数宣言のように)が、FooIdタイプが与えられ、これは私を次の解決策に導きます:
data FooIds = FooIds [FooId] deriving (Show, Read, Eq)
instance MultiPiece FooIds where
toMultiPiece (FooIds fooList) = map (Data.Text.pack . show) fooList
fromMultiPiece texts =
if length (filter isNothing listOfMaybeFooId) > 0
then Nothing
else Just $ FooIds $ map fromJust listOfMaybeFooId
where
listOfMaybeFooId = map constructMaybeFooId texts
constructMaybeFooId :: Text -> Maybe FooId
constructMaybeFooId x = case reads (Data.Text.unpack x) :: [(FooId,String)] of
[(foo,_)] -> Just foo
_ -> Nothing
もちろん、ルートを次のように変更しました。/foos/#Int/#Int/*FooIds FoosReturnR GET
およびハンドラー:
getFoosReturnR :: Int -> Int -> FooIds -> Handler RepPlain
getFoosReturnR coordX coordY (FooIds withoutIds) = do
そして今、コンパイル中や実行時にエラーが発生することはありません。唯一の満足のいくものではないのは、結果が得られるはずのパラメーターを指定しても、結果として常にNotFoundを受け取ることです。どのSQLがデータベースに正確に送信されたかを判別する方法
編集:
これで、「見つかりません」が問題に関連していることがわかり、上記の編集は解決策ではありません-localhost:3000 / foos / 4930000/3360000を参照すると、結果が得られます(ただし、FooIdsは空です) -しかし、localhost:3000 /ectors / 4930000/3360000/1のようなものを追加すると、常に「見つかりません」と表示されます-したがって、まだ機能していません。