Dynamic records in Elm 0.18 - immutability

The model in my Elm app has some nested records. I am currently setting them with normal immutable functions.
Types.elm
type alias Model =
{ settings : Settings
...
}
type alias Settings =
{ username : String
, password : String
...
}
App.elm
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
case msg of
SetUsername username ->
( model |> setUserName username, Cmd.none )
SetPassword password ->
( model |> setPassword password, Cmd.none )
Setters.elm
setUserName : String -> Model -> Model
setUserName username model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | username = username }
in
{ model | userSettings = newUserSettings }
setPassword : String -> Model -> Model
setPassword password model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | password = password }
in
{ model | userSettings = newUserSettings }
I'd like to generalize the Setters so that I can set them dynamically. Something like this:
setUserSettings : String -> String -> Model
setUserSettings field variable model =
let
oldUserSettings =
model.userSettings
newUserSettings =
{ oldUserSettings | field = variable }
in
{ model | userSettings = newUserSettings }
setUserName : String -> Model -> Model
setUserName value model =
setUserSettings username value
setPassword : String -> Model -> Model
setPassword value model =
setUserSettings password value
What is the most elm-like way to do this?

As already have been mentioned, there is no built-in syntax for setting a field of a record.
Due to this limitation, I think, your current code is fine. But if some more fields appear in the Settings, it may be useful to extract the logic of access to a nested field into a separate function:
setUserName : String -> Model -> Model
setUserName username model =
setUserSettings model (\r -> { r | username = username })
setPassword : String -> Model -> Model
setPassword password model =
setUserSettings model (\r -> { r | password = password })
setUserSettings : Model -> (Settings -> Settings) -> Model
setUserSettings model updateSettings =
let
oldUserSettings =
model.userSettings
newUserSettings =
updateSettings oldUserSettings
in
{ model | userSettings = newUserSettings }
In case a deeper nesting appears, you might find focus library useful. Here is an example of its usage.
In your current case, the library is going to modify your code to this:
update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
let
userSettings =
create .userSettings (\f r -> { r | userSettings = f r.userSettings })
username =
create .username (\f r -> { r | username = f r.username })
password =
create .password (\f r -> { r | password = f r.password })
in
case msg of
SetUsername value ->
( set (userSettings => username) value model, Cmd.none )
SetPassword value ->
( set (userSettings => password) value model, Cmd.none )
But both solutions are not perfect since you need to define a custom setter for each field.

Related

Custom Result handling by calling store procedure in Spring Data JPA

I have requirement to call store procedures which takes input parameters. This store procedure returns custom result set, that result set i need to read and process further before return to UI. How we can achieve this?
EG:
#Query("CALL SP_EMPLOYEE_REPORT(:year)",nativeQuery = true)
List<EmpolypeeCustomReportBean> getEmployeeReport(#param("year") Integer year);
Given the following stored procedure.
CREATE PROCEDURE NAME_OF_THE_PROCEDURE(IN param VARCHAR(255), OUT retval INT)
You can call it from interface query:
#Procedure(value = "NAME_OF_THE_PROCEDURE")
int getFromStoredProcedure(String param);
Also by #Query annotation:
#Query(value = "CALL NAME_OF_THE_PROCEDURE(:input_value);", nativeQuery = true)
Integer findSomeThing(#Param("input_value") Integer name);
Or you can use named stored procedure query too.
#Entity
#NamedStoredProcedureQuery(name = "MyObj.getSomethingFromProc",
procedureName = "NAME_OF_THE_PROCEDURE", parameters = {
#StoredProcedureParameter(mode = ParameterMode.IN, name = "param", type = String.class),
#StoredProcedureParameter(mode = ParameterMode.OUT, name = "retval", type = Integer.class)})
public class MyObj{
// class definition
}
Then call it.
#Procedure(name = "MyObj.getSomethingFromProc")
Integer getSomethingFromStoredProc(#Param("param") String model);
Also you can use resultClasses and resultSetMapping properties in #NamedStoredProcedureQuery for complex return types.
Complex example provided by Eclipselink:
#NamedStoredProcedureQuery(
name="ReadUsingMultipleResultSetMappings",
procedureName="Read_Multiple_Result_Sets",
resultSetMappings={"EmployeeResultSetMapping", "AddressResultSetMapping", "ProjectResultSetMapping", "EmployeeConstructorResultSetMapping"}
)
#SqlResultSetMappings({
#SqlResultSetMapping(
name = "EmployeeResultSetMapping",
entities = {
#EntityResult(entityClass = Employee.class)
}
),
#SqlResultSetMapping(
name = "EmployeeConstructorResultSetMapping",
classes = {
#ConstructorResult(
targetClass = EmployeeDetails.class,
columns = {
#ColumnResult(name="EMP_ID", type=Integer.class),
#ColumnResult(name="F_NAME", type=String.class),
#ColumnResult(name="L_NAME", type=String.class),
#ColumnResult(name="R_COUNT", type=Integer.class)
}
)
}
)
})
public Employee(){
....
}

