Lift Weekly Recap 3: Merges, Roundtrip boolean returns, and more

89 views
Skip to first unread message

Antonio Salazar Cardozo

unread,
Jan 25, 2014, 6:10:41 PM1/25/14
to lif...@googlegroups.com
Round 3 of this series, later still than the previous one. I'm hoping to do the 4th
weekly recap in the next few days so I don't end up missing a week ;) Still playing
the ML post game, as I've been swamped and have had no time to dedicate to
setting up a proper site to put these on.

As an ongoing rule, if you have any ideas for things that might be mentioned in
something like this, drop me a line at savedfastcool AT gmail.com !

We're still in the long-term recap phase where we're running through changes
that have gone into Lift 2.6 and Lift 3 over the past few months, but we've also
got some updates from this week to cover today!

First off, the master branch was merged into lift_30. For most people this doesn't
make a big difference, as the two had been kept synced via commit cherry-picks
and a few other strategies since the very beginning of Lift 3 development. However,
this makes the master...lift_30 diff much more accurate, both when it comes to the
list of commits on the lift_30 branch and when it comes to the actual changes on
the lift_30 branch. That makes my life easier when putting together these
summaries, amongst other things :)

On a related note, the committer team has agreed to rely more on merges for
integrating work between the master and lift_30 branches, and when integrating
feature branches into either of those two main development branches. This is
a generalization of a decision we'd already made when we decided to allow limited
non-committer contributions a few months back.

The second change that landed in Lift 3 this week was a fix for an issue where
roundtrip promises could not return booleans to the client. This was due to how
failures were detected on the client side, and antidata was kind enough to provide
a fix in pull request 1514 (original discussion in this mailing list thread).

Now let's take a step back in time and continue our recap of Lift 3 changes and
updates.

As a starter, AnyVar, which is the shared trait that underlies RequestVar, SessionVar,
TransientRequestVar, ContainerVar, etc, used to have a setIsUnset function. That
was a typo, and should have been setIfUnset. Calling setIfUnset with a value will
set the given var to that value only if it wasn't previously set in its current scope.
So, for example, calling setIfUnset(35) on a RequestVar[Int] would only set it to
35 if it hadn't been set to anything else at another point in the current request lifetime
(which includes followup Lift AJAX requests), while on a SessionVar it would happen
if it hadn't been set at another point in the current session. We'll be deprecating setIsUnset
in Lift 2.6 (really soon), but it'll be gone in Lift 3, so you'll have to update any code that
calls setIsUnset to correctly call setIfUnset.

AnyVar also got an onChange property. You can add functions to this and they will
be called whenever the var's value is changed. The function takes a Box[T], which is
the value that is being set on the var, and a Boolean, which indicates if the var is
being reset to its default value. This is to distinguish between someone setting the
value to some value and Lift setting the var to the default you specified when defining
it, which will also be passed to this function as a Full Box.

It's expected that onChange will be set either at Boot or when you define the
Var, and the onChange variable is not thread-safe, so you should be careful of where
you set it.

Here's an example:

object UserInfo extends Loggable {
object userId extends SessionVar[Box[String]](Empty)
userId.onChange { (newValue: Box[Box[String]], resettingToDefault: Boolean) =>
newValue.map { updatedValue =>
if (resettingToDefault)
logger.info("User id requested while unset, defaulting to " + updatedValue)
else
logger.info("Setting user id to " + updatedValue)
} openOr {
logger.info("Clearing user id.")
}
}
}
 
userId.is // logs User id requested while unset, defaulting to Empty
userId.is // no log statement
userId(Full("abfd-1428")) // logs Setting user id to Full("abfd-1428")
userId(Full("fdea-8498")) // logs Setting user id to Full("fdea-8498")
userId(Empty) // logs Setting user id to Empty
userId.is // no log statement
userId.clear // logs Clearing user id.
userId.is // logs User id requested while unset, defaulting to Empty

In BasicTypesHelper in both Lift 2.6 and Lift 3, using toBoolean converts the string "on"
to a true value. Before, "on" converted to false because it was unrecognized. Note that
BasicTypesHelper functions are available wherever you've imported
net.liftweb.util.Helpers._ .

Back to Lift 3 only, BindHelpers, which is also included in Helpers._, now has a
removeAttribute helper function. You pass it an Elem and the name of an attribute you
want removed and it returns the Elem without that attribute:

val myElem = <this has="too" many="attributes">Am I right?</this>
removeAttribute("many", myElem) // => <this has="too">Am I right?</this>

A very old relic, MappedLongForeignKey had a can method that returned a Full with the
Long value of the key if it was defined, or an Empty if that key wasn't defined. This was
a leftover from the days when the Box trait was called Can, way back in the day. This
method was deprecated in favor of the box method, which does the same thing but has
a name that fits with the rest of the framework. In Lift 3, the can method is gone altogether,
so you'll have to update any code that was using it to use box instead.

For more resilience, CometActor now waits 1s longer than the lifeSpan before deciding
a comet is dead on the client. This helps the comet actor adhere to the lifeSpan you specify
without exploding unexpectedly because of transient connection loss, though it does mean
it's slightly less accurate.

We'll stop there for this week, but there's plenty more to come. As I said, look for the
4th weekly recap in the next few days; I've already done most of the research for it, just
need to get it written up. Hopefully we'll have gotten a pending fix to MockHttpServletRequest
pulled in by then as well! Either way, we'll look at a new resource management trait in Lift 3,
some tweaks to host name resolution in Props, and a few cleanups that have happened.

David Barri

unread,
Jan 26, 2014, 5:32:14 PM1/26/14
to lif...@googlegroups.com
Nice. Thanks for another update!

Richard Dallaway

unread,
Jan 27, 2014, 5:37:50 AM1/27/14
to Lift
+1 These updates are fantastic. Thank you.




On 26 Jan 2014 22:32:14, David Barri <japg...@gmail.com> wrote:
Nice. Thanks for another update!
--
--
Lift, the simply functional web framework: http://liftweb.net
Code: http://github.com/lift
Discussion: http://groups.google.com/group/liftweb
Stuck? Help us help you: https://www.assembla.com/wiki/show/liftweb/Posting_example_code
 
---
You received this message because you are subscribed to the Google Groups "Lift" group.
To unsubscribe from this group and stop receiving emails from it, send an email to liftweb+u...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Peter Petersson

unread,
Jan 27, 2014, 8:13:46 AM1/27/14
to lif...@googlegroups.com

Thanks Antonio really great stuff as always.

best regards
  Peter Petersson
if< /span> (resettingToDefault)

Tyler Weir

unread,
Jan 27, 2014, 10:30:09 AM1/27/14
to lif...@googlegroups.com
+2 These updates are fantastic.

Antonio Salazar Cardozo

unread,
Jan 27, 2014, 3:48:40 PM1/27/14
to lif...@googlegroups.com
Thanks guys, glad you're enjoying them! :)
Antonio
Reply all
Reply to author
Forward
0 new messages