Note that there are some explanatory texts on larger screens.

plurals
  1. POHow to use MultiPiece
    primarykey
    data
    text
    <p>I'm completely new to Yesod (and not very experienced in haskell) and I'm trying to build my first handler. I scraffolded my app using default parameters (I'm using Yesod 0.9.4.1 version and choose postgresql in scraffolding) and now I'm trying to retrieve some data from a table using selectList. I defined a new table (let's call it Foo) in models config file:</p> <pre><code> Foo xStart Int yStart Int </code></pre> <p>and want to pass a list of FooId's and some other Foo attributes so I defined a route: </p> <p><code>/foos/#Int/#Int/*FooId FoosReturnR GET</code></p> <p>and a handler:</p> <pre><code> module Handler.FoosReturn where import Import selectWindowSize :: Int selectWindowSize = 10000 getFoosReturnR :: Int -&gt; Int -&gt; [FooId] -&gt; Handler RepPlain getFoosReturnR x y withoutIds = do foos &lt;- runDB $ selectList [FooId /&lt;-. withoutIds, FooXStart &lt;. x + selectWindowSize, FooXStart &gt;=. x - selectWindowSize, FooYStart &lt;. y + selectWindowSize, FooYStart &gt;=. y - selectWindowSize] [] return $ RepPlain $ toContent $ show foos </code></pre> <p>I imported the handler in Application.hs and added it to cabal file and now when I'm trying to run it I receive an error saying that FooId is not an instance of MultiPiece - but when I try to make it an instance there is an error saying that FooId is a type synonym and cannot be an instance of MultiPiece - how to resolve this problem?</p> <hr> <p>EDIT: Daniel: well, actually I don't know what exactly is FooId - it's a part of Yesod's magic which I don't fully understand so far - it's generated automatically from the table definition - but it's a some kind of a number.</p> <p>Because I don't know how to use MultiPiece I switched to simpler solution and modified:</p> <p>route: <code>/foos/#Int/#Int/#String FoosReturnR GET</code></p> <p>handler: [added also some logging]</p> <pre><code> module Handler.FoosReturn where import Import import Data.List.Split import qualified Data.Text.Lazy as TL selectWindowSize :: Int selectWindowSize = 10000 getFoosReturnR :: Int -&gt; Int -&gt; String -&gt; Handler RepPlain getFoosReturnR x y withoutIds = do app &lt;- getYesod liftIO $ logLazyText (getLogger app) ("getFoosReturnR('" `TL.append` (TL.pack $ (show x) ++ "', '" ++ (show y) ++ "', '" ++ withoutIds ++ "') ")) foos &lt;- runDB $ selectList [FooId /&lt;-. (map (\a -&gt; read a :: FooId) $ splitOn "," withoutIds), FooXStart &lt;. x + selectWindowSize, FooXStart &gt;=. x - selectWindowSize, FooYStart &lt;. y + selectWindowSize, FooYStart &gt;=. y - selectWindowSize] [] return $ RepPlain $ toContent $ show foos </code></pre> <p>and now it is compiling but when I browse to: <a href="http://localhost:3000/sectors/1/1/1,2" rel="nofollow">http://localhost:3000/sectors/1/1/1,2</a> I get a page containing only: Internal Server Error Prelude.read: no parse</p> <p>Well, I don't fully understand what is FooId here - how to create such a list of FooId's from list of strings containing numbers?</p> <p>And of course a solution of how to make the FooId an instance of MultiPiece is most wanted.</p> <hr> <p>EDIT: </p> <p>Daniel and svachalek, thanks for your posts - I tried your (Daniel's) solution but then I was receiving errors saying that [FooId] is expected (as in the handler function declaration) but FooId type was given and this lead me to the following solution:</p> <pre><code> 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) &gt; 0 then Nothing else Just $ FooIds $ map fromJust listOfMaybeFooId where listOfMaybeFooId = map constructMaybeFooId texts constructMaybeFooId :: Text -&gt; Maybe FooId constructMaybeFooId x = case reads (Data.Text.unpack x) :: [(FooId,String)] of [(foo,_)] -&gt; Just foo _ -&gt; Nothing </code></pre> <p>of course I changed the route to: <code>/foos/#Int/#Int/*FooIds FoosReturnR GET</code></p> <p>and the handler to: </p> <pre><code> getFoosReturnR :: Int -&gt; Int -&gt; FooIds -&gt; Handler RepPlain getFoosReturnR coordX coordY (FooIds withoutIds) = do </code></pre> <p>and now I don't get any errors during compilation nor runtime, and the only not satisfying thing is that I always receive Not Found as a result, even if I supply parameters that should give me some results - so now I have to figure out how to determine what SQL was exactly sent to the database</p> <hr> <p>EDIT:</p> <p>Now I see that the "Not Found" is connected to the problem and that the above edit is not a solution - when I browse to localhost:3000/foos/4930000/3360000 then I get the results (but then the FooIds is empty) - but when I add something like: localhost:3000/sectors/4930000/3360000/1 then I always get "Not Found" - so it's still not working..</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload