2013-10-23 72 views
4

我想我前段時間曾問過類似的問題,但由於API不穩定而沒有回答。所以我等待0.13通過。我不確定提出類似的問題是否正確...?捕捉:編譯拼接代碼示例

編譯拼接世界中解釋runChildrenWith(Text)mapSplices的替代方案是什麼? (這個組合似乎是最常見的) 如果可能,我會非常感激一些代碼示例。

如果我理解正確,我們將所有應用程序拼接在一起,然後將它們添加到heistInit。任何人都可以展示如何做到這一點?

拼接綁定標籤在整個應用程序中是否必須是唯一的?

是否有完整的快照項目utilising新的API和編譯拼接,以便我可以閱讀和了解學習?

謝謝。

- 更新 -

大下面的答案。但不幸的是,有些部件(帶鏡頭的部件)讓我更加困惑。 如果我理解正確的話,這是簡單的方式拼接的字符串:

mySplice = "testSplice" ## testSplice 
    where testSplice = return $ C.yieldRuntimeText $ do 
      return "text to be spliced" 

如果我需要運行拼接字符串幾次,在5個原糖說我會做這樣的:

mySplices = C.manyWithSplices C.runChildren mySplice 

這是正確的嗎?

我收到一堆錯誤,試圖在heist配置中添加接頭。

addConfig h $ mempty 
{ 
    hcCompiledSplices = "mySplice" ## mySplice -- or mySplices 
} 

我哪裏錯了?對不起,速度很慢。

我真正需要的所有東西(只是現在,所以我可以理解)是拼接並顯示從數據庫接收的簡單字符串。

- UPDATE 2 -

得益於extremle樂於助人的丹尼爾答案我終於可以得到的東西的工作。

到目前爲止,我得到了兩種代碼工作方式。

第一個,由於丹尼爾

stringSplice :: Monad n => C.Splice n 
stringSplice = C.manyWithSplices C.runChildren splicefuncs (return ["aa","bb","cc"]) 
    where 
    splicefuncs = "string" ## (C.pureSplice . C.textSplice $ id) 

而且secod

testSplice :: C.Splice (Handler App App) 
testSplice = return $ C.yieldRuntimeText $ return "text to be spliced" 

(C.pureSplice . C.textSplice $ id) 

產生類似的結果

return $ C.yieldRuntimeText $ return "text to be spliced" 

以上是否有區別?任何情況下,一個人會喜歡另一個?他們似乎產生了相同的結果。

在編譯後的拼接庫中有一個「deferMany」函數,根據這些文檔,在解釋的lib中產生與mapSplices類似的結果。 我們可以用它來代替「C.manyWithSplices C.runChildren」的組合嗎?

+0

@r編譯拼接是不直觀,在第一,因爲它們需要控制的反轉:你必須告訴拼接如何找到所需的運行數據。我花了一段時間才弄到這些東西。我認爲他們已經變得更容易在最新版本的搶劫中使用。 – danidiaz

+0

@r我覺得'C.yieldRuntimeText'和'C.deferMany'就足夠了,當你不關心你想要拼接的標籤的內容時:你只需要用生成的字符串完全替換標籤。當您想渲染(一個,多個)具有字段的複雜結構時,可以使用'withSplices'和'manyWithSplices',並且您關心拼接標籤的內容,因爲它們定義了結構的「視圖」。 'withSplices'和'manyWithSplices'可以讓你在頂層拼接和渲染單個字段的子文件之間建立對應關係。 – danidiaz

+0

@r這就是爲什麼'C.withSplices'和'C.manyWithSplices'經常與'C.runWithChildren'結合使用的原因。這基本上就像是說「使用標籤的內容作爲我們要呈現的結構的視圖」。 – danidiaz

回答

6

比方說,你想顯示關於使用編譯接頭的人員名單信息(假設我們從snap init產生的腳手架開始。)

一個非常簡單的_persons.tpl模板虛擬值會是這樣的

<body> 
    <person> 
     <div> 
      <h1><name>dummy name</name></h1> 
      <p><age>77</age></p> 
      <p><location>jauja</location></p> 
     </div> 
    </person> 
</body> 

personnameagelocation是要拼接的標籤。

我們定義保存的信息

data Foo = Foo 
    { 
     _persons :: [Person] 
    } 

makeLenses ''Foo 

