【问题标题】:Snap: compiled splices code exampleSnap:编译的拼接代码示例
【发布时间】:2013-11-01 14:55:09
【问题描述】:

我想我前段时间确实问过类似的问题,但由于 API 不稳定而没有回答。所以我在等待 0.13 过去。我不确定提出类似问题是否正确...?

在编译拼接世界中解释 runChildrenWith(Text)mapSplices 的替代方案是什么? (这个组合似乎是最常见的) 如果可能的话,我真的很感激一些代码示例。

如果我理解正确,我们将所有应用程序拼接在一起,然后将它们添加到heistInit。谁能告诉我怎么做?

拼接绑定标签在整个应用程序中是否必须是唯一的?

是否有完整的 snap 项目utilising 新的 API 和编译的拼接,以便我可以阅读和学习?

谢谢。

-- 更新--

下面的答案很好。但不幸的是,有些部分(带镜片的部分)让我更加困惑。 如果我理解正确,这是拼接字符串的简单方法:

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

如果我需要多次运行拼接字符串,比如在 5 个表中,我会这样做:

mySplices = C.manyWithSplices C.runChildren mySplice

这对吗?

我在尝试在抢劫配置中添加接头时遇到一堆错误。

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

我哪里错了?抱歉有点慢。

我真正需要的(只是现在我能理解的)就是拼接并显示一个我从数据库接收到的简单字符串。

-- 更新 2 --

感谢 Daniel 的极有帮助的回答,我终于可以开始工作了。

到目前为止,我的两种代码都可以正常工作。

第一个,感谢丹尼尔

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

第二个

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”函数,根据文档,它产生与解释库中的 mapSplices 相似的结果。 我们可以用它来代替“C.manyWithSplices C.runChildren”的组合吗??

【问题讨论】:

  • @r 编译的拼接起初并不直观,因为它们需要控制反转:您必须告诉拼接如何找到所需的运行时数据。我花了一段时间来掌握他们的窍门。我认为它们在最新版本的抢劫中变得更容易使用了。
  • @r 我认为C.yieldRuntimeTextC.deferMany 在您不关心要拼接的标签内容时就足够了:您只想用生成的字符串完全替换标签. withSplicesmanyWithSplices 可以在您想要渲染(一个,多个)具有字段的复杂结构时使用,并且您确实关心拼接标签的内容,因为它们定义了结构的“视图”。 withSplicesmanyWithSplices 让您在顶级拼接和渲染各个字段的子拼接之间建立对应关系。
  • @r 这就是为什么C.withSplicesC.manyWithSplices 经常与C.runWithChildren 结合使用。这基本上就像说“使用标签的内容作为我们要渲染的结构的视图”。
  • @Daniel 再次感谢。如果卡住了,我会尝试找出其余的并打开另一个问题。

标签: haskell haskell-snap-framework heist


【解决方案1】:

假设您要显示有关使用已编译拼接的人员列表的信息(假设我们从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是要拼接的标签。

我们定义了一个简单的 Snaplet 来保存信息

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

makeLenses ''Foo

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

makeLenses ''Person

我们将其添加到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

此函数构造一个返回人员列表的处理程序(使用来自Control.Lensview):

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

此函数从生成人员列表的RuntimeSplice 构造适当的编译拼接。 RuntimeSplices 表示只能在运行时知道的信息,而不是加载时:

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)
        ]

并且该功能可用于在全局Heist配置中注册拼接。请注意,我们将Handler 提升为RuntimeSplice

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 应该会显示列表。

更新

对于更简单的情况(没有复杂的记录,没有镜头),您只想显示字符串列表。

模板可能类似于:

<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 -&gt; Splice n 类型。这里id 的类型为Text -&gt; TextC.TextSplice 将其转换为 Text -&gt; Builder 类型,C.pureSplice 执行最终转换为 RuntimeSplice n Text -&gt; Splice n

代替(return ["aa","bb","cc"]),您可以提供更复杂的操作来连接数据库并从那里提取字符串。

注册这个拼接的函数是:

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

【讨论】:

  • 感谢 Daniel 提供更新的答案。这终于开始有意义了。我可以在您在更新中提供的简单练习的基础上构建更复杂的练习。我上面还有几个后续问题。很抱歉问了这么长的问题),但你似乎是我在这方面唯一的知识来源,我想尽可能多地获得。谢谢。
  • 很好的答案。我唯一的评论是 snaplet 的东西与编译抢劫的问题无关。正如您的示例所示,它 可以 但是,但不一定如此。您无需了解 snaplets 即可了解已编译的 Heist。您的更新有助于说明这一点,但我只是想我会强调这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-22
  • 1970-01-01
相关资源
最近更新 更多