Snap:编译拼接代码示例 [英] Snap: compiled splices code example

查看:140
本文介绍了Snap:编译拼接代码示例的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



解释 runChildrenWith(Text) mapSplices 在编译的拼接世界中? (这个组合似乎是最常见的)
如果可能的话,我会非常感激一些代码示例。如果我理解正确,我们将所有应用程序拼接,然后将它们添加到 heistInit 中。任何人都可以展示如何做到这一点吗?



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



是否有完整的快照项目利用新的API和编译拼接,以便我可以阅读和了解学习?



谢谢。


$ b - UPDATE -



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

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

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

  mySplices = C.manyWithSplices C.runChildren mySplice 

这是正确的吗?



我尝试在heist配置中添加拼接错误。

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

我哪里错了?



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



- UPDATE 2 -



感谢极端有用的丹尼尔答案I可以最终得到一些工作。



到目前为止,我得到了两种代码工作方式。



第一个,感谢Daniel

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



  testSplice :: C.Splice(Handler App App)
testSplice = return $ C.yieldRuntimeText $ return要拼接的文本

其中

  (C.pureSplice。C.textSplice $ id)

产生与

$ b类似的结果
$ b

  return $ C.yieldRuntimeText $ return要拼接的文本

以上是否有区别?任何情况下,一个人会喜欢另一个?他们似乎产生了相同的结果。

编译后的拼接库中有一个deferMany函数,根据这些文档,在解释中产生与mapSplices类似的结果库。
我们可以用它来代替C.manyWithSplices C.runChildren组合吗?

解决方案

显示关于使用编译拼接的人员列表的信息(假设我们从由 snap init 生成的脚手架开始)。



一个非常简单的带有虚拟值的 _persons.tpl 模板可能类似于

 <身体GT; 
< person>
< div>
< h1><名称>虚拟名称< /名称>< / h1>
< p>< age> 77< / age>< / p>
< p>< location> jauja< / location>< / p>
< / div>
< / person>
< / body>

其中 person name age location 是要拼接的标签。



我们定义一个容易获得信息的简单Snaplet

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

makeLenses''Foo

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

makeLenses''Person

我们将它添加到应用程序记录中:

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

我们将以下内容添加到应用程序初始化程序中:

$ p $ f < - nestSnapletfoofoo $ makeSnapletfooFoo Snaplet没什么$ retu $ foo $
[Person'Ricardo'33'Los Cantones'
,Person'Luis'38'Montealto'
]

...

return $ App hsaf

该函数构造一个Handler,它返回人员列表(从 Control.Lens )使用 view

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

这个函数从 RuntimeSplice 产生一个人员列表。 RuntimeSplice s表示只能在运行时才知道的信息,而不是加载时间:

  personSplice :: Monad n => RuntimeSplice n [Person]  - > C.Splice n 
personSplice = C.manyWithSplices C.runChildren splicefuncs
其中
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 - >
初始化器bv()
addPersonSplices hl = addConfig h $ mempty
{
hcCompiledSplices =person##(personSplice。lift $ personH​​ l)
}

一定要将这一行添加到应用程序初始化程序中:

  addPersonSplices h foo 

然后添加以下对到应用程序的路线:

 (/ persons,cRender_persons)

如果您现在运行服务器,请导航到 http://127.0.0.1:8000/persons 应显示列表。



更新

没有复杂的记录,没有镜头),你只想显示一个字符串列表。



模板可能是这样的:

 < body> 
<字符串>
< p><字串>虚拟值< / string>< / p>
< / strings>
< / body>

顶级拼接可能是:

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

这意味着当我们遇到与此相关的标签时拼接,执行产生字符串列表的动作,并为每个字符串渲染标签的内容,用当前字符串替换字符串标签。



请注意,强制将(##)右边的内容加入类型 RuntimeSplice n Text - > Splice n 。这里 id 的类型是 Text - >文本 C.TextSplice 将其转换为类型的文本 - 文本 - > Builder C.pureSplice 执行最终转换为 RuntimeSplice n Text - > Splice n



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

注册这个拼接的函数是:

  addStringSplices :: HasHeist b => Snaplet(Heist b) - >初始化程序bv()
addStringSplices h = addConfig h $ mempty
{
hcCompiledSplices =strings## stringSplice
}


I think I did asked a similar question some time ago but it was not answered due to unstable API. So I was waiting for the 0.13 to pass by. I am not sure if it is correct to bring up a similar question...?

What is the alternative to interpreted runChildrenWith(Text) and mapSplices in the compiled splices world? (this combination seems to be the most common) I would really appreciate some code examples if possible.

If I understand correctly, we get together all the application splices and then add them to the heistInit. Can anyone show how to do it please?

Does the splice binding tag has to be unique across the whole application?

Is there a completed snap project utilising new APIs and compiled splices so that I could read and see learn?

Thank you.

-- UPDATE --

Great answer below. But some parts (the ones with lenses) got me even more confused, unfortunately. If I understand correctly this is the simple way to splice a string:

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

If i need to run the spliced string several times, say in 5 table raws i would do it like this:

mySplices = C.manyWithSplices C.runChildren mySplice

Is this correct?

I get bunch of errors trying to add the splices in heist config.

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

Where am I going wrong? Sorry for being slow.

All I need really ( just for now so I can understand) is to splice and display a simple string that I receive from database.

-- UPDATE 2 --

Thanks to the extremle helpfull Daniel`s answer I can finally get something working.

So far I get both variants of code working.

The first one, thanks to 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)

And the secod

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

Where

(C.pureSplice . C.textSplice $ id)

produces similar results to

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

Is there difference between the above? Any cases that one would prefer one to another? They seem to produce the same results.

There is a "deferMany" function in the compiled splices lib that, according to the docs, produces similar results to the mapSplices in interpreted lib. Can we use it instead of "C.manyWithSplices C.runChildren" combination??

解决方案

Let's say you want to display information about a list of persons using compiled splices (assume that we start from the scaffolding generated by snap init.)

A very simple _persons.tpl template with dummy values would be something like

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

Where person, name, age, and location are the tags to be spliced.

We define a trivial Snaplet that holds the info

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

makeLenses ''Foo

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

makeLenses ''Person

and we add it to the App record:

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

we add the following to the app initializer

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

This function constructs a Handler that returns the list of persons (using view from Control.Lens):

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

This function constructs the appropiate compiled splice from a RuntimeSplice that produces a list of Persons. RuntimeSplices represent information that can only be known at run time, as opposed to load time:

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

And this function can be used to register the splice in the global Heist configuration. Notice that we lift the Handler into a 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) 
   } 

Be sure to add this line to the app initializer:

addPersonSplices h foo

And to add the following pair to the app's routes:

("/persons",  cRender "_persons")

If you now run the server, navigating to http://127.0.0.1:8000/persons should show the list.

UPDATE

For the simpler case (no complex records, no lenses) in which you only want to show a list of strings.

The template could be something like:

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

The top-level splice would be:

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

This means "when we encounter the tag associated to this splice, perform an action that produces a list of strings, and for each string, render the contents of the tag, substituting the current string for the string tag".

Notice that the signature of manyWithSplices forces the stuff to the right of the (##) to have type RuntimeSplice n Text -> Splice n. Here id has type Text -> Text. C.TextSplice transforms it into something of type Text -> Builder, and C.pureSplice performs the final transformation into a RuntimeSplice n Text -> Splice n.

In place of (return ["aa","bb","cc"]) you could provide a more complex action that connected a database and extracted the strings form there.

A function to register this splice would be:

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

这篇关于Snap:编译拼接代码示例的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