data Person = Person 
    { 
     _name :: Text 
    , _age :: Int 
    , _location :: Text 
    } 

makeLenses ''Person 

瑣碎Snaplet,我們把它添加到App記錄:

data App = App 
    { _heist :: Snaplet (Heist App) 
    , _sess :: Snaplet SessionManager 
    , _auth :: Snaplet (AuthManager App) 
    , _foo :: Snaplet Foo 
    } 

我們以下內容添加到應用程序初始化

f <- nestSnaplet "foo" foo $ makeSnaplet "foo" "Foo Snaplet" Nothing $ return $ Foo $ 
     [ Person "Ricardo" 33 "Los Cantones" 
     , Person "Luis" 38 "Montealto" 
     ] 

... 

return $ App h s a f 

該函數構造一個處理程序,它返回人員列表(使用viewControl.Lens):

personH :: SnapletLens b Foo -> Handler b b [Person] 
personH l = withTop l $ view persons <$> get 

此函數構造從RuntimeSplice產生的人的列表編譯剪接的不合適。 RuntimeSplice s爲只能在運行時是已知的信息,而不是加載時間:

personSplice :: Monad n => RuntimeSplice n [Person] -> C.Splice n 
personSplice = C.manyWithSplices C.runChildren splicefuncs 
    where 
    splicefuncs = mconcat 
     [ "name" ## (C.pureSplice . C.textSplice $ view name) 
     , "age" ## (C.pureSplice . C.textSplice $ T.pack . show . view age) 
     , "location" ## (C.pureSplice . C.textSplice $ view location) 
     ] 

而這個函數可用於註冊在全局斯特配置拼接。請注意,我們解除HandlerRuntimeSplice

addPersonSplices :: HasHeist b => Snaplet (Heist b) -> 
            SnapletLens b Foo -> 
            Initializer b v() 
addPersonSplices h l = addConfig h $ mempty 
    { 
     hcCompiledSplices = "person" ## (personSplice . lift $ personH l) 
    } 

一定要將此行添加到應用程序初始化:

addPersonSplices h foo 

而且下面對添加到應用程序的路徑:

("/persons", cRender "_persons") 

如果您現在運行服務器,導航到http://127.0.0.1:8000/persons應顯示該列表。

UPDATE

對於簡單的情況下(沒有複雜的記錄,無鏡片)中,你只想要顯示的字符串列表。

模板可以是這樣的:

<body> 
    <strings> 
     <p><string>dummy value</string></p> 
    </strings> 
</body> 

頂級拼接是:

stringSplice :: Monad n => C.Splice n 
stringSplice = C.manyWithSplices C.runChildren splicefuncs (return ["aa","bb","cc"]) 
    where 
    splicefuncs = "string" ## (C.pureSplice . C.textSplice $ id) 

這意味着「當我們遇到關聯到這個拼接標記,執行的行動,生成一個字符串列表,併爲每個字符串呈現標記的內容,用當前字符串替代string標記「。

請注意,manyWithSplices的簽名強制(##)右側的內容的類型爲RuntimeSplice n Text -> Splice n。這裏id有型號Text -> TextC.TextSplice將其轉換爲Text -> Builder類型的內容,C.pureSplice執行最終轉換爲RuntimeSplice n Text -> Splice n

代替(return ["aa","bb","cc"])您可以提供更復雜的操作,連接數據庫並從中提取字符串。

一個函數註冊到這個拼接是:

addStringSplices :: HasHeist b => Snaplet (Heist b) -> Initializer b v() 
addStringSplices h = addConfig h $ mempty 
    { 
      hcCompiledSplices = "strings" ## stringSplice 
    } 
+0

非常感謝您爲我寫這篇文章。看到上面的更新... –

+0

感謝丹尼爾更新的答案。這終於開始有意義了。我可以在更新中提供的簡單內容之上構建更復雜的內容。我有一個更多後續問題的聯席會議。對於長長的問題,抱歉),但你似乎是我的唯一知識來源,我希望儘可能多地獲得。謝謝。 –

+1

很棒的回答。我唯一的意見就是,這些簡單的東西與編譯Heist的問題無關。正如你的例子所示,它*可以*但是,但它不一定是。你不需要理解理解編譯後的海斯特就能理解。你的更新有助於明確,但我只是認爲我會強調這一點。 – mightybyte