Yesod Hamlet type error in for all loop is confusing - yesod

I have a Yesod handler that is returning a list of type [(Category, [Product])] I am trying to loop through this in my hamlet template.
$if null rows
<p>No products
$else
<div class="list-group menu">
$forall (category, products) <- rows
<h4>#{categoryName category}
$forall product <- products
<p>#{productName product} - #{productPrice product}</p>
When I compile though I get the error message:
Handler/Menu.hs:11:7:
Couldn't match type ‘[(Category, [Product])]’
with ‘(Category, t0 Product)’
Expected type: ReaderT SqlBackend m1 (Category, t0 Product)
Actual type: ReaderT SqlBackend m1 [(Category, [Product])]
In the second argument of ‘Data.Foldable.mapM_’, namely ‘rows’
In a stmt of a 'do' block:
Data.Foldable.mapM_
(\ (category_aiv7, products_aiv8)
-> do { (asWidgetT GHC.Base.. toWidget)
((blaze-markup-0.7.0.3:Text.Blaze.Internal.preEscapedText
GHC.Base.. Data.Text.pack)
"<div class=\"list-group-item\"><h4 class=\"list-group-item-heading\">");
(asWidgetT GHC.Base.. toWidget)
(toHtml (categoryName category_aiv7));
.... })
rows
I don't understand why it is expecting this and what I can do to make it work. Many Thanks.
Update:
My handler.
getMenuR :: Handler Html
getMenuR = do
let rows = query
defaultLayout $ do
$(widgetFile "menu")
query = do
cats <- selectList [] [Asc CategoryName]
forM cats $ \(Entity catId cat) -> do
products <- selectList
[ProductCategory ==. catId]
[Asc ProductName]
return (cat, map entityVal products)

After the help from Michael it is as easy as replacing let rows = query with rows <- runDB query

Related

How to filter query result to list of strings

I have a query result same as below:
var ptns = from p in db.Patients
select p;
This query returns a list of patients, but I need to filter the result based on DoctorNameID. The DoctorNameID should be in list of doctors as below:
List<string> listofDoctors = usrtodrs.Split(',').ToList();
I have searched a lot but I don't know how to do this. I have tested this query which doesn't work:
var ptns1 = from d in listofDoctors
join p in ptns.ToList() on d equals p.DoctorNameID
select p;
And also this query:
var ptns1 = ptns.ToList()
.Where(a => listofDoctors.Equals(a.DoctorNameID))
.ToList();
Any help?
You can use Contains extension and get the desired result.
var ptns1 = ptns.Where(x => listofDoctors.Contains(x.DoctorNameID)).ToList();
Refer the C# Fiddle with sample data.

Slick: Is there a way to create a WHERE clause with a regex?

I look for a slick equivalient to
select * from users where last_name ~* '[\w]*son';
So for example when having the following names in the database:
first_name | last_name
----------------------
Tore | Isakson
John | Smith
Solveig | Larsson
Marc | Finnigan
The result would be
first_name | last_name
----------------------
Tore | Isakson
Solveig | Larsson
My current solution is to interpolate this with an SQLActionBuilder like
val pattern = "[\\w]*son"
val action = sql""" SELECT * FROM users WHERE last_name ~* ${pattern}; """.as[User]
But this is not the way I would like to have it. I would prefer something like
users.filter(_.last_name matchRegex "[\\w]*son") // <- This does not exist
In case it is relevant: I use Postgres.
(This answer is following the question in Slick: How can I combine a SQL LIKE statement with a SQL IN statement)
Although Slick doesn't support the ~* operator out of the box, you can add it yourself. That would give you a way to execute the query using the lifted embedded style of Slick query.
To do that, you can use the SimpleExpression builder. There's not much documentation on it, but the jumping off point would be the Scalar Database Functions page of the reference manual.
What we want to do is write a method along these lines:
def find(names: Seq[String]): DBIO[Seq[String]] = {
val pattern = names.mkString("|")
users.filter(_.lastName regexLike pattern).map(_.lastName).result
}
To get regexLike we can use a enrich (enhance, "pimp") a string column to have the regexLike method:
implicit class RegexLikeOps(s: Rep[String]) {
def regexLike(p: Rep[String]): Rep[Boolean] = {
val expr = SimpleExpression.binary[String,String,Boolean] { (s, p, qb) =>
qb.expr(s)
qb.sqlBuilder += " ~* "
qb.expr(p)
}
expr.apply(s,p)
}
}
The implicit class part is allow the compiler to construct the RegexLikeOps class anytime it has a Rep[String] that calls a method that Rep[String] doesn't already have (i.e., when regexLike is asked for).
Our regexLike method takes another Rep[String] argument as the pattern, and then uses SimpleExpression builder to safely construct the SQL we want to use.
Putting it all together we can write:
val program = for {
_ <- users.schema.create
_ <- users ++= User("foo") :: User("baz") :: User("bar") :: Nil
result <- find( Seq("baz","bar") )
} yield result
println( Await.result(db.run(program), 2.seconds) )
The SQL generated (in my test with H2) is:
select "last_name" from "app_user" where "last_name" ~* 'baz|bar'
The full code is: https://github.com/d6y/so46199828

Spark - remove special characters from rows Dataframe with different column types

