Define `type alias` with a partial definition or default - record

Is there a way to DRY this?
I don’t want to repeat contents : List Nav and wrapperId : String
type alias InputModel =
{ contents : List Nav
, containerClassName : Maybe String
, wrapperId : String
}
type alias Model =
{ contents : List Nav
, containerClassName : String
, wrapperId : String
}
modelWithDefaults : InputModel -> Model
modelWithDefaults input =
{ input | containerClassName = withDefault "" input.containerClassName }

Yes there is! You can move the common fields into a separate record and add a row variable to it. The row variable, a, which specify the remaining fields, can then be supplied later:
type alias CommonModel a =
{ a
| contents : List Nav
, wrapperId : String
}
type alias InputModel =
CommonModel
{ containerClassName : Maybe String }
type alias Model =
CommonModel
{ containerClassName : String }
You can also use row variables to write functions that accept any record as long as it has the common fields. E.g.
getWrappedId : CommonModel a -> String
getWrapperId { wrapperId } = wrappedId
will accept both InputModel and Model, or any other record that contains at least the fields specified by CommonModel. The row variable will be inferred, just like any other type variable would.

Related

How to render partial responses with Akka HTTP

I would like to render partial response using Akka HTTP. In the request the client should specify which fields to include in the response (e.g. using a fields request parameter, for example: https://www.acme.com/api/users/100?fields=id,name,address).
I would appreciate any pointers on how to solve this.
Akka http provides a useful DSL known as Directives to solve these types of problems. You can match on a particular path and then extract the HttpRequest query string for the "fields" key:
import akka.http.scaladsl.server.Directives._
val route = get {
path("api" / "users" / IntNumber) { pathInt =>
parameter('fields) { fields =>
complete(generateResponse(pathInt, fields))
}
}
}
For the given example request ("https://www.acme.com/api/users/100?fields=id,name,address") the generateResponse function will be called with 100 and id,name,address as the input variables. Say you have some lookup table of the values:
case class Person(id : String, name : String, address : String, age : Int)
val lookupTable : Map[Int, Person] = ???
You can then use this lookup table to get the person and extract the appropriate fields:
def personField(person : Person)(field : String) = field match {
case "id" => s"\"id\" = \"${person.id}\""
case "name" => s"\"name\" = \"${person.name}\""
...
}
//generates JSON responses
def generateResponse(key : Int, fields : String) : String = {
val person = lookupTable(key)
"{ " +
fields
.split(",")
.map(personField(person))
.reduce(_ + " " + _)
+ " }"
}

How to get the value of an annotated variable?

So, I'm writing a method that will get annotated variables (doubles) and store them in a map. The variables are elements of an object. The name of the variable should be the key and its value - the parameter.
public void putInMap() {
Field[] fields = this.getClass().getDeclaredFields();
for (Field v: fields) {
if (v.isAnnotationPresent(Annotation.class))
map.put(v.getName(), *value here* );
}
}
My question is how to get the value of the variable (which is now a Field) so that I could put it in my map?
Try:
for (Field v : fields) {
if (v.isAnnotationPresent(Annotation.class)) {
v.setAccessible(true);
map.put(v.getName(), v.get(this));
}
}

How to set a derived property to lower case in Grails/GORM?

This is a newbie question -- thank you for your help. I wanted to set a derived property to lower case in my domain model. Did some search (http://grails.org/doc/latest/guide/GORM.html#ormdsl plus some other) and I thought the following would work (note: nameLowerCase formula: 'LOWER(NAME)') ...
class Item {
String name
String nameLowerCase
static constraints = {
name(blank: false)
nameLowerCase(blank: false, unique: true)
}
static mapping = {
nameLowerCase formula: 'LOWER(NAME)'
sort nameLowerCase: "asc"
}
}
However, when I do ...
new Item(name: 'A').save(failOnError: true)
new Item(name: 'c').save(failOnError: true)
new Item(name: 'B').save(flush: true, failOnError: true)
println Item.list().nameLowerCase
I was expecting it to print [a, b, c] (turning to lower case in addition to the sorting), but it prints [null, null, null], and I am unable to figure out why.
What am I doing wrong? Or, is there any other way I can achieve the lower case in my domain class itself for nameLowerCase irrespective of what is passed for the name (other than using the formula in mapping)? Any help will be appreciated.
I think storing the same data in the database is a bad idea.
It's better to do it this way:
class Item {
static transients = ['nameLoweCase']
String name
String getNameLowerCase(){
name.toLowerCase()
}
static constraints = {
name blank: false
}
}
And in the controller:
class SomeController{
def show(Long id){
def item = Item.get(id)
item.nameLowerCase // name in lower case
}
}
'transient' defines a list of property names that should not be persisted to the database (more about it).
Just add this
def beforeInsert() {
nameLowerCase = name.toLowerCase()
}
def beforeUpdate() {
nameLowerCase = name.toLowerCase()
}
and remove this
nameLowerCase formula: 'LOWER(NAME)'
and Enjoy..

Check for existing mapping when writing a custom applier in ConfORM

I am writing my first custom column name applier for ConfORM.
How do I check if another column has already been map with same mapping name?
This is what I have so far:
public class MyColumnNameApplier : IPatternApplier<PropertyPath, IPropertyMapper>
{
public bool Match(PropertyPath subject)
{
return (subject.LocalMember != null);
}
public void Apply(PropertyPath subject, IPropertyMapper applyTo)
{
string shortColumnName = ToOracleName(subject);
// How do I check if the short columnName already exists?
applyTo.Column(cm => cm.Name(shortColumnName));
}
private string ToOracleName(PropertyPath subject)
{
...
}
}
}
I need to shorten the generated column names to less than 30 characters to fit in with Oracle's 30 character limit. Because I am shortening the column names it is possible that the same column name can potentially be generated two different properties. I would like to know when a duplicate mapping occurs.
If I don't handle this scenario ConfORM/NHibernate allows two different properties to 'share' the same column name - this is obviously creates a problem for me.
if column names are mapped twice you will get exception about parameter count on first load. You can can check after configuring:
foreach (var clazz in config.ClassMappings)
{
var propertiesWithOneColumn = clazz.PropertyClosureIterator.Where(p => p.ColumnSpan == 1);
var distinctColumns = new HashSet<string>();
foreach (var prop in propertiesWithOneColumn)
{
var col = prop.ColumnIterator.First().Text;
if (distinctColumns.Add(col))
{
Console.WriteLine("duplicate column "+ col + " found for property " + prop.PersistentClass.ClassName + "." + prop.Name);
}
}
}

converting 0 or 1 to yes or no in MVC4 model for display purposes

I will be displaying some results that will be either 0 or 1 in my MVC 4 application. I would like for them to display either yes (1) or no (0). Is there an annotation I can add to my fields to do that? Or do I have to do that in the view somehow...
In the model, add a backing field and specify the getter for the property
private string _myString;
public string MyString
{
get
{
_myString = _myString.Equals( "0" ) ? "No" : "Yes";
return _myString;
}
set { _myString = value; }
}
You could use a custom HTML helper for this:
http://www.asp.net/mvc/tutorials/older-versions/views/creating-custom-html-helpers-cs
or perhaps just a plain extension method. I have one I use for Boolean values.
public static bool ToYesNo(this Boolean boolValue)
{
return (boolValue ? "Yes" : "No");
}