The new percolator is to be loaded in the following ratio:
1/8 cup (metal scoop) per 2 cups water.
Review pending.
The new percolator is to be loaded in the following ratio:
1/8 cup (metal scoop) per 2 cups water.
Review pending.
The MappedEmail class does not take kindly to blank submissions in it’s default form, however with a simple override you can retain all the goodness of the validations built into MappedEmail, while ignoring these requirements if there is no value submitted:
object emailAddress extends MappedEmail(this, 100) {
override def validate = if (this.is == "") Nil else super.validate
}
Open up your preferences, and go to your SBT settings. You want to add this to your VM Parameters: “-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005″
Now to debug, you need to create a new debugging profile of type “Remote”
And make sure that it is running with your sbt debug line ” -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005″, and verify that the settings are set to transport:socket, debugger mode: Attach, and host:localhost on port 5005.
Set breakpoints and enjoy.
Lift provides built in snippets to allow easy pagination of data. Here is a brief reference for the SortedMapperPaginatorSnippet (SMPS henceforth). As you can tell from the name, it specifically allows sorted pagination of mapper data.
The Lift documentation provides more general information on PaginatorSnippets here.
Let’s say you have a snippet called listProducts. You’d like listProducts to display a sorted pagination of all your products, which are stored in your database. Of course, you’ve already created Mapper classes to relate to the data. The very first thing to do is add a couple of imports to your snippet:
import net.liftweb.mapper.{By, OrderBy, MaxRows, Like,Cmp,NotNullRef,NullRef, QueryParam, StartAt, Ascending, Descending}
import net.liftweb.mapper.view.{MapperPaginatorSnippet, SortedMapperPaginatorSnippet}
Now let’s create the paginator.
val paginator = new SortedMapperPaginatorSnippet(Product, Product.createdAt, “createdAt” -> Product.createdAt, “price” -> Product.price) {
}
The first argument sets the mapper class we are querying. The next one specifies the column we want to sort by initially. Finally we have the two columns we will allow the user to sort by. These are actually both part of the third argument, but thanks to scala’s repeated parameters, we can have as many choices as we’d like. The third argument(s) should be pair(s) of column labels [String] and MappedFields.
Now let’s say we want to add some custom query criteria. For example, let’s only return products who have their inStock field set to true. To do this, we must set the constantParams var that is built into SMPS. This variable takes the format of a Seq[QueryParam]. So inside our paginator, add the following code:
var params: List[net.liftweb.mapper.QueryParam[Product]] = Nil
params = By(Product.inStock, true) :: Nil
constantParams = params
The first line sets up the Seq[QueryParam] format of the variable. Then, we set the list to have 2 elements: first is a By QueryParam and second is a Nil. If we had set the variable to just the QueryParam, then Scala would have changed the variable type to QueryParam. By prepending a Nil to the end, it maintains its status as a sequence of elements. The By param takes two arguments. First is the Mapper field to check and second is the value it must be. So in this case, we are checking the inStock is true. Finally set constantParams equal to params. This adds our custom query to the SMPS’s logic.
This is all you need to do to set up an SMPS in a snippet. To add it to a template, you need to bind each page to something in the xhtml. An example of how to do this would be to add this code to the snippet (outside of the paginator!):
def all(xhtml: NodeSeq) : NodeSeq = paginator.page.flatMap(a => bind(“p”,xhtml,”createdAt” -> a.createdAt, “price” -> a.price, “inStock” -> a.inStock))
Paginator creates a “page” that is essentially a list of Products that is sorted and offset based on which page the user has selected. The code above simply binds each product in the paginator.page to some xhtml code. We could use this on a Lift template like this:
<lift:listProducts.paginator.paginate>
<tr><th><sort:createdAt /></th><th><sort:price /></th></tr>
</lift:listProducts.paginator.paginate><lift:listProducts.all>
<tr><td><p:createdAt /></td><td><p:price /></td><td><p:inStock /></td></tr>
</lift:listProducts.all>
<lift:listProducts.paginator.paginate> <nav:first/> | <nav:prev/> | <nav:allpages/> | <nav:next/> | <nav:last/> | <nav:records/>
</lift:listProducts.paginator.paginate>
Note that all of the tags inside both the <lift:listProducts.paginator.paginate> areas are built into SMPS, which the code inside <lift:listProducts.all> is populated by the custom all function we defined above. Also note that all this can (and should) be customized for your own needs.
A final point about SMPS is that the current sort field, offset, and sort order can all be set by url query strings:
paginatorpage?sort=0 would cause our SMPS above to sort by the createdAt field. sort=1 would cause it to sort by price.
paginatorpage?offset=100 would cause our SMPS’s current page to start at record 100.
paginatorpage?asc=false would cause our SMPS to sort in descending order.
Of course these can be combined such as: paginatorpage?sort=1&asc=true
Before you start this tutorial, make sure you have the following handy:
Once you are ready, go to your iPhone home screen and tap the Settings icon.
In settings, scroll to and tap Mail, Contacts, Calendars
Tap Add Account
Tap Other
At this next screen, you will need to enter the name you want associated with your email account. The sample image below uses “Morroni Technologies” but you can enter anything you want.
For the Address and Password please enter the email address and password you were provided with.
Tap Next when finished.
The next step is to set up the Incoming/Outgoing mail servers. First, set up the Incoming Mail Server (IMAP).
Now, scroll down to set up the Outgoing Mail Server (SMTP).
Scroll down and tap Mail, Contacts, Calendars. Tap your newly created account in the list as shown below. Again, it will be labelled with either your email address or, your description if you entered one.
You will arrive at the account settings screen pictured below. Tap the account under IMAP.
Scroll to the bottom of this screen and tap Advanced.
Tap Drafts Mailbox
Scroll to the On The Server list and select Drafts.
Tap the Advanced button in the upper left corner of the screen.
Tap Sent Mailbox.
Scroll to the On The Server list and select Sent.
Tap the Advanced button in the upper left corner of the screen.
Tap Deleted Mailbox.
Scroll to the On The Server list and select Trash.
At this point, you are ready to use the iPhone Mail app with your Morroni Email account. Simply press the home button and tap the Mail app to begin!
I’ve been searching for the ideal startup process when building a lift project and I might have just found it!
I am using simple-build-tool(sbt) and two sbt processors. The processors are:
lifty: http://lifty.github.com/Lifty/
sbt-idea: https://github.com/mpeltonen/sbt-idea
Here are the steps:
amore:wheels lmorroni$ sbt
Project does not exist, create new project? (y/N/s) y
Name: appName
Organization: com.morroni
Version [1.0]:
Scala version [2.7.7]: 2.8.1
sbt version [0.7.4]:
...
>*lifty is org.lifty lifty 1.6
>*sbtIdeaRepo at http://mpeltonen.github.com/maven/
>*idea is com.github.mpeltonen sbt-idea-processor 0.3.0
>lifty create project-blank with user
>reload
>update
>idea
>~jetty-run
References:
http://lifty.github.com/Lifty/
https://github.com/mpeltonen/sbt-idea
If you’re developing lift in IntelliJ, often you get popup inspector errors all over your XHTML markup because the namespaces of your snippet classes, etc. are not valid. To turn it off, you can click on the inspector in the bottom right of the intelliJ window, Configure Inspections, and turn off that specific XML setting inspection in the XML options. Nothing huge, but it saves some annoyance.
This may not seem like a difficult task for many of the more experienced Scala/Lift developers out there but it took me some time to write this little piece and I thought I would share it.
I basically needed a way to redirect clients running IE6 to a single page which explained that the site does not support their browser and here is how to upgrade. To do this, I used the LiftRules object’s dispatch field inside the boot.scala file. Here’s the line of code:
LiftRules.dispatch.prepend {
case Req(path, _, _) if (path != List("unsupported-browser") && S.request.dmap(false)(_.isIE6)) => () => {Full(RedirectResponse("unsupported-browser"))}
}
So I showed this line to my co-worker, Jeff, and his eyes almost popped out of his head. I am digging Scala and Lift and I do see the power once I get a grasp on the syntax. However, ramping up in this language is no small task. It has actually been quite difficulty for me and while I may not be the sharpest developer in the world, I think I am relatively capable. Anyway, enough of a rant. Here’s what is going on above. If any Scala masters are reading this and want to correct my explanation, please feel free.
We are prepending a new rule to the dispatch field. The format of the case statement is basically case pattern if guard => {/*do something*/}
The part that I got stuck on was binding a variable in the pattern that could be used in the guard. So here’s how it breaks down.
Pattern: Req(path, _, _)
This grabs the current dispatch request and binds the path variable to the current path list.
Guard: if (path != List("unsupported-browser") && S.request.dmap(false)(_.isIE6))
The guard takes the binded path variable and checks to make sure it is any single path on the site EXCEPT the /unsupported-browser path. That is an important part since we do not want a infinite loop redirect. The second half of the guard takes the current session request box and uses dmap to open it and check if the current browser is indeed ie6.
Action: If the pattern and guard are satisfied then we do a redirect to the unsupported browser page.
Hopefully some people find this information useful.
Update: This is easier now. See this post: http://blog.morroni.com/2011/03/11/the-best-lift-sbt-intellij-startup-process/
This post describes how to get IntelliJ, Git, SBT(Scala Build Tool) and Lift playing nicely together. This post assumes you have Maven and SBT already installed since you will need them in order to make this work. More information about the sbt setup is here: http://code.google.com/p/simple-build-tool/wiki/Setup. Information about installing maven is available here: http://maven.apache.org/run-maven/index.html
Install GIT
bash$ cd /Volumes/Git\ 1.6.4.4\ Intel\ Leopard/bash$ ./setup\ git\ PATH\ for\ non-terminal\ programs.shgit and confirm it is installed.Download archetype
mvn archetype:generate -U \
-DarchetypeGroupId=net.liftweb \
-DarchetypeArtifactId=lift-archetype-basic \
-DarchetypeVersion=2.0 \
-DremoteRepositories=http://scala-tools.org/repo-releases \
-Dversion=0.1 \
-DgroupId=com.myCompany.myProject -DartifactId=myProjectOpen IntelliJ
I did a pretty verbose post on using IntelliJ with lift here: http://blog.morroni.com/2010/07/14/setup-intellij-9-for-lift-framework-development/. This assumes you have installed the Scala and SBT plugins in IntelliJ.
import sbt._
class LiftProject(info: ProjectInfo) extends DefaultWebProject(info) {
val liftVersion = "2.0"
override def libraryDependencies = Set(
"net.liftweb" % "lift-webkit" % liftVersion % "compile->default",
"net.liftweb" % "lift-mapper" % liftVersion % "compile->default",
"org.mortbay.jetty" % "jetty" % "6.1.22" % "test->default",
"junit" % "junit" % "4.5" % "test->default",
"org.scala-tools.testing" % "specs" % "1.6.2.1" % "test->default",
"com.h2database" % "h2" % "1.2.138"
) ++ super.libraryDependencies
}
sbt ~jetty-runI am making an assumption here that you already know the normal forward-usage of the patch command. If you’re unversed In case you didn’t want to decipher the entire man page just yet, you’re in luck. I came across an instance where I had to remove a previous patch file from the Magento Enterprise code-base. The patch was originally applied as so:
patch -p0 < firstpatch.patch
Problems ensued, and I was given a new patch, however it was a cumulative patch so it couldn’t be laid over the first patch. So how to remove? After a man-page reading, it’s quite a breeze. You need the original patch to be removed, and use the patch number you used in the first patching instance. In this case it equates to the following:
patch -R -p0 < firstpatch.patch
now you can add the new patch.
patch -p0 < secondpatch.patch
Hopefully this will save someone a man-page reading on a small terminal in a dimly lit server room.