2017-06-23 18 views
2

以下のコードでは、静的フォルダに画像があります:bsd.jpg。 ajaxの成功方法では、img srcを静止画像に向けて表示したいと思います。私はこのコードを実行する理由を把握し、エラーを取得できませんでした:あなたはYesod静的ファイルタイプセーフルート変数がスコープにありません

import Yesod.Static (staticFiles) 

-- This generates easy references to files in the static directory at compile time, 
-- giving you compile-time verification that referenced files exist. 
-- Warning: any files added to your static directory during run-time can't be 
-- accessed this way. You'll have to use their FilePath or URL to access them. 
-- 
-- For example, to refer to @static/js/[email protected] via an identifier, you'd use: 
-- 
--  js_script_js 
-- 
-- If the identifier is not available, you may use: 
-- 
--  StaticFile ["js", "script.js"] [] 

staticFiles (appStaticDir compileTimeAppSettings) 

を行う場所

upload.hs:91:22: error: Variable not in scope: bsd_jpg :: Route Static 

#!/usr/bin/env stack 
{- stack 
    --resolver lts-8.19 
    --install-ghc 
    runghc 
    --package yesod 
    --package yesod-static 
    --package persistent-sqlite 
-} 

{-# LANGUAGE OverloadedStrings #-} 
{-# LANGUAGE TemplateHaskell #-} 
{-# LANGUAGE QuasiQuotes #-} 
{-# LANGUAGE TypeFamilies #-} 
{-# LANGUAGE MultiParamTypeClasses #-} 
{-# LANGUAGE FlexibleContexts #-} 
{-# LANGUAGE GADTs #-} 
{-# LANGUAGE GeneralizedNewtypeDeriving #-} 
{-# LANGUAGE ViewPatterns #-} 

import Yesod 
import Yesod.Static 
import Data.Time (UTCTime) 
import System.FilePath 
import System.Directory (removeFile, doesFileExist, createDirectoryIfMissing) 
import Control.Applicative ((<$>), (<*>)) 
import Control.Monad.Logger (runStdoutLoggingT) 
import Data.Conduit 
import qualified Data.Text as T 
import Data.Text (unpack) 
import qualified Data.ByteString.Lazy as DBL 
import Data.Conduit.List (consume) 
import Database.Persist 
import Database.Persist.Sqlite 
import Data.Time (getCurrentTime) 
import qualified Data.Conduit.Text as CT 
import qualified Data.Conduit.List as CL 

share [mkPersist sqlSettings,mkMigrate "migrateAll"] [persistUpperCase| 
Image 
    filename String 
    description Textarea Maybe 
    date UTCTime 
    deriving Show 
|] 

data App = App 
    { getStatic :: Static --^Settings for static file serving. 
    , connPool :: ConnectionPool 
    } 

mkYesod "App" [parseRoutes| 
/ImagesR GET POST 
/image/#ImageId ImageR DELETE 
/static StaticR Static getStatic 
/echo-body EchoBodyR PUT 
|] 

instance Yesod App where 
    maximumContentLength _ (Just ImagesR) = Just $ 200 * 1024 * 1024 -- 200 megabytes 
    maximumContentLength _ _ = Just $ 10 * 1024 * 1024 -- 10 megabytes 

instance YesodPersist App where 
    type YesodPersistBackend App = SqlBackend 
    runDB action = do 
     App _ pool <- getYesod 
     runSqlPool action pool 

instance RenderMessage App FormMessage where 
    renderMessage _ _ = defaultFormMessage 

uploadDirectory :: FilePath 
uploadDirectory = "static" 

uploadForm :: Html -> MForm Handler (FormResult (FileInfo, Maybe Textarea, UTCTime), Widget) 
uploadForm = renderBootstrap $ (,,) 
    <$> fileAFormReq "Image file" 
    <*> aopt textareaField "Image description" Nothing 
    <*> lift (liftIO getCurrentTime) 

addStyle :: Widget 
addStyle = do 
    -- Twitter Bootstrap 
    addStylesheetRemote "http://netdna.bootstrapcdn.com/twitter-bootstrap/2.1.0/css/bootstrap-combined.min.css" 
    addStylesheetRemote "https://www.w3schools.com/w3css/4/w3.css" 
    -- message style 
    toWidget [lucius|.message { padding: 10px 0; background: #ffffed; } |] 
    -- jQuery 
    addScriptRemote "http://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js" 
    -- delete function 
    toWidget [julius| 
$(function(){ 
    function confirmDelete(link) { 
     if (confirm("Are you sure you want to delete this image?")) { 
      deleteImage(link); 
     }; 
    } 
    function deleteImage(link) { 
     $.ajax({ 
      type: "DELETE", 
      url: link.attr("data-img-url"), 
     }).done(function(msg) { 
      var table = link.closest("table"); 
      link.closest("tr").remove(); 
      var rowCount = $("td", table).length; 
      if (rowCount === 0) { 
       table.remove(); 
      } 
     }); 
    } 

    $("#screenshot").click(function(){ 
    $.ajax({ 
      // sending a JSON encoded body 
      contentType: "application/json", 
      // don't process the body, we'll render data into a valid string 
      processData: false, 
      url: "@{EchoBodyR}", 
      type: "PUT", 
      // notice the usage of stringify here 
      data: JSON.stringify([{name:"Alice",age:25}, {name:"Bob",age:30}]), 
      success: function(data) { 
       alert(data.body); 
       $("#screenshot-pic").attr("src","@{StaticR bsd_jpg}"); 

      }, 
      // this only refers to the data type of the *returned* data 
      dataType: "json" 
     }); 

    return false; 
    }); 

    $("a.delete").click(function() { 
     confirmDelete($(this)); 
     return false; 
    }); 
}); 
|] 
putEchoBodyR :: Handler Value 
putEchoBodyR = do 
    texts <- rawRequestBody $$ CT.decode CT.utf8 =$ CL.consume 
    return $ object ["body" .= T.concat texts] 


getImagesR :: Handler Html 
getImagesR = do 
    ((_, widget), enctype) <- runFormPost uploadForm 
    images <- runDB $ selectList [ImageFilename !=. ""] [Desc ImageDate] 
    mmsg <- getMessage 
    defaultLayout $ do 
     addStyle 
     [whamlet|$newline never 
$maybe msg <- mmsg 
    <div .message> 
     <div .container> 
      #{msg} 
<div .container> 
    <div .row> 
     <h2> 
      Upload new image 

     <button #screenshot class="w3-button w3-teal">Screenshot 

     <img #screenshot-pic class="w3-round"> 

     <div .form-actions> 
      <form method=post enctype=#{enctype}> 
       ^{widget} 
       <input .btn type=submit value="Upload"> 
     $if not $ null images 
      <table .table> 
       <tr> 
        <th> 
         Image 
        <th> 
         Decription 
        <th> 
         Uploaded 
        <th> 
         Action 
       $forall Entity imageId image <- images 
        <tr> 
         <td> 
          <a href=#{imageFilePath $ imageFilename image}> 
           #{imageFilename image} 
         <td> 
          $maybe description <- imageDescription image 
           #{description} 
         <td> 
          #{show $ imageDate image} 
         <td> 
          <a href=# .delete [email protected]{ImageR imageId}> 
           delete 

|] 

postImagesR :: Handler Html 
postImagesR = do 
    ((result, widget), enctype) <- runFormPost uploadForm 
    case result of 
     FormSuccess (file, info, date) -> do 
      -- TODO: check if image already exists 
      -- save to image directory 
      filename <- writeToServer file 
      _ <- runDB $ insert (Image filename info date) 
      setMessage "Image saved" 
      redirect ImagesR 
     _ -> do 
      setMessage "Something went wrong" 
      redirect ImagesR 

deleteImageR :: ImageId -> Handler() 
deleteImageR imageId = do 
    image <- runDB $ get404 imageId 
    let filename = imageFilename image 
     path = imageFilePath filename 
    liftIO $ removeFile path 
    -- only delete from database if file has been removed from server 
    stillExists <- liftIO $ doesFileExist path 

    case (not stillExists) of 
     False -> redirect ImagesR 
     True -> do 
      runDB $ delete imageId 
      setMessage "Image has been deleted." 
      redirect ImagesR 

writeToServer :: FileInfo -> Handler FilePath 
writeToServer file = do 
    let filename = unpack $ fileName file 
     path = imageFilePath filename 
    liftIO $ fileMove file path 
    return filename 

imageFilePath :: String -> FilePath 
imageFilePath f = uploadDirectory </> f 

openConnectionCount :: Int 
openConnectionCount = 10 

main :: IO() 
main = do 
    pool <- runStdoutLoggingT $ createSqlitePool "images.db3" openConnectionCount 
    runSqlPool (runMigration migrateAll) pool 
    -- Get the static subsite, as well as the settings it is based on 
    createDirectoryIfMissing True uploadDirectory 
    [email protected](Static settings) <- static uploadDirectory 
    warp 3000 $ App static pool 
+3

この例は最小限ではありませんが、これを切り詰めるようにしてください。おそらく(私はすべてのコードを見ていない)あなたはどこかで変数を定義せずに変数 'bsd_jpg'をタイプするような愚かな何かをしなかった場合、スプライスが悪いコードを生成しています。 '-ddump-splices'を使ってスプライスの実際の出力を確認し、' bsd_jpg'の出現箇所を探します。私の推測では、「@ {StaticR bsd_jpg}」を含むスプライスが原因です。 – user2407038

答えて

3

私は、このコードは、デフォルトのsqliteのベースイェソド足場から取得され表示されません。 Yesodで遊んでいるのであれば、それから始めることをお勧めします(stack templates + stack new <selected-template>)。

staticFilesはTemplate Haskell関数であり、これらを使用するにはいくつかの制限があることに注意してください。具体的には、生成された同じ.hsファイルから生成されたコードを使用することはできません。

+0

本当にうわー!私はTemplate Haskellの限界を知らない – WellTyped

関連する問題