Kotlin entered value not searching database

We have worked on this code to error trap a value entered in a Edit Text field
When the value is entered correctly we are informed that the entered value does not match
BUT if we select the value from a recycler view list and populate the Edit Text field with the value the search tells us we have a match
Here is the code for the search in the DBHelper
fun getOneName(id: Int): Contact? {
val db = this.writableDatabase
val selectQuery = "SELECT * FROM $TABLE_NAME WHERE $colId = ?"
db.rawQuery(selectQuery, arrayOf(id.toString())).use { // .use requires API 16
if (it.moveToFirst()) {
val result = Contact(id = 0,name ="")
result.id = it.getInt(it.getColumnIndex(colId))
result.name = it.getString(it.getColumnIndex(colName))
return result
}
}
return null
}
We used this for the Model Class our first time using data class as just plain class
data class Contact (
var id: Int,
var name: String
)
And here is the button click that manages the search
btnGetID.setOnClickListener {
if(etPerson.text.toString().trim().isNullOrEmpty()){
message("Enter Contact Name")
return#setOnClickListener
}
var numeric = true
var string = etPerson.text.toString().trim()
numeric = string.matches(".*\\d+.*".toRegex())
if(numeric){
message("No NUMBERS")
return#setOnClickListener
}
val dbManager = DBHelper(this)
var name = etPerson.text.toString()
//val contact = dbManager.getOneName(name)
val contact = dbManager.getOneName(id.toInt())
if(contact?.name.equals(name)){
println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! contact ID= "+contact)
etPerson.setText("The contact name is $name the ID is "+contact?.id.toString())
}else{
etPerson.setText("Name NOT = to $name and the ID is "+contact?.id.toString())
}
}
We know the name Sally is in the DB if we type Sally in the else statement shows Name NOT = bla
If we select Sally from the Recyclerview List the first statement shows The contact name bla bla
Kotlin 1.2.71 API 27
Our question is why is the hand typed name failing if it mataches?
HERE IS THE CORRECT CODE FOR THE DBHelper
fun getOneName(name: String): Contact? {
val db = this.writableDatabase
val selectQuery = "SELECT * FROM $TABLE_NAME WHERE $colName = ?"
db.rawQuery(selectQuery, arrayOf(name)).use { // .use requires API 16
if (it.moveToFirst()) {
val result = Contact(id = 0,name ="")
result.id = it.getInt(it.getColumnIndex(colId))
result.name = it.getString(it.getColumnIndex(colName))
return result
}
}
return null
}

Conditional method call in the map method java 8

Persons = personDao.getFileInformation(filePath)
.skip(1)
.map(this::getPerson)
.filter(person -> person != null)
.collect(Collectors.toList());
getFileInformation(filePath) returns Stream<String>
after reading lines in a file.
I would like to replace the getPerson method with a getMale or getFemale method based on the value of an enum
public enum gender {
male,female
}
How can this be achieved used lambda expressions?
If you just want to filter by gender (assuming there is an accessor like Person.getGender), then you only need to add a filter:
List<Person> malePeople;
malePeople = personDao.getFileInformation(filePath)
.skip(1)
.map(this::getPerson)
.filter(Objects::nonNull)
.filter(p -> p.getGender() == gender.male) // or gender.female
.collect(Collectors.toList());
If you rather want to group your results, the following will help you:
Map<gender, List<Person>> peopleByGender;
peopleByGender = personDao.getFileInformation(filePath)
.skip(1)
.map(this::getPerson)
.filter(Objects::nonNull)
.collect(Collectors.groupingBy(Person::getGender));
now access all your female people with:
List<Person> femalePeople = peopleByGender.get(gender.female);
and the male ones with:
List<Person> malePeople = peopleByGender.get(gender.male);
If you just wanted to use a method to simplify the filter-predicate (p -> p.getGender() == gender.male), then you could use one of the following:
.filter(this::getMale) // or: YourClass::getMale for a static method
where this::getMale refers to the following method:
boolean getMale(Person p) {
return p.getGender() == gender.male;
}
or
.filter(getMale())
where getMale() refers to the following method:
Predicate<Person> getMale() {
return p -> p.getGender() == gender.male;
}