Assuming I've a Dataframe with many columns, some are type string others type int and others type map.
e.g.
field/columns types: stringType|intType|mapType<string,int>|...
|--------------------------------------------------------------------------
| myString1 |myInt1| myMap1 |...
|--------------------------------------------------------------------------
|"this_is_#string"| 123 |{"str11_in#map":1,"str21_in#map":2, "str31_in#map": 31}|...
|"this_is_#string"| 456 |{"str12_in#map":1,"str22_in#map":2, "str32_in#map": 32}|...
|"this_is_#string"| 789 |{"str13_in#map":1,"str23_in#map":2, "str33_in#map": 33}|...
|--------------------------------------------------------------------------
I want to remove some characters like '_' and '#' from all columns of String and Map type
so the result Dataframe/RDD will be:
|------------------------------------------------------------------------
|myString1 |myInt1| myMap1|... |
|------------------------------------------------------------------------
|"thisisstring"| 123 |{"str11inmap":1,"str21inmap":2, "str31inmap": 31}|...
|"thisisstring"| 456 |{"str12inmap":1,"str22inmap":2, "str32inmap": 32}|...
|"thisisstring"| 789 |{"str13inmap":1,"str23inmap":2, "str33inmap": 33}|...
|-------------------------------------------------------------------------
I am not sure if it's better to convert the Dataframe into an RDD and work with it or perform the work in the Dataframe.
Also, not sure how to handle the regexp with different column types in the best way (I am sing scala).
And I would like to perform this action for all column of these two types (string and map), trying to avoid using the column names like:
def cleanRows(mytabledata: DataFrame): RDD[String] = {
//this will do the work for a specific column (myString1) of type string
val oneColumn_clean = mytabledata.withColumn("myString1", regexp_replace(col("myString1"),"[_#]",""))
...
//return type can be RDD or Dataframe...
}
Is there any simple solution to perform this?
Thanks
One option is to define two udfs to handle string type column and Map type column separately:
import org.apache.spark.sql.functions.udf
val df = Seq(("this_is#string", 3, Map("str1_in#map" -> 3))).toDF("myString", "myInt", "myMap")
df.show
+--------------+-----+--------------------+
| myString|myInt| myMap|
+--------------+-----+--------------------+
|this_is#string| 3|Map(str1_in#map -...|
+--------------+-----+--------------------+
1) Udf to handle string type columns:
def remove_string: String => String = _.replaceAll("[_#]", "")
def remove_string_udf = udf(remove_string)
2) Udf to handle Map type columns:
def remove_map: Map[String, Int] => Map[String, Int] = _.map{ case (k, v) => k.replaceAll("[_#]", "") -> v }
def remove_map_udf = udf(remove_map)
3) Apply udfs to corresponding columns to clean it up:
df.withColumn("myString", remove_string_udf($"myString")).
withColumn("myMap", remove_map_udf($"myMap")).show
+------------+-----+-------------------+
| myString|myInt| myMap|
+------------+-----+-------------------+
|thisisstring| 3|Map(str1inmap -> 3)|
+------------+-----+-------------------+

How do I render a Map data structure in an Ember template?

I use Ember 2.8. There exists Map data structure in Ember. It should be iterable. However there's no examples how to enumerate through it and render it.
Assuming that both keys and values in my map are JS objects that have some 'name' set, I tried in Emblem:
each myMap.keys as |key|
p = key.name
each myMap.values as |value|
p = value.name
/ each myMap as |key, value| //this one causes build error
/ p = key.name
/ p = value.name
None of these syntaxes seem to work and render something more than 'undefined' empty space.
Do any of you know how to render a Map in Ember?
Turns out it was enough to use native JS Map.
My Map ended up using pairs Object: Array[Object].
In Emblem template:
each myMap as |value key| // <--- notice the order!
p {{key.name}}
p {{key.date}}
each value as |item| // values from map are arrays so I enumerate through them as well
p {{item.name}}
p {{item.details}}
In controller:
myMap: function() {
var myMap = new Map();
myMap.set(
{name: 'keyname', date: 'keydate'},
[{name: 'itemname', details: 'itemdetails'}, {name: 'itemname2', etails: 'itemdetails2'}]
);
// ... etc set more pairs
return myMap;
}.property();
Are you looking for something like each-in helper?
Usage:
{{#each-in obj as |key value|}}
{{key}}:{{value}}<br>
{{/each-in}}
Have a look at this sample demo.

How to render list in elm?

I have a hard time to render List of custom types within the view function.
This is the model:
type alias Guid = String
type alias User = String
type alias TaxonomyCategory =
{ id : Guid
, name: String
, updatedAt: Date
, updatedBy: User
, terms: List TaxonomyTerm
}
type TaxonomyTerm =
TaxonomyTerm
{ id : Guid
, name: String
, terms: List TaxonomyTerm
}
I tried several approaches with List.map function but I always ended up with some kind of error message.
The 2nd argument to function `ul` is causing a mismatch.
120| ul
121| []
122|> [ List.map renderTaxonomyTerm tc.terms ]
Function `ul` is expecting the 2nd argument to be:
List (VirtualDom.Node a)
But it is:
List (List (Html a))
The second parameter of ul should be a list of Html elements. Your second value contains a list within a list since you surrounded it with brackets. Changing it to this should fix your problem:
ul
[]
(List.map renderTaxonomyTerm tc.terms)
For using ul see previous answer. Thanks to Chad.
I have an addition. You can't create recursive records. You should create structure like type TaxonomyTerm = TaxonomyTerm Guid String (List TaxonomyTerm).