IHP - How to use Select Inputs with Nullable Enums in HSX Forms? - ihp

Given an enum:
CREATE TYPE CONTENT_TYPE AS ENUM ('video', 'article', 'audio');
How should I update the my HSX Form selectField to support Maybe ContentType?
formFor subscription [hsx|
{selectField #contentType allContentTypes}
|]
where
allContentTypes = allEnumValues #ContentType
The CanSelect instance is defined as follows:
instance CanSelect (Maybe ContentType) where
type SelectValue (Maybe ContentType) = Maybe ContentType
selectValue (Just value) = Just value
selectValue Nothing = Nothing
selectLabel (Just groupType) = tshow contentType
selectLabel Nothing = "none selected"

Your CanSelect instance looks correct. The list of allContentTypes should have a type of [Maybe ContentType]. You can wrap the content types with a Just constructor by mapping it over the list: e.g. fmap Just allContentTypes and passing the wrapped list to selectField.

Related

Data class .copy only if nullable parameter is not null

I have a Front-End application that sends me Data to update my User (updatedUser). Since I don't want to send the whole Userdata, I'm only sending the data that has changed. Now I want to Update my Userdata with the changes provided, so I'd like to know if there is a more elegant way to do this than just a list of ifs/lets. I'm quite new to kotlin, so don't expect too much from me^^
Not so elegant way:
changeData.firstname?.let { updatedUser.firstname = it }
changeData.lastname?.let { updatedUser.lastname = it }
...
Expected (doesn't work - type mismatch):
updatedUser.copy(
firstname = changeData?.firstname,
lastname = changeData?.lastname,
...)
the reason you get a type mismatch is There is a string type and a string nullable type
var variableName:String = "myData" // if you want a non nullable
var variableName:String? = "myDataThatCouldBeNull" // if you want a string that could be null

Applescript Get value of property by string name of property

In AppleScript. Let's say I have a record with a property called Title.
Let's say I set a variable to the text "Title"; can I use that variable to get the value of the property Title? Basically, is there any way to do something like this:
set result to property named "Title" of myRecord
Instead of:
set result to Title of myRecord
I found the answer. I also realize I didn't ask the correct question. The value I'm trying to obtain is from a property list item.
Here's what I learned, and how to accomplish this:
use framework "Foundation"
set _plist to ...
set _objcPlist to GetAppleScriptObjectAsObjcObject(_plist)
set _value to GetObjcPropertyValueByName("MyProperty", item 1 of _objcPlist)
on GetAppleScriptObjectAsObjcObject(asObject)
set a to current application
set cClass to class of asObject
if (cClass is record) then
return a's NSDictionary's dictionaryWithDictionary:asObject
else if (cClass is list) then
return a's NSArray's arrayWithArray:asObject
else
error "Unexpected Class Type"
end if
end GetAppleScriptObjectAsObjcObject
on GetObjcPropertyValueByName(propertyName, objcItem)
return (objcItem's valueForKey:propertyName) as text
end GetObjcPropertyValueByName
you may try the try ... on error approach:
set aRecord to {title:"hello world", author:"who's who"}
try
aRecord as Unicode text
on error error_message
set err to error_message
end try
err
-- "Can’t make {title:\"hello world\", author:\"who's who\"} into type Unicode text."
then parse err (it's text now). it depends on the complexity of aRecord, if it's a record of nested lists, or records; the parsing would be very complicated. have fun :)

How can I get the value of a variable named after another one in groovy?

I have a variable that contains the name of another variable which I want to retrieve the value, e.g.:
def variable = "finalVariableValue"
def variableName = "variable"
How can I get variable.value as I only know variableName?
I've seen the a Binding could be used but I have a lot of variable that I need to put on this Binding object in order to make it works. Is the only way?
NB: this behaviour is really similar to the ant property extension mechanism.
Thanks,
Michele.
By prefixing it with def you are not registering it in an object you can inspect, like a map; one could argue it is registered in the AST, but that is a rocky road.
My 0.03 are working with a map, with a binding, or with dynamic properties. Drop the def part and choose one of the solutions:
Map
Simply declare the variable as a key in a map:
def map = [:]
map.variable = "finalVariableValue"
def variableName = "variable"
assert map[variableName] == "finalVariableValue"
Binding (with script)
Use the script built-in binding. Note this only works with scripts:
variable = "finalVariableValue"
variableName = "variable"
assert binding[variableName] == "finalVariableValue"
Dynamic properties
Use some dynamic properties mechanism, like an Expando (also, you could use getProperty with setProperty and others):
class Container extends Expando {
def declare() {
variable = "finalVariableValue"
variableName = "variable"
}
}
c = new Container()
c.declare()
assert c[c.variableName] == "finalVariableValue"
You can use the script's scope, simply dropping the Type definition:
variable = 'value'
name = 'variable'
assert 'variable' == this.name
assert 'value' == this[this.name]
or using #Field annotation:
import groovy.transform.Field
#Field def variable = 'value'
#Field def name = 'variable'
assert 'variable' == this.name
assert 'value' == this[this.name]

When getting types from an assembly, is there a way to determine if type is an Anonymous Type?

I added an Anonymous type to my project:
'Put the courses from the XML file in an Anonymous Type
Dim courses = From myCourse In xDoc.Descendants("Course")
Select New With
{
.StateCode = myCourse.Element("StateCode").Value, _
.Description = myCourse.Element("Description").Value, _
.ShortName = myCourse.Element("ShortName").Value, _
.LongName = myCourse.Element("LongName").Value, _
.Type = myCourse.Element("Type").Value, _
.CipCode = CType(myCourse.Element("CIPCode"), String) _
}
For Each course In courses
If Not UpdateSDECourseCode(acadYear, course.StateCode, course.Description, course.Type, course.ShortName, course.LongName, course.CipCode) Then errors.Add(String.Format("Cannot import State Course Number {0} with Year {1} ", course.StateCode, acadYear))
Next
After doing so, a Unit Test failed:
Public Function GetAreaTypeList() As List(Of Type)
Dim types As New List(Of Type)
Dim asmPath As String = IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "My.Stuff.dll")
For Each t As Type In Reflection.Assembly.LoadFrom(asmPath).GetTypes()
If t.Namespace.StartsWith("My.Stuff.BatchUpdater") Then
If t.BaseType Is GetType(My.Stuff.BatchUpdater.Area) Then
types.Add(t)
End If
End If
Next
Return types
End Function
It fails because a new type has been added to the project (VB$AnonymousType_0`6) and it does not have a property called Namespace.
I fixed by making the following change to the IF Statement:
If Not t.Namespace Is Nothing AndAlso t.Namespace.StartsWith("My.Stuff.BatchUpdater") Then
Since I don't fully understand what's happening, I feel leery about my code change.
Why is the Namespace Nothing for the Anonymous type?
Would you fix your Unit Test in the same fashion? Or should it be something more specific (e.g. If Not t.Names = "VB$AnonymousType_0`6")
UPDATE
decyclone gave me the info I needed to create a better test:
For Each t As Type In Reflection.Assembly.LoadFrom(asmPath).GetTypes()
'Ignore CompilerGeneratedAttributes (e.g. Anonymous Types)
Dim isCompilerGeneratedAttribute = t.GetCustomAttributes(False).Contains(New System.Runtime.CompilerServices.CompilerGeneratedAttribute())
If Not isCompilerGeneratedAttribute AndAlso t.Namespace.StartsWith("My.Stuff.BatchUpdater") Then
'...Do some things here
End If
Next
Honestly, it could be improved more with a LINQ query, but this suits me.
Anonymous methods and types are decorated with CompilerGeneratedAttribute. You can check for their existance to identify an anonymous type.
var anonymous = new { value = 1 };
Type anonymousType = anonymous.GetType();
var attributes = anonymousType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false);
if (attributes.Any())
{
// Anonymous
}
You can filter these out in your test.
It is also possible to mark a user defined type with CompilerGeneratedAttribute. So maybe you can combine it with checking if Namespace is null or not
var anonymous = new { value = 1 };
Type anonymousType = anonymous.GetType();
var attributes = anonymousType.GetCustomAttributes(typeof(CompilerGeneratedAttribute), false);
if (attributes.Any() && anonymousType.Namespace == null)
{
// Anonymous
}

F# Serialization of Record types

I know how to serialize in F# using mutable objects, but is there a way to serialize/deserialize using record types using either XmlSerializer or the DataContractSerializer? looks like there is a way to do this for a discriminated union using the KnownType attribute, but i am looking for a way to use non-mutable records without default constructor...
Beginning with F# 3.0, serialization of record types is now supported by applying the CliMutableAttribute to the type. Example:
[<CLIMutable>]
type MyRecord = { Name : string; Age : int }
This example is taken from http://blogs.msdn.com/b/fsharpteam/archive/2012/07/19/more-about-fsharp-3.0-language-features.aspx, which includes a discussion of this feature and three other new features in F# 3.0: triple-quoted strings, automatic properties, and unused variable warnings.
The sample code for reading data from Freebase by Jomo Fisher uses DataContractJsonSerializer to load data into immutable F# records. The declaration of the record that he uses looks like this:
[<DataContract>]
type Result<'TResult> = { // '
[<field: DataMember(Name="code") >]
Code:string
[<field: DataMember(Name="result") >]
Result:'TResult // '
[<field: DataMember(Name="message") >]
Message:string }
The key point here is that the the DataMember attribute is attached to the underlying field that's actually used to store the data and not to the read-only property that the F# compiler generates (using the field: modifier on the attribute).
I'm not 100% sure if this is going to work with other types of serialization (probably not), but it may be a useful pointer to start with...
EDIT I'm not sure if I'm missing something here, but the following basic example works fine for me:
module Demo
#r "System.Runtime.Serialization.dll"
open System.IO
open System.Text
open System.Xml
open System.Runtime.Serialization
type Test =
{ Result : string[]
Title : string }
do
let sb = new StringBuilder()
let value = { Result = [| "Hello"; "World" |]; Title = "Hacking" }
let xmlSerializer = DataContractSerializer(typeof<Test>);
xmlSerializer.WriteObject(new XmlTextWriter(new StringWriter(sb)), value)
let sr = sb.ToString()
printfn "%A" sr
let xmlSerializer = DataContractSerializer(typeof<Test>);
let reader = new XmlTextReader(new StringReader(sr))
let obj = xmlSerializer.ReadObject(reader) :?> Test
printfn "Reading: %A" obj
EDIT 2 If you want to generate cleaner XML then you can add attributes like this:
[<XmlRoot("test")>]
type Test =
{ [<XmlArrayAttribute("results")>]
[<XmlArrayItem(typeof<string>, ElementName = "string")>]
Result : string[]
[<XmlArrayAttribute("title")>]
Title : string }
It doesn't use XmlSerializer or the DataContractSerializer, but Json.NET 6.0 includes nice F# support.
It looks like this:
type TestTarget =
{ a: string
b: int }
[<TestFixture>]
type JsonTests() =
[<Test>]
member x.``can serialize``() =
let objectUnderTest = { TestTarget.a = "isa"; b = 9 }
let jsonResult: string = Newtonsoft.Json.JsonConvert.SerializeObject(objectUnderTest)
printfn "json is:\n%s" jsonResult
let xmlResult = Newtonsoft.Json.JsonConvert.DeserializeXmlNode(jsonResult, "root")
printfn "xml is:\n%s" (xmlResult.OuterXml)
let jsonRoundtrip = Newtonsoft.Json.JsonConvert.DeserializeObject<TestTarget>(jsonResult)
printfn "json roundtrip: %A" jsonRoundtrip
let xmlAsJson = Newtonsoft.Json.JsonConvert.SerializeXmlNode(xmlResult, Newtonsoft.Json.Formatting.Indented, true)
printfn "object -> json -> xml -> json:\n%A" xmlAsJson
let xmlRoundtrip = Newtonsoft.Json.JsonConvert.DeserializeObject<TestTarget>(xmlAsJson)
printfn "xml roundtrip:\n%A" xmlRoundtrip
Assert.That(true, Is.False)
()
json is:
{"a":"isa","b":9}
xml is:
<root><a>isa</a><b>9</b></root>
json roundtrip: {a = "isa";
b = 9;}
object -> json -> xml -> json:
"{
"a": "isa",
"b": "9"
}"
xml roundtrip:
{a = "isa";
b = 9;}
You can use this series of annotations on the properties of classes to format the XML:
[XmlRoot("root")]
[XmlElement("some-element")]
[XmlAttribute("some-attribute")]
[XmlArrayAttribute("collections")]
[XmlArrayItem(typeof(SomeClass), ElementName = "item")]
I use the attributes on my c# classes, but deserialize in F# (c# classes are ina referenced lib).
in f#:
use file = new FileStream(filePath, FileMode.Open)
let serializer= XmlSerializer(typeof<SomeClass>)
let docs = serializer.Deserialize file :?> SomeClass