Based on some feedback from folks like Alex Black, I've enhanced Lift's support for stateless requests.
First, determining if a request should be stateless. There's a new LiftRule: /** * Certain paths and requests within your application can be marked as stateless * and if there is access to Lift's stateful facilities (setting * SessionVars, updating function tables, etc.) the developer will * receive a notice and the operation will not complete. */ val statelessReqTest = RulesSeq[StatelessReqTestPF]
/** * The test between the path of a request, the HTTP request, and whether that path * should result in stateless servicing of that path */ type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
/** * The data structure that contains information to determine if the * request should be treated as a stateful or stateless request */ final case class StatelessReqTest(path: List[String], httpReq: HTTPRequest)
You can now test the HTTPRequest for stuff like user agent, cookies, etc. to determine if the request should be stateless.
Further, a Loc can be marked as stateless based on a function executed at request time via LocParams:
/** * A function that calculates the statelessness of the Loc for the given request */ case class CalcStateless(f: () => Boolean) extends AnyLocParam
/** * A function that calculates the statelessness of the Loc for the given request * with the parameterized type passed into the function */ case class CalcParamStateless[-T](f: Box[T] => Boolean) extends LocParam[T]
Finally, it's bad practice to ignore the state in stateless error boxes. They mean that there's something wrong with your code. However, it seems that some folks have snippets that access session state and just kinda ignore that sometimes these snippets execute in stateless mode because in production mode the only bad thing that happens is that a log message is generated.
For those folks, I've added the following traits:
/** * Mix this snippet into any snippet. If the snippet is invoked in response to a * stateless request, then the behavior method is called with the method name of * the snippet (usually render, but there may be others if you specify a method * after the snippet name: MySnippet.dothing). */ trait StatelessBehavior { /** * Given the method name, return the transformation for the method */ def behavior(methodName: String): NodeSeq => NodeSeq
}
/** * A simpler way to define behavior if the snippet is invoked. Just implement the behavior() method * and all methods for the snippet will use that behavior. */ trait DefaultStatelessBehavior extends StatelessBehavior { def behavior(): NodeSeq => NodeSeq def behavior(methodName: String): NodeSeq => NodeSeq = behavior()
}
/** * A "default" implementation of StatelessBehavior. Just ignore everything and return a zero-length Text. */ trait BlankStatelessBehavior extends StatelessBehavior { def behavior(methodName: String): NodeSeq => NodeSeq = ignore => Text("")
}
Mix these traits into your the snippets that have stateful access. The snippet execution will be short-circuited and the behavior defined in the StatelessBehavior will be used instead of the normal snippet behavior. Put simply, mix BlankStatelessBehavior into your snippets that display buttons and forms and such and instead of executing those snippets, you'll just get empty Node in your output.
Questions?
Thanks,
David
PS -- Alex -- stateless is binary... a request is either handled in a stateless manner or not. There's no tri-state or ability to toggle the statelessness based on user actions (although you could do so by putting a marker cookie in responses of a certain type and then look for that cookie in the stateless test.)
> Based on some feedback from folks like Alex Black, I've enhanced Lift's > support for stateless requests.
> First, determining if a request should be stateless. There's a new > LiftRule: > /** > * Certain paths and requests within your application can be marked as > stateless > * and if there is access to Lift's stateful facilities (setting > * SessionVars, updating function tables, etc.) the developer will > * receive a notice and the operation will not complete. > */ > val statelessReqTest = RulesSeq[StatelessReqTestPF]
> /** > * The test between the path of a request, the HTTP request, and whether > that path > * should result in stateless servicing of that path > */ > type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
> /** > * The data structure that contains information to determine if the > * request should be treated as a stateful or stateless request > */ > final case class StatelessReqTest(path: List[String], httpReq: HTTPRequest)
> You can now test the HTTPRequest for stuff like user agent, cookies, etc. > to determine if the request should be stateless.
> Further, a Loc can be marked as stateless based on a function executed at > request time via LocParams:
> /** > * A function that calculates the statelessness of the Loc for the given > request > */ > case class CalcStateless(f: () => Boolean) extends AnyLocParam
> /** > * A function that calculates the statelessness of the Loc for the given > request > * with the parameterized type passed into the function > */ > case class CalcParamStateless[-T](f: Box[T] => Boolean) extends > LocParam[T]
> Finally, it's bad practice to ignore the state in stateless error boxes. > They mean that there's something wrong with your code. However, it seems > that some folks have snippets that access session state and just kinda > ignore that sometimes these snippets execute in stateless mode because in > production mode the only bad thing that happens is that a log message is > generated.
> For those folks, I've added the following traits:
> /** > * Mix this snippet into any snippet. If the snippet is invoked in > response to a > * stateless request, then the behavior method is called with the method > name of > * the snippet (usually render, but there may be others if you specify a > method > * after the snippet name: MySnippet.dothing). > */ > trait StatelessBehavior { > /** > * Given the method name, return the transformation for the method > */ > def behavior(methodName: String): NodeSeq => NodeSeq > }
> /** > * A simpler way to define behavior if the snippet is invoked. Just > implement the behavior() method > * and all methods for the snippet will use that behavior. > */ > trait DefaultStatelessBehavior extends StatelessBehavior { > def behavior(): NodeSeq => NodeSeq > def behavior(methodName: String): NodeSeq => NodeSeq = behavior() > }
> /** > * A "default" implementation of StatelessBehavior. Just ignore everything > and return a zero-length Text. > */ > trait BlankStatelessBehavior extends StatelessBehavior { > def behavior(methodName: String): NodeSeq => NodeSeq = ignore => Text("") > } > Mix these traits into your the snippets that have stateful access. The > snippet execution will be short-circuited and the behavior defined in the > StatelessBehavior will be used instead of the normal snippet behavior. Put > simply, mix BlankStatelessBehavior into your snippets that display buttons > and forms and such and instead of executing those snippets, you'll just get > empty Node in your output.
> Questions?
> Thanks,
> David
> PS -- Alex -- stateless is binary... a request is either handled in a > stateless manner or not. There's no tri-state or ability to toggle the > statelessness based on user actions (although you could do so by putting a > marker cookie in responses of a certain type and then look for that cookie > in the stateless test.)
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
Also perhaps the case class should not have "Test" in its name, since it's not a test; it just represents a request. Why not use Req -- is it only for stateful requests? (If yes then it certainly makes sense to just call the case class StatelessReq.)
On Tue, Aug 23, 2011 at 6:47 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
> Why bother with StatelessBehavior? Why not just an API to test if the > current request is stateless?
> Also perhaps the parameterless def behavior should not have the empty > parameter list?
> On Tue, Aug 23, 2011 at 5:05 PM, David Pollak < > feeder.of.the.be...@gmail.com> wrote:
>> Folks,
>> Based on some feedback from folks like Alex Black, I've enhanced Lift's >> support for stateless requests.
>> First, determining if a request should be stateless. There's a new >> LiftRule: >> /** >> * Certain paths and requests within your application can be marked as >> stateless >> * and if there is access to Lift's stateful facilities (setting >> * SessionVars, updating function tables, etc.) the developer will >> * receive a notice and the operation will not complete. >> */ >> val statelessReqTest = RulesSeq[StatelessReqTestPF]
>> /** >> * The test between the path of a request, the HTTP request, and whether >> that path >> * should result in stateless servicing of that path >> */ >> type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
>> /** >> * The data structure that contains information to determine if the >> * request should be treated as a stateful or stateless request >> */ >> final case class StatelessReqTest(path: List[String], httpReq: >> HTTPRequest)
>> You can now test the HTTPRequest for stuff like user agent, cookies, etc. >> to determine if the request should be stateless.
>> Further, a Loc can be marked as stateless based on a function executed at >> request time via LocParams:
>> /** >> * A function that calculates the statelessness of the Loc for the given >> request >> */ >> case class CalcStateless(f: () => Boolean) extends AnyLocParam
>> /** >> * A function that calculates the statelessness of the Loc for the given >> request >> * with the parameterized type passed into the function >> */ >> case class CalcParamStateless[-T](f: Box[T] => Boolean) extends >> LocParam[T]
>> Finally, it's bad practice to ignore the state in stateless error boxes. >> They mean that there's something wrong with your code. However, it seems >> that some folks have snippets that access session state and just kinda >> ignore that sometimes these snippets execute in stateless mode because in >> production mode the only bad thing that happens is that a log message is >> generated.
>> For those folks, I've added the following traits:
>> /** >> * Mix this snippet into any snippet. If the snippet is invoked in >> response to a >> * stateless request, then the behavior method is called with the method >> name of >> * the snippet (usually render, but there may be others if you specify a >> method >> * after the snippet name: MySnippet.dothing). >> */ >> trait StatelessBehavior { >> /** >> * Given the method name, return the transformation for the method >> */ >> def behavior(methodName: String): NodeSeq => NodeSeq >> }
>> /** >> * A simpler way to define behavior if the snippet is invoked. Just >> implement the behavior() method >> * and all methods for the snippet will use that behavior. >> */ >> trait DefaultStatelessBehavior extends StatelessBehavior { >> def behavior(): NodeSeq => NodeSeq >> def behavior(methodName: String): NodeSeq => NodeSeq = behavior() >> }
>> /** >> * A "default" implementation of StatelessBehavior. Just ignore >> everything and return a zero-length Text. >> */ >> trait BlankStatelessBehavior extends StatelessBehavior { >> def behavior(methodName: String): NodeSeq => NodeSeq = ignore => >> Text("") >> } >> Mix these traits into your the snippets that have stateful access. The >> snippet execution will be short-circuited and the behavior defined in the >> StatelessBehavior will be used instead of the normal snippet behavior. Put >> simply, mix BlankStatelessBehavior into your snippets that display buttons >> and forms and such and instead of executing those snippets, you'll just get >> empty Node in your output.
>> Questions?
>> Thanks,
>> David
>> PS -- Alex -- stateless is binary... a request is either handled in a >> stateless manner or not. There's no tri-state or ability to toggle the >> statelessness based on user actions (although you could do so by putting a >> marker cookie in responses of a certain type and then look for that cookie >> in the stateless test.)
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
Feedback:
- StatelessReqTest looks great, I can easily see how we can use that
to mark say requests from GoogleBot as stateless
- I haven't yet been able to understand the behavior trait, I'm not
following what use case its for, or how to use it, I'll read it over
again.
I'm still interested in not creating sessions until they're needed,
but, thats probably just icing on the cake, being able to not give
sessions to crawlers should be a big help.
- Alex
On Aug 23, 5:05 pm, David Pollak <feeder.of.the.be...@gmail.com>
wrote:
> Based on some feedback from folks like Alex Black, I've enhanced Lift's
> support for stateless requests.
> First, determining if a request should be stateless. There's a new
> LiftRule:
> /**
> * Certain paths and requests within your application can be marked as
> stateless
> * and if there is access to Lift's stateful facilities (setting
> * SessionVars, updating function tables, etc.) the developer will
> * receive a notice and the operation will not complete.
> */
> val statelessReqTest = RulesSeq[StatelessReqTestPF]
> /**
> * The test between the path of a request, the HTTP request, and whether
> that path
> * should result in stateless servicing of that path
> */
> type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
> /**
> * The data structure that contains information to determine if the
> * request should be treated as a stateful or stateless request
> */
> final case class StatelessReqTest(path: List[String], httpReq: HTTPRequest)
> You can now test the HTTPRequest for stuff like user agent, cookies, etc. to
> determine if the request should be stateless.
> Further, a Loc can be marked as stateless based on a function executed at
> request time via LocParams:
> /**
> * A function that calculates the statelessness of the Loc for the given
> request
> */
> case class CalcStateless(f: () => Boolean) extends AnyLocParam
> /**
> * A function that calculates the statelessness of the Loc for the given
> request
> * with the parameterized type passed into the function
> */
> case class CalcParamStateless[-T](f: Box[T] => Boolean) extends
> LocParam[T]
> Finally, it's bad practice to ignore the state in stateless error boxes.
> They mean that there's something wrong with your code. However, it seems
> that some folks have snippets that access session state and just kinda
> ignore that sometimes these snippets execute in stateless mode because in
> production mode the only bad thing that happens is that a log message is
> generated.
> For those folks, I've added the following traits:
> /**
> * Mix this snippet into any snippet. If the snippet is invoked in response
> to a
> * stateless request, then the behavior method is called with the method
> name of
> * the snippet (usually render, but there may be others if you specify a
> method
> * after the snippet name: MySnippet.dothing).
> */
> trait StatelessBehavior {
> /**
> * Given the method name, return the transformation for the method
> */
> def behavior(methodName: String): NodeSeq => NodeSeq
> }
> /**
> * A simpler way to define behavior if the snippet is invoked. Just
> implement the behavior() method
> * and all methods for the snippet will use that behavior.
> */
> trait DefaultStatelessBehavior extends StatelessBehavior {
> def behavior(): NodeSeq => NodeSeq
> def behavior(methodName: String): NodeSeq => NodeSeq = behavior()
> }
> /**
> * A "default" implementation of StatelessBehavior. Just ignore everything
> and return a zero-length Text.
> */
> trait BlankStatelessBehavior extends StatelessBehavior {
> def behavior(methodName: String): NodeSeq => NodeSeq = ignore => Text("")}
> Mix these traits into your the snippets that have stateful access. The
> snippet execution will be short-circuited and the behavior defined in the
> StatelessBehavior will be used instead of the normal snippet behavior. Put
> simply, mix BlankStatelessBehavior into your snippets that display buttons
> and forms and such and instead of executing those snippets, you'll just get
> empty Node in your output.
> Questions?
> Thanks,
> David
> PS -- Alex -- stateless is binary... a request is either handled in a
> stateless manner or not. There's no tri-state or ability to toggle the
> statelessness based on user actions (although you could do so by putting a
> marker cookie in responses of a certain type and then look for that cookie
> in the stateless test.)
So, if one wanted users to be stateless until some action took place
you could:
a. mark all requests as stateless by default
b. if the user takes some action, then give them a cookie
c. mark future requests as stateful if the cookie is present
so I'm just thinking this through.. imagine:
- request comes in, no cookie present, mark it as stateless
- process the request, determine its a request to store some state and
hence initiate a session
- now, we cannot store that state in the session, because we're
already stateless
any thoughts? Perhaps I'm over complicating things, or perhaps there
is a way around this.
On Aug 23, 8:18 pm, Alex Black <a...@alexblack.ca> wrote:
> Feedback:
> - StatelessReqTest looks great, I can easily see how we can use that
> to mark say requests from GoogleBot as stateless
> - I haven't yet been able to understand the behavior trait, I'm not
> following what use case its for, or how to use it, I'll read it over
> again.
> I'm still interested in not creating sessions until they're needed,
> but, thats probably just icing on the cake, being able to not give
> sessions to crawlers should be a big help.
> - Alex
> On Aug 23, 5:05 pm, David Pollak <feeder.of.the.be...@gmail.com>
> wrote:
> > Folks,
> > Based on some feedback from folks like Alex Black, I've enhanced Lift's
> > support for stateless requests.
> > First, determining if a request should be stateless. There's a new
> > LiftRule:
> > /**
> > * Certain paths and requests within your application can be marked as
> > stateless
> > * and if there is access to Lift's stateful facilities (setting
> > * SessionVars, updating function tables, etc.) the developer will
> > * receive a notice and the operation will not complete.
> > */
> > val statelessReqTest = RulesSeq[StatelessReqTestPF]
> > /**
> > * The test between the path of a request, the HTTP request, and whether
> > that path
> > * should result in stateless servicing of that path
> > */
> > type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
> > /**
> > * The data structure that contains information to determine if the
> > * request should be treated as a stateful or stateless request
> > */
> > final case class StatelessReqTest(path: List[String], httpReq: HTTPRequest)
> > You can now test the HTTPRequest for stuff like user agent, cookies, etc. to
> > determine if the request should be stateless.
> > Further, a Loc can be marked as stateless based on a function executed at
> > request time via LocParams:
> > /**
> > * A function that calculates the statelessness of the Loc for the given
> > request
> > */
> > case class CalcStateless(f: () => Boolean) extends AnyLocParam
> > /**
> > * A function that calculates the statelessness of the Loc for the given
> > request
> > * with the parameterized type passed into the function
> > */
> > case class CalcParamStateless[-T](f: Box[T] => Boolean) extends
> > LocParam[T]
> > Finally, it's bad practice to ignore the state in stateless error boxes.
> > They mean that there's something wrong with your code. However, it seems
> > that some folks have snippets that access session state and just kinda
> > ignore that sometimes these snippets execute in stateless mode because in
> > production mode the only bad thing that happens is that a log message is
> > generated.
> > For those folks, I've added the following traits:
> > /**
> > * Mix this snippet into any snippet. If the snippet is invoked in response
> > to a
> > * stateless request, then the behavior method is called with the method
> > name of
> > * the snippet (usually render, but there may be others if you specify a
> > method
> > * after the snippet name: MySnippet.dothing).
> > */
> > trait StatelessBehavior {
> > /**
> > * Given the method name, return the transformation for the method
> > */
> > def behavior(methodName: String): NodeSeq => NodeSeq
> > }
> > /**
> > * A simpler way to define behavior if the snippet is invoked. Just
> > implement the behavior() method
> > * and all methods for the snippet will use that behavior.
> > */
> > trait DefaultStatelessBehavior extends StatelessBehavior {
> > def behavior(): NodeSeq => NodeSeq
> > def behavior(methodName: String): NodeSeq => NodeSeq = behavior()
> > }
> > /**
> > * A "default" implementation of StatelessBehavior. Just ignore everything
> > and return a zero-length Text.
> > */
> > trait BlankStatelessBehavior extends StatelessBehavior {
> > def behavior(methodName: String): NodeSeq => NodeSeq = ignore => Text("")}
> > Mix these traits into your the snippets that have stateful access. The
> > snippet execution will be short-circuited and the behavior defined in the
> > StatelessBehavior will be used instead of the normal snippet behavior. Put
> > simply, mix BlankStatelessBehavior into your snippets that display buttons
> > and forms and such and instead of executing those snippets, you'll just get
> > empty Node in your output.
> > Questions?
> > Thanks,
> > David
> > PS -- Alex -- stateless is binary... a request is either handled in a
> > stateless manner or not. There's no tri-state or ability to toggle the
> > statelessness based on user actions (although you could do so by putting a
> > marker cookie in responses of a certain type and then look for that cookie
> > in the stateless test.)
On Tue, Aug 23, 2011 at 6:47 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
> Why bother with StatelessBehavior? Why not just an API to test if the > current request is stateless?
There's already an API to test. The problem is that wrapping an "if (stateless) xxx else normal behavior" around lots of code takes a lot of time and is error prone and messes up the code.
> Also perhaps the parameterless def behavior should not have the empty > parameter list?
Then you get into the "is this a partially applied function or a method call" quandary.
> On Tue, Aug 23, 2011 at 5:05 PM, David Pollak < > feeder.of.the.be...@gmail.com> wrote:
>> Folks,
>> Based on some feedback from folks like Alex Black, I've enhanced Lift's >> support for stateless requests.
>> First, determining if a request should be stateless. There's a new >> LiftRule: >> /** >> * Certain paths and requests within your application can be marked as >> stateless >> * and if there is access to Lift's stateful facilities (setting >> * SessionVars, updating function tables, etc.) the developer will >> * receive a notice and the operation will not complete. >> */ >> val statelessReqTest = RulesSeq[StatelessReqTestPF]
>> /** >> * The test between the path of a request, the HTTP request, and whether >> that path >> * should result in stateless servicing of that path >> */ >> type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
>> /** >> * The data structure that contains information to determine if the >> * request should be treated as a stateful or stateless request >> */ >> final case class StatelessReqTest(path: List[String], httpReq: >> HTTPRequest)
>> You can now test the HTTPRequest for stuff like user agent, cookies, etc. >> to determine if the request should be stateless.
>> Further, a Loc can be marked as stateless based on a function executed at >> request time via LocParams:
>> /** >> * A function that calculates the statelessness of the Loc for the given >> request >> */ >> case class CalcStateless(f: () => Boolean) extends AnyLocParam
>> /** >> * A function that calculates the statelessness of the Loc for the given >> request >> * with the parameterized type passed into the function >> */ >> case class CalcParamStateless[-T](f: Box[T] => Boolean) extends >> LocParam[T]
>> Finally, it's bad practice to ignore the state in stateless error boxes. >> They mean that there's something wrong with your code. However, it seems >> that some folks have snippets that access session state and just kinda >> ignore that sometimes these snippets execute in stateless mode because in >> production mode the only bad thing that happens is that a log message is >> generated.
>> For those folks, I've added the following traits:
>> /** >> * Mix this snippet into any snippet. If the snippet is invoked in >> response to a >> * stateless request, then the behavior method is called with the method >> name of >> * the snippet (usually render, but there may be others if you specify a >> method >> * after the snippet name: MySnippet.dothing). >> */ >> trait StatelessBehavior { >> /** >> * Given the method name, return the transformation for the method >> */ >> def behavior(methodName: String): NodeSeq => NodeSeq >> }
>> /** >> * A simpler way to define behavior if the snippet is invoked. Just >> implement the behavior() method >> * and all methods for the snippet will use that behavior. >> */ >> trait DefaultStatelessBehavior extends StatelessBehavior { >> def behavior(): NodeSeq => NodeSeq >> def behavior(methodName: String): NodeSeq => NodeSeq = behavior() >> }
>> /** >> * A "default" implementation of StatelessBehavior. Just ignore >> everything and return a zero-length Text. >> */ >> trait BlankStatelessBehavior extends StatelessBehavior { >> def behavior(methodName: String): NodeSeq => NodeSeq = ignore => >> Text("") >> } >> Mix these traits into your the snippets that have stateful access. The >> snippet execution will be short-circuited and the behavior defined in the >> StatelessBehavior will be used instead of the normal snippet behavior. Put >> simply, mix BlankStatelessBehavior into your snippets that display buttons >> and forms and such and instead of executing those snippets, you'll just get >> empty Node in your output.
>> Questions?
>> Thanks,
>> David
>> PS -- Alex -- stateless is binary... a request is either handled in a >> stateless manner or not. There's no tri-state or ability to toggle the >> statelessness based on user actions (although you could do so by putting a >> marker cookie in responses of a certain type and then look for that cookie >> in the stateless test.)
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
On Tue, Aug 23, 2011 at 8:26 PM, Alex Black <a...@alexblack.ca> wrote: > I glossed over your point about cookies.
> So, if one wanted users to be stateless until some action took place > you could: > a. mark all requests as stateless by default > b. if the user takes some action, then give them a cookie > c. mark future requests as stateful if the cookie is present
> so I'm just thinking this through.. imagine: > - request comes in, no cookie present, mark it as stateless > - process the request, determine its a request to store some state and > hence initiate a session
This is something you can do. It is not something that Lift can do.
> - now, we cannot store that state in the session, because we're > already stateless
Basically, you need to create a URL that is the "transition from stateless to stateful" URL and when a request comes into that URL, it creates a new, stateful session. But the decision about stateful vs. stateless happens so early in the request response cycle (and it cannot happen any later than it does) that it forecloses on doing the kind of design that you want.
> any thoughts? Perhaps I'm over complicating things, or perhaps there > is a way around this.
> On Aug 23, 8:18 pm, Alex Black <a...@alexblack.ca> wrote: > > Great, I'm looking forward to trying it out.
> > Feedback: > > - StatelessReqTest looks great, I can easily see how we can use that > > to mark say requests from GoogleBot as stateless > > - I haven't yet been able to understand the behavior trait, I'm not > > following what use case its for, or how to use it, I'll read it over > > again.
> > I'm still interested in not creating sessions until they're needed, > > but, thats probably just icing on the cake, being able to not give > > sessions to crawlers should be a big help.
> > - Alex
> > On Aug 23, 5:05 pm, David Pollak <feeder.of.the.be...@gmail.com> > > wrote:
> > > Folks,
> > > Based on some feedback from folks like Alex Black, I've enhanced Lift's > > > support for stateless requests.
> > > First, determining if a request should be stateless. There's a new > > > LiftRule: > > > /** > > > * Certain paths and requests within your application can be marked > as > > > stateless > > > * and if there is access to Lift's stateful facilities (setting > > > * SessionVars, updating function tables, etc.) the developer will > > > * receive a notice and the operation will not complete. > > > */ > > > val statelessReqTest = RulesSeq[StatelessReqTestPF]
> > > /** > > > * The test between the path of a request, the HTTP request, and > whether > > > that path > > > * should result in stateless servicing of that path > > > */ > > > type StatelessReqTestPF = PartialFunction[StatelessReqTest, Boolean]
> > > /** > > > * The data structure that contains information to determine if the > > > * request should be treated as a stateful or stateless request > > > */ > > > final case class StatelessReqTest(path: List[String], httpReq: > HTTPRequest)
> > > You can now test the HTTPRequest for stuff like user agent, cookies, > etc. to > > > determine if the request should be stateless.
> > > Further, a Loc can be marked as stateless based on a function executed > at > > > request time via LocParams:
> > > /** > > > * A function that calculates the statelessness of the Loc for the > given > > > request > > > */ > > > case class CalcStateless(f: () => Boolean) extends AnyLocParam
> > > /** > > > * A function that calculates the statelessness of the Loc for the > given > > > request > > > * with the parameterized type passed into the function > > > */ > > > case class CalcParamStateless[-T](f: Box[T] => Boolean) extends > > > LocParam[T]
> > > Finally, it's bad practice to ignore the state in stateless error > boxes. > > > They mean that there's something wrong with your code. However, it > seems > > > that some folks have snippets that access session state and just kinda > > > ignore that sometimes these snippets execute in stateless mode because > in > > > production mode the only bad thing that happens is that a log message > is > > > generated.
> > > For those folks, I've added the following traits:
> > > /** > > > * Mix this snippet into any snippet. If the snippet is invoked in > response > > > to a > > > * stateless request, then the behavior method is called with the > method > > > name of > > > * the snippet (usually render, but there may be others if you specify > a > > > method > > > * after the snippet name: MySnippet.dothing). > > > */ > > > trait StatelessBehavior { > > > /** > > > * Given the method name, return the transformation for the method > > > */ > > > def behavior(methodName: String): NodeSeq => NodeSeq
> > > }
> > > /** > > > * A simpler way to define behavior if the snippet is invoked. Just > > > implement the behavior() method > > > * and all methods for the snippet will use that behavior. > > > */ > > > trait DefaultStatelessBehavior extends StatelessBehavior { > > > def behavior(): NodeSeq => NodeSeq > > > def behavior(methodName: String): NodeSeq => NodeSeq = behavior()
> > > Mix these traits into your the snippets that have stateful access. The > > > snippet execution will be short-circuited and the behavior defined in > the > > > StatelessBehavior will be used instead of the normal snippet behavior. > Put > > > simply, mix BlankStatelessBehavior into your snippets that display > buttons > > > and forms and such and instead of executing those snippets, you'll just > get > > > empty Node in your output.
> > > Questions?
> > > Thanks,
> > > David
> > > PS -- Alex -- stateless is binary... a request is either handled in a > > > stateless manner or not. There's no tri-state or ability to toggle the > > > statelessness based on user actions (although you could do so by > putting a > > > marker cookie in responses of a certain type and then look for that > cookie > > > in the stateless test.)
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
> On Tue, Aug 23, 2011 at 6:47 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
>> Why bother with StatelessBehavior? Why not just an API to test if the >> current request is stateless?
> There's already an API to test. The problem is that wrapping an "if > (stateless) xxx else normal behavior" around lots of code takes a lot of > time and is error prone and messes up the code.
I hear that.
>> Also perhaps the parameterless def behavior should not have the empty >> parameter list?
> Then you get into the "is this a partially applied function or a method > call" quandary.
Oh, I see.
What is the advantage of DefaultStatelessBehavior -- that it saves the extra typing of def behavior*(method: String)* = ... ?
If so maybe one option to consider is just to make one trait with one method, and define it as def behavior: String => NodeSeq=>NodeSeq
This has two advantages: 1. If you don't care about the method name you can do def behavior = _ => "*" #> ... // very concise. 2. You can use pattern matching syntax: def behavior = { case "method1" => statelessMethod1 case _ => ClearNodes
}
Actually the above reminds me of DispatchSnipet#dispatch, so we can throw in a third advantage: making it easier to remember how to use it, since it's similar to other Lift contstruct(s). Or, come to that, another possibility is to give it the same signature as dispatch. But then you lose #1 above (although it increases #3)...
/** * Mix this snippet into any snippet. If the snippet is invoked in response to a * stateless request, then the behavior method is called with the method name of * the snippet (usually render, but there may be others if you specify a method * after the snippet name: MySnippet.dothing). */ trait StatelessBehavior { /** * Given the method name, return the transformation for the method */ def behaviorDispatch: PartialFunction[String, NodeSeq => NodeSeq]
}
So it's like a DispatchSnippet
On Tue, Aug 23, 2011 at 8:35 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
> On Tue, Aug 23, 2011 at 10:56 PM, David Pollak < > feeder.of.the.be...@gmail.com> wrote:
>> On Tue, Aug 23, 2011 at 6:47 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
>>> Why bother with StatelessBehavior? Why not just an API to test if the >>> current request is stateless?
>> There's already an API to test. The problem is that wrapping an "if >> (stateless) xxx else normal behavior" around lots of code takes a lot of >> time and is error prone and messes up the code.
> I hear that.
>>> Also perhaps the parameterless def behavior should not have the empty >>> parameter list?
>> Then you get into the "is this a partially applied function or a method >> call" quandary.
> Oh, I see.
> What is the advantage of DefaultStatelessBehavior -- that it saves the > extra typing of > def behavior*(method: String)* = ... ?
> If so maybe one option to consider is just to make one trait with one > method, and define it as > def behavior: String => NodeSeq=>NodeSeq
> This has two advantages: > 1. If you don't care about the method name you can do > def behavior = _ => "*" #> ... // very concise. > 2. You can use pattern matching syntax: > def behavior = { > case "method1" => statelessMethod1 > case _ => ClearNodes > }
> Actually the above reminds me of DispatchSnipet#dispatch, so we can throw > in a third advantage: making it easier to remember how to use it, since it's > similar to other Lift contstruct(s). Or, come to that, another possibility > is to give it the same signature as dispatch. But then you lose #1 above > (although it increases #3)...
> Just some food for thought... :)
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
> wrote: > Thanks for the suggestion, I've updated:
> /** > * Mix this snippet into any snippet. If the snippet is invoked in > response to a > * stateless request, then the behavior method is called with the method > name of > * the snippet (usually render, but there may be others if you specify a > method > * after the snippet name: MySnippet.dothing). > */ > trait StatelessBehavior { > /** > * Given the method name, return the transformation for the method > */ > def behaviorDispatch: PartialFunction[String, NodeSeq => NodeSeq] > }
> So it's like a DispatchSnippet
> On Tue, Aug 23, 2011 at 8:35 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
>> On Tue, Aug 23, 2011 at 10:56 PM, David Pollak < >> feeder.of.the.be...@gmail.com> wrote:
>>> On Tue, Aug 23, 2011 at 6:47 PM, Naftoli Gugenheim <naftoli...@gmail.com >>> > wrote:
>>>> Why bother with StatelessBehavior? Why not just an API to test if the >>>> current request is stateless?
>>> There's already an API to test. The problem is that wrapping an "if >>> (stateless) xxx else normal behavior" around lots of code takes a lot of >>> time and is error prone and messes up the code.
>> I hear that.
>>>> Also perhaps the parameterless def behavior should not have the empty >>>> parameter list?
>>> Then you get into the "is this a partially applied function or a method >>> call" quandary.
>> Oh, I see.
>> What is the advantage of DefaultStatelessBehavior -- that it saves the >> extra typing of >> def behavior*(method: String)* = ... ?
>> If so maybe one option to consider is just to make one trait with one >> method, and define it as >> def behavior: String => NodeSeq=>NodeSeq
>> This has two advantages: >> 1. If you don't care about the method name you can do >> def behavior = _ => "*" #> ... // very concise. >> 2. You can use pattern matching syntax: >> def behavior = { >> case "method1" => statelessMethod1 >> case _ => ClearNodes >> }
>> Actually the above reminds me of DispatchSnipet#dispatch, so we can throw >> in a third advantage: making it easier to remember how to use it, since it's >> similar to other Lift contstruct(s). Or, come to that, another possibility >> is to give it the same signature as dispatch. But then you lose #1 above >> (although it increases #3)...
>> Just some food for thought... :)
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
How about you go and update the names and any other method signatures that you think need improvement? I am less than optimal at naming and am happy to have improvements. On Aug 28, 2011 2:57 PM, "Naftoli Gugenheim" <naftoli...@gmail.com> wrote:
> Cool! > Sorry for being so perfectionist, but that makes me think it should be > called def statelessDispatch...
>> /** >> * Mix this snippet into any snippet. If the snippet is invoked in >> response to a >> * stateless request, then the behavior method is called with the method >> name of >> * the snippet (usually render, but there may be others if you specify a >> method >> * after the snippet name: MySnippet.dothing). >> */ >> trait StatelessBehavior { >> /** >> * Given the method name, return the transformation for the method >> */ >> def behaviorDispatch: PartialFunction[String, NodeSeq => NodeSeq] >> }
>> So it's like a DispatchSnippet
>> On Tue, Aug 23, 2011 at 8:35 PM, Naftoli Gugenheim <naftoli...@gmail.com >wrote:
>>> On Tue, Aug 23, 2011 at 10:56 PM, David Pollak < >>> feeder.of.the.be...@gmail.com> wrote:
>>>> On Tue, Aug 23, 2011 at 6:47 PM, Naftoli Gugenheim <
>>>>> Why bother with StatelessBehavior? Why not just an API to test if the >>>>> current request is stateless?
>>>> There's already an API to test. The problem is that wrapping an "if >>>> (stateless) xxx else normal behavior" around lots of code takes a lot of >>>> time and is error prone and messes up the code.
>>> I hear that.
>>>>> Also perhaps the parameterless def behavior should not have the empty >>>>> parameter list?
>>>> Then you get into the "is this a partially applied function or a method >>>> call" quandary.
>>> Oh, I see.
>>> What is the advantage of DefaultStatelessBehavior -- that it saves the >>> extra typing of >>> def behavior*(method: String)* = ... ?
>>> If so maybe one option to consider is just to make one trait with one >>> method, and define it as >>> def behavior: String => NodeSeq=>NodeSeq
>>> This has two advantages: >>> 1. If you don't care about the method name you can do >>> def behavior = _ => "*" #> ... // very concise. >>> 2. You can use pattern matching syntax: >>> def behavior = { >>> case "method1" => statelessMethod1 >>> case _ => ClearNodes >>> }
>>> Actually the above reminds me of DispatchSnipet#dispatch, so we can throw >>> in a third advantage: making it easier to remember how to use it, since it's >>> similar to other Lift contstruct(s). Or, come to that, another possibility >>> is to give it the same signature as dispatch. But then you lose #1 above >>> (although it increases #3)...
>>> Just some food for thought... :)
>>> -- >>> You received this message because you are subscribed to the Google Groups >>> "Lift" group. >>> To post to this group, send email to liftweb@googlegroups.com. >>> To unsubscribe from this group, send email to >>> liftweb+unsubscribe@googlegroups.com. >>> For more options, visit this group at >>> http://groups.google.com/group/liftweb?hl=en.
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to
diff --git a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala index 3d533e4..468cba2 100644 --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala @@ -173,29 +173,29 @@ trait DispatchSnippet { * the snippet (usually render, but there may be others if you specify a method * after the snippet name: MySnippet.dothing). */ trait [-StatelessBehavior-]{+*StatelessDispatch*+} { /** * Given the method name, return the transformation for the method */ def [-behaviorDispatch:-]{+*statelessDispatch*:+} PartialFunction[String, NodeSeq => NodeSeq]
}
/** * A simpler way to define behavior if the snippet is invoked. Just implement the behavior() method * and all methods for the snippet will use that behavior. */ trait [-DefaultStatelessBehavior-]{+*SimpleStatelessDispatch*+} extends [-StatelessBehavior-]{+*StatelessDispatch*+} { def [-behavior():-]{+*stateless*:+} NodeSeq => NodeSeq def [-behaviorDispatch:-]{+*statelessDispatch*:+} PartialFunction[String, NodeSeq => NodeSeq] = { case _ => [-behavior()-]{+*stateless*+} }
}
/** * A "default" implementation of [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and return a zero-length Text. */ trait [-BlankStatelessBehavior-]{+*BlankStatelessDispatch*+} extends [-StatelessBehavior-]{+*StatelessDispatch*+} { def [-behaviorDispatch:-]{+*statelessDispatch*:+} PartialFunction[String, NodeSeq => NodeSeq] = { case _ => [-ignore-]{+_+} => NodeSeq.Empty }
On Mon, Aug 29, 2011 at 5:26 AM, Naftoli Gugenheim <naftoli...@gmail.com> wrote: > Thoughts? > diff --git > a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > index 3d533e4..468cba2 100644 > --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > @@ -173,29 +173,29 @@ trait DispatchSnippet { > * the snippet (usually render, but there may be others if you specify a > method > * after the snippet name: MySnippet.dothing). > */ > trait [-StatelessBehavior-]{+StatelessDispatch+} { > /** > * Given the method name, return the transformation for the method > */ > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > NodeSeq => NodeSeq] > } > /** > * A simpler way to define behavior if the snippet is invoked. Just > implement the behavior() method > * and all methods for the snippet will use that behavior. > */ > trait [-DefaultStatelessBehavior-]{+SimpleStatelessDispatch+} extends > [-StatelessBehavior-]{+StatelessDispatch+} { > def [-behavior():-]{+stateless:+} NodeSeq => NodeSeq > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > NodeSeq => NodeSeq] = { > case _ => [-behavior()-]{+stateless+} > } > } > /** > * A "default" implementation of > [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and > return a zero-length Text. > */ > trait [-BlankStatelessBehavior-]{+BlankStatelessDispatch+} extends > [-StatelessBehavior-]{+StatelessDispatch+} { > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > NodeSeq => NodeSeq] = { > case _ => [-ignore-]{+_+} => NodeSeq.Empty > }
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
On Sun, Aug 28, 2011 at 8:26 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
> Thoughts?
I'm not keen on StatelessDispatch... because it's a behavior only in stateless mode. I think it would be confusing to people who would see it as a stateless counterpart to StatefulSnippets. Sorry... I guess I'm a better critic than I am a doer. What do others think? If I'm the only one seeing a likelihood of confusions, let's go with it. If there are a couple of other folks who see a likelihood of confusions, let's try a different name (not necessarily StatelessBehavior.)
> diff --git > a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > index 3d533e4..468cba2 100644 > --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > @@ -173,29 +173,29 @@ trait DispatchSnippet { > * the snippet (usually render, but there may be others if you specify a > method > * after the snippet name: MySnippet.dothing). > */ > trait [-StatelessBehavior-]{+*StatelessDispatch*+} { > /** > * Given the method name, return the transformation for the method > */ > def [-behaviorDispatch:-]{+*statelessDispatch*:+} > PartialFunction[String, NodeSeq => NodeSeq] > }
> /** > * A simpler way to define behavior if the snippet is invoked. Just > implement the behavior() method > * and all methods for the snippet will use that behavior. > */ > trait [-DefaultStatelessBehavior-]{+*SimpleStatelessDispatch*+} extends > [-StatelessBehavior-]{+*StatelessDispatch*+} { > def [-behavior():-]{+*stateless*:+} NodeSeq => NodeSeq > def [-behaviorDispatch:-]{+*statelessDispatch*:+} > PartialFunction[String, NodeSeq => NodeSeq] = { > case _ => [-behavior()-]{+*stateless*+} > } > }
> /** > * A "default" implementation of > [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and > return a zero-length Text. > */ > trait [-BlankStatelessBehavior-]{+*BlankStatelessDispatch*+} extends > [-StatelessBehavior-]{+*StatelessDispatch*+} { > def [-behaviorDispatch:-]{+*statelessDispatch*:+} > PartialFunction[String, NodeSeq => NodeSeq] = { > case _ => [-ignore-]{+_+} => NodeSeq.Empty > }
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
Good to know about --color-words (although of course it wouldn't work to paste into an email). I used --word-diff. (I don't know why tab completion doesn't know about it.)
On Mon, Aug 29, 2011 at 9:50 AM, Peter Brant <peter.br...@gmail.com> wrote: > Hi Naftoli,
> This is OT, but how are you generating that diff output? That's > pretty nifty (sort of like a b/w version of --color-words).
> Thanks,
> Pete
> On Mon, Aug 29, 2011 at 5:26 AM, Naftoli Gugenheim <naftoli...@gmail.com> > wrote: > > Thoughts? > > diff --git > > a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > > b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > > index 3d533e4..468cba2 100644 > > --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > > +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala > > @@ -173,29 +173,29 @@ trait DispatchSnippet { > > * the snippet (usually render, but there may be others if you specify a > > method > > * after the snippet name: MySnippet.dothing). > > */ > > trait [-StatelessBehavior-]{+StatelessDispatch+} { > > /** > > * Given the method name, return the transformation for the method > > */ > > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > > NodeSeq => NodeSeq] > > } > > /** > > * A simpler way to define behavior if the snippet is invoked. Just > > implement the behavior() method > > * and all methods for the snippet will use that behavior. > > */ > > trait [-DefaultStatelessBehavior-]{+SimpleStatelessDispatch+} extends > > [-StatelessBehavior-]{+StatelessDispatch+} { > > def [-behavior():-]{+stateless:+} NodeSeq => NodeSeq > > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > > NodeSeq => NodeSeq] = { > > case _ => [-behavior()-]{+stateless+} > > } > > } > > /** > > * A "default" implementation of > > [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and > > return a zero-length Text. > > */ > > trait [-BlankStatelessBehavior-]{+BlankStatelessDispatch+} extends > > [-StatelessBehavior-]{+StatelessDispatch+} { > > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > > NodeSeq => NodeSeq] = { > > case _ => [-ignore-]{+_+} => NodeSeq.Empty > > }
> > -- > > You received this message because you are subscribed to the Google Groups > > "Lift" group. > > To post to this group, send email to liftweb@googlegroups.com. > > To unsubscribe from this group, send email to > > liftweb+unsubscribe@googlegroups.com. > > For more options, visit this group at > > http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
No problem --- what do you say to this one? I.e., your trait names and my method names. Another possibility is "def statelessBehavior."
@@ -177,17 +177,17 @@ trait StatelessBehavior { /** * Given the method name, return the transformation for the method */ def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, NodeSeq => NodeSeq]
}
/** * A simpler way to define behavior if the snippet is invoked. Just implement the behavior() method * and all methods for the snippet will use that behavior. */ trait [-DefaultStatelessBehavior-]{+SimpleStatelessBehavior+} extends StatelessBehavior { def [-behavior():-]{+stateless:+} NodeSeq => NodeSeq def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, NodeSeq => NodeSeq] = { case _ => [-behavior()-]{+stateless+} }
}
@@ -195,7 +195,7 @@ trait DefaultStatelessBehavior extends StatelessBehavior { * A "default" implementation of StatelessBehavior. Just ignore everything and return a zero-length Text. */ trait BlankStatelessBehavior extends StatelessBehavior { def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, NodeSeq => NodeSeq] = { case _ => [-ignore-]{+_+} => NodeSeq.Empty }
> On Sun, Aug 28, 2011 at 8:26 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
>> Thoughts?
> I'm not keen on StatelessDispatch... because it's a behavior only in > stateless mode. I think it would be confusing to people who would see it as > a stateless counterpart to StatefulSnippets. Sorry... I guess I'm a better > critic than I am a doer. What do others think? If I'm the only one seeing > a likelihood of confusions, let's go with it. If there are a couple of > other folks who see a likelihood of confusions, let's try a different name > (not necessarily StatelessBehavior.)
>> diff --git >> a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> index 3d533e4..468cba2 100644 >> --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> @@ -173,29 +173,29 @@ trait DispatchSnippet { >> * the snippet (usually render, but there may be others if you specify a >> method >> * after the snippet name: MySnippet.dothing). >> */ >> trait [-StatelessBehavior-]{+*StatelessDispatch*+} { >> /** >> * Given the method name, return the transformation for the method >> */ >> def [-behaviorDispatch:-]{+*statelessDispatch*:+} >> PartialFunction[String, NodeSeq => NodeSeq] >> }
>> /** >> * A simpler way to define behavior if the snippet is invoked. Just >> implement the behavior() method >> * and all methods for the snippet will use that behavior. >> */ >> trait [-DefaultStatelessBehavior-]{+*SimpleStatelessDispatch*+} extends >> [-StatelessBehavior-]{+*StatelessDispatch*+} { >> def [-behavior():-]{+*stateless*:+} NodeSeq => NodeSeq >> def [-behaviorDispatch:-]{+*statelessDispatch*:+} >> PartialFunction[String, NodeSeq => NodeSeq] = { >> case _ => [-behavior()-]{+*stateless*+} >> } >> }
>> /** >> * A "default" implementation of >> [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and >> return a zero-length Text. >> */ >> trait [-BlankStatelessBehavior-]{+*BlankStatelessDispatch*+} extends >> [-StatelessBehavior-]{+*StatelessDispatch*+} { >> def [-behaviorDispatch:-]{+*statelessDispatch*:+} >> PartialFunction[String, NodeSeq => NodeSeq] = { >> case _ => [-ignore-]{+_+} => NodeSeq.Empty >> }
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
> No problem --- what do you say to this one? I.e., your trait names and my > method names. > Another possibility is "def statelessBehavior."
> @@ -177,17 +177,17 @@ trait StatelessBehavior { > /** > * Given the method name, return the transformation for the method > */ > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > NodeSeq => NodeSeq] > }
> /** > * A simpler way to define behavior if the snippet is invoked. Just > implement the behavior() method > * and all methods for the snippet will use that behavior. > */ > trait [-DefaultStatelessBehavior-]{+SimpleStatelessBehavior+} extends > StatelessBehavior { > def [-behavior():-]{+stateless:+} NodeSeq => NodeSeq > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > NodeSeq => NodeSeq] = { > case _ => [-behavior()-]{+stateless+} > } > }
> @@ -195,7 +195,7 @@ trait DefaultStatelessBehavior extends > StatelessBehavior { > * A "default" implementation of StatelessBehavior. Just ignore everything > and return a zero-length Text. > */ > trait BlankStatelessBehavior extends StatelessBehavior { > def [-behaviorDispatch:-]{+statelessDispatch:+} PartialFunction[String, > NodeSeq => NodeSeq] = { > case _ => [-ignore-]{+_+} => NodeSeq.Empty > }
> On Mon, Aug 29, 2011 at 11:48 AM, David Pollak < > feeder.of.the.be...@gmail.com> wrote:
>> On Sun, Aug 28, 2011 at 8:26 PM, Naftoli Gugenheim <naftoli...@gmail.com>wrote:
>>> Thoughts?
>> I'm not keen on StatelessDispatch... because it's a behavior only in >> stateless mode. I think it would be confusing to people who would see it as >> a stateless counterpart to StatefulSnippets. Sorry... I guess I'm a better >> critic than I am a doer. What do others think? If I'm the only one seeing >> a likelihood of confusions, let's go with it. If there are a couple of >> other folks who see a likelihood of confusions, let's try a different name >> (not necessarily StatelessBehavior.)
>>> diff --git >>> a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >>> b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >>> index 3d533e4..468cba2 100644 >>> --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >>> +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >>> @@ -173,29 +173,29 @@ trait DispatchSnippet { >>> * the snippet (usually render, but there may be others if you specify a >>> method >>> * after the snippet name: MySnippet.dothing). >>> */ >>> trait [-StatelessBehavior-]{+*StatelessDispatch*+} { >>> /** >>> * Given the method name, return the transformation for the method >>> */ >>> def [-behaviorDispatch:-]{+*statelessDispatch*:+} >>> PartialFunction[String, NodeSeq => NodeSeq] >>> }
>>> /** >>> * A simpler way to define behavior if the snippet is invoked. Just >>> implement the behavior() method >>> * and all methods for the snippet will use that behavior. >>> */ >>> trait [-DefaultStatelessBehavior-]{+*SimpleStatelessDispatch*+} extends >>> [-StatelessBehavior-]{+*StatelessDispatch*+} { >>> def [-behavior():-]{+*stateless*:+} NodeSeq => NodeSeq >>> def [-behaviorDispatch:-]{+*statelessDispatch*:+} >>> PartialFunction[String, NodeSeq => NodeSeq] = { >>> case _ => [-behavior()-]{+*stateless*+} >>> } >>> }
>>> /** >>> * A "default" implementation of >>> [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and >>> return a zero-length Text. >>> */ >>> trait [-BlankStatelessBehavior-]{+*BlankStatelessDispatch*+} extends >>> [-StatelessBehavior-]{+*StatelessDispatch*+} { >>> def [-behaviorDispatch:-]{+*statelessDispatch*:+} >>> PartialFunction[String, NodeSeq => NodeSeq] = { >>> case _ => [-ignore-]{+_+} => NodeSeq.Empty >>> }
>>> -- >>> You received this message because you are subscribed to the Google Groups >>> "Lift" group. >>> To post to this group, send email to liftweb@googlegroups.com. >>> To unsubscribe from this group, send email to >>> liftweb+unsubscribe@googlegroups.com. >>> For more options, visit this group at >>> http://groups.google.com/group/liftweb?hl=en.
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.
On Tue, Aug 30, 2011 at 5:16 AM, Naftoli Gugenheim <naftoli...@gmail.com> wrote: > Good to know about --color-words (although of course it wouldn't work to > paste into an email). > I used --word-diff. (I don't know why tab completion doesn't know about it.)
> On Mon, Aug 29, 2011 at 9:50 AM, Peter Brant <peter.br...@gmail.com> wrote:
>> Hi Naftoli,
>> This is OT, but how are you generating that diff output? That's >> pretty nifty (sort of like a b/w version of --color-words).
>> Thanks,
>> Pete
>> On Mon, Aug 29, 2011 at 5:26 AM, Naftoli Gugenheim <naftoli...@gmail.com> >> wrote: >> > Thoughts? >> > diff --git >> > a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> > b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> > index 3d533e4..468cba2 100644 >> > --- a/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> > +++ b/web/webkit/src/main/scala/net/liftweb/http/StatefulSnippet.scala >> > @@ -173,29 +173,29 @@ trait DispatchSnippet { >> > * the snippet (usually render, but there may be others if you specify a >> > method >> > * after the snippet name: MySnippet.dothing). >> > */ >> > trait [-StatelessBehavior-]{+StatelessDispatch+} { >> > /** >> > * Given the method name, return the transformation for the method >> > */ >> > def [-behaviorDispatch:-]{+statelessDispatch:+} >> > PartialFunction[String, >> > NodeSeq => NodeSeq] >> > } >> > /** >> > * A simpler way to define behavior if the snippet is invoked. Just >> > implement the behavior() method >> > * and all methods for the snippet will use that behavior. >> > */ >> > trait [-DefaultStatelessBehavior-]{+SimpleStatelessDispatch+} extends >> > [-StatelessBehavior-]{+StatelessDispatch+} { >> > def [-behavior():-]{+stateless:+} NodeSeq => NodeSeq >> > def [-behaviorDispatch:-]{+statelessDispatch:+} >> > PartialFunction[String, >> > NodeSeq => NodeSeq] = { >> > case _ => [-behavior()-]{+stateless+} >> > } >> > } >> > /** >> > * A "default" implementation of >> > [-StatelessBehavior.-]{+StatelessDispatch.+} Just ignore everything and >> > return a zero-length Text. >> > */ >> > trait [-BlankStatelessBehavior-]{+BlankStatelessDispatch+} extends >> > [-StatelessBehavior-]{+StatelessDispatch+} { >> > def [-behaviorDispatch:-]{+statelessDispatch:+} >> > PartialFunction[String, >> > NodeSeq => NodeSeq] = { >> > case _ => [-ignore-]{+_+} => NodeSeq.Empty >> > }
>> > -- >> > You received this message because you are subscribed to the Google >> > Groups >> > "Lift" group. >> > To post to this group, send email to liftweb@googlegroups.com. >> > To unsubscribe from this group, send email to >> > liftweb+unsubscribe@googlegroups.com. >> > For more options, visit this group at >> > http://groups.google.com/group/liftweb?hl=en.
>> -- >> You received this message because you are subscribed to the Google Groups >> "Lift" group. >> To post to this group, send email to liftweb@googlegroups.com. >> To unsubscribe from this group, send email to >> liftweb+unsubscribe@googlegroups.com. >> For more options, visit this group at >> http://groups.google.com/group/liftweb?hl=en.
> -- > You received this message because you are subscribed to the Google Groups > "Lift" group. > To post to this group, send email to liftweb@googlegroups.com. > To unsubscribe from this group, send email to > liftweb+unsubscribe@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/liftweb?hl=en.