Different ways of adding items to a dictionary with different results

I'm dabbling in swift after a long time away and I've hit an issue that I can't figure out. I'm trying two different ways to add items to a dictionary and getting some different results.
I was initially adding values to a dictionary by doing:
userInfo = ["username":username]
userInfo = ["email":email]
userInfo = ["password":password]
I would then print("\(userInfo)") but it would only contain password.
I then tried switching it up to:
userInfo!["username"] = username
userInfo!["email"] = email
userInfo!["password"] = password
but this resulted in fatal error: unexpectedly found nil while unwrapping an Optional value for username
I finally switched it to the following configuration
userInfo = ["username":username]
userInfo!["email"] = email
userInfo!["password"] = password
and everything prints put. Whats up with that?
Full implementation:
nextPressed()
{
if let userInfo:[String:String] = try registrationValidation()
{
print("\(userInfo)")
}
}
func registrationValidation () throws -> [String:String]?
{
var userInfo: [String:String]?
var problems: [ValidationMessage] = []
if let username = usernameField.text
{
let p1 = validateUsername(username)
problems.appendContentsOf(p1)
userInfo = ["username":username]
//userInfo!["username"] = username
//Above results in nil, yet lines below work?
}
if let email = emailField.text
{
let p2 = validateEmail(email)
problems.appendContentsOf(p2)
//userInfo = ["email":email]
userInfo!["email"] = email
}
if let password = passwordField.text
{
let p3 = validatePassword(password)
problems.appendContentsOf(p3)
//userInfo = ["password":password]
userInfo!["password"] = password
}
if !problems.isEmpty{
throw ValidationError(problems:problems)
}
else
{
print("validation succeeded")
return userInfo
}
}
I think this would be a better way to do what you want to achieve like :
func registrationValidation () throws -> [String:String]?
{
var userInfo = [String:String]() // **Initialize an empty dictionary**
var problems: [ValidationMessage] = []
if let username = usernameField.text
{
let p1 = validateUsername(username)
problems.appendContentsOf(p1)
userInfo["username"] = username
}
if let email = emailField.text
{
let p2 = validateEmail(email)
problems.appendContentsOf(p2)
//userInfo = ["email":email] **// This line will result in creating a new dictionary object**
userInfo["email"] = email
}
if let password = passwordField.text
{
let p3 = validatePassword(password)
problems.appendContentsOf(p3)
//userInfo = ["password":password]
userInfo["password"] = password
}
if !problems.isEmpty{
throw ValidationError(problems:problems)
}
else
{
print("validation succeeded")
return userInfo
}
}

MVC3 ajaxgrid scaffolding error, Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Objects.ObjectQuery'

I'm using MVC3 ajaxgrid scaffolding with EF4.1 code first and i've this error:
Cannot implicitly convert type 'System.Linq.IQueryable' to 'System.Data.Objects.ObjectQuery'
The code with the error in, is autogenerated:
public ActionResult GridData(int start = 0, int itemsPerPage = 20, string orderBy = "UserID", bool desc = false)
{
Response.AppendHeader("X-Total-Row-Count", repository.Users.Count().ToString());
ObjectQuery<User> users = (repository as IObjectContextAdapter).ObjectContext.CreateObjectSet<User>();
users = repository.Users.Include(u => u.Role); //ERROR HERE
users = users.OrderBy("it." + orderBy + (desc ? " desc" : ""));
return PartialView(users.Skip(start).Take(itemsPerPage));
}
This is the Users repository method and the Roles Foreign Key
public IQueryable<Entities.User> Users
{
get { return context.Users; }
}
public IQueryable<Entities.Role>Roles
{
get { return context.Roles; }
}
How can i resolve the conversion?
Get rid of the Lambda and use the related object:
var users = repository.Users.Include("Role"); //ERROR HERE
Assuming the entity User has a navigational property Role.
The reason is clear:
You have users variable with ObjectQuery<User> type then you assign that variable result of a query which is IQueryable<User>.
UPDATE:
Try the code below:
public ActionResult GridData(int start = 0, int itemsPerPage = 20, string orderBy = "UserID", bool desc = false)
{
Response.AppendHeader("X-Total-Row-Count", repository.Users.Count().ToString());
//ObjectQuery<User> users = (repository as IObjectContextAdapter).ObjectContext.CreateObjectSet<User>();
var users = repository.Users.Include(u => u.Role); //ERROR HERE
users = users.OrderBy("it." + orderBy + (desc ? " desc" : ""));
return PartialView(users.Skip(start).Take(itemsPerPage));
}

Resources