how to update an inner record in elm - elm

I have this model
type alias Model =
{ exampleId : Int
, groupOfExamples : GroupExamples
}
type alias GroupExamples =
{ groupId : Int
, results : List String
}
In my update function, if I want to update the exampleId would be like this:
{ model | exampleId = updatedValue }
But what if I need to do to update, for example, just the results value inside of GroupExamples?

The only way to do it in the language without anything extra is to destructure the outer record like:
let
examples = model.groupOfExamples
newExamples = { examples | results = [ "whatever" ] }
in
{ model | groupOfExamples = newExamples }
There is also the focus package which would allow you to:
set ( groupOfExamples => results ) [ "whatever" ] model

Related

PostgreSQL - Update inner json

I have a column jdata of type jsonb inside a table 'JTABLE'. A sample jdata looks like this :
{
"id" : 12,
"address" : {
"houseName": {
"name" : "Jackson",
"lang" : "ENG"
}
}
}
How can i query to update the lang to anotherValue for this?
I tried this and it doesn't seem to work :
UPDATE JTABLE SET jdata -> 'address'->'houseName'-> 'lang' = '"DEU"' where jdata->>'id' = '12';
This doesn't work! Any help?
EDIT:
This overwrites my value and i get this when i run :
{
"id" : 12,
"address" : {
"houseName": {
"lang" : "DEU"
}
}
}
I lost key name.
I'm trying this query now :
SELECT jsonb_set(jdata, 'address,houseName}', '{"lang":"DEU"}'::jsonb) FROM JTABLE where jdata->>'id' = '12';
Your path is wrong, the 2nd statement should be a path to the json key you wish to update.
The query to view your update should look like :
SELECT jsonb_set(jdata, '{address,houseName,lang}', '"DEU"') FROM JTABLE where jdata->'id' = '12';
The final query to update :
UPDATE JTABLE SET jdata = jsonb_set(jdata, '{address,houseName,lang}', '"DEU"') WHERE jdata->'id' = '12';
Also don't type cast a record to `jsonb.

Elm record shorthand notation

To get better at functional programming in JavaScript, I started leaning Elm.
In JavaScript you have the object shorthand notation:
const foo = 'bar';
const baz = { foo }; // { foo: 'bar' };
I was wondering whether there is something like that in Elm? I'm asking because I have the following model:
type alias Model =
{ title : String
, description : String
, tag : String
, tags : List String
, notes : List Note
}
type alias Note =
{ title : String
, description : String
, tags : List String
}
And an update function that upon receiving the AddNote action adds the note to the notes array and clears the inputs:
AddNote ->
{ model | notes = model.notes ++ [ { title = model.title, description = model.description, tags = model.tags } ], title = "", description = "", tag = "" }
I know that in function definitions you can "destructure" records, but I think even in the return type I would have to explicitly type out each key of the record.
AddNote ->
{ model | notes = model.notes ++ [ getNote model ], title = "", description = "", tag = "" }
getNote : Model -> Note
getNote { title, description, tags } =
{ title = title, description = description, tags = tags }
There is not a shorthand record notation similar to JavaScript objects.
However, a type alias also serves as a constructor function, so you could have something like this:
getNote : Model -> Note
getNote { title, description, tags } =
Note title description tags

Azure Stream Analytics: Get Array Elements by name

I was wondering if it is possible for me to get the elements of the array by the name of property than the position. For example, this is my incoming data:
{
"salesdata": {
"productsbyzone": {
"zones": [{
"eastzone": "shirts, trousers"
},
{
"westzone": "slacks"
},
{
"northzone": "gowns"
},
{
"southzone": "maxis"
}
]
}
}
}
I intend to move this to a SQL database and I have columns within the database for each zone. The problem is that the order of different zones changes within each json. I was successfully using the following query until I realized that the position of the zones changes within each json:
WITH
salesData AS
(
SELECT
(c.salesdata.productsbyzone.zone,0) as eastzone,
(c.salesdata.productsbyzone.zone,1) as westzone,
(c.salesdata.productsbyzone.zone,2) as northzone,
(c.salesdata.productsbyzone.zone,3) as sourthzone,
FROM [sales-data] as c
)
SELECT
eastzone.eastzone as PRODUCTS_EAST,
westzone.westzone as PRODUCTS_WEST,
northzone.northzone as PRODUCTS_NORTH,
southzone.southzone as PRODUCTS_SOUTH
INTO PRODUCTSDATABASE
FROM salesData
Need a way to reference these fields by the name rather than by the position.
I recommend a solution: Use the JavaScript UDF in the azure stream job to complete the columns sort.
Please refer to my sample:
Input data(upset the order):
{
"salesdata": {
"productsbyzone": {
"zones": [{
"westzone": "slacks"
},
{
"eastzone": "shirts, trousers"
},
{
"northzone": "gowns"
},
{
"southzone": "maxis"
}
]
}
}
}
js udf code:
function test(arg) {
var z = arg;
var obj = {
eastzone: "",
westzone: "",
northzone: "",
southzone: ""
}
for(var i=0;i<z.length;i++){
switch(Object.keys(z[i])[0]){
case "eastzone":
obj.eastzone = z[i]["eastzone"];
continue;
case "westzone":
obj.westzone = z[i]["westzone"];
continue;
case "northzone":
obj.northzone = z[i]["northzone"];
continue;
case "southzone":
obj.southzone = z[i]["southzone"];
continue;
}
}
return obj;
}
You can define the order you want in the obj parameter
SQL:
WITH
c AS
(
SELECT
udf.test(jsoninput.salesdata.productsbyzone.zones) as result
from jsoninput
),
b AS
(
SELECT
c.result.eastzone as east,c.result.westzone as west,c.result.northzone as north,c.result.southzone as south
from c
)
SELECT
b.east,b.west,b.north,b.south
INTO
jaycosmos
FROM
b
Output:
Hope it helps you.
You can use GetArrayElement to return array element then access to each property. Please refer the below query
WITH
salesData AS
(
SELECT
GetArrayElement(zones,0) as z
FROM [sales-data] as s
)
SELECT
z.eastzone
z.westzone
z.northzone
z.southzone
FROM PRODUCTSDATABASE
FROM salesData

Load different resources on urlUpdate elm

I am new to elm and functional programming. Hope this is a simple question. What I am trying to do is, when I change views I want elm to fetch records based on the view that it is about to change to. I was hoping I could do it in the urlUpdate method based on the currentRoute. I have two views one for players and one for perks, both have independent commands objects. I tried to do it like this:
urlUpdate : Result String Route -> Model -> ( Model, Cmd Msg )
urlUpdate result model =
let
currentRoute =
Routing.routeFromResult result
_ =
Debug.log "Current Route" currentRoute
in
if toString currentRoute == "PerksRoute" then
( { model | route = currentRoute }
, Perks.Commands.fetchAll
)
else if toString currentRoute == "PlayersRoute" then
( { model | route = currentRoute }
, Players.Commands.fetchAll
)
else
( { model | route = currentRoute }, Cmd.none )
However I get this error:
The 1st branch has this type:
( { a | route : Route }, Cmd Perks.Messages.Msg )
But the 2nd is:
( { a | route : Route }, Cmd Players.Messages.Msg )
I am not sure why this is happening, I would think that having this Type defined at would be ok.
type Msg
= PlayersMsg Players.Messages.Msg
| PerksMsg Perks.Messages.Msg
Here is the full src
You need to use Cmd.map to map the child command to the parent:
if toString currentRoute == "PerksRoute" then
( { model | route = currentRoute }
, Cmd.map PerksMsg Perks.Commands.fetchAll
)
else if toString currentRoute == "PlayersRoute" then
( { model | route = currentRoute }
, Cmd.map PlayersMsg Players.Commands.fetchAll
)

Simplifying recursive updating of records

Can this code be simplified?
update : Action -> Model -> Model
update action model =
let
formValue = model.formValue
in
case action of
UpdateWhat what ->
let
newValue = { formValue | what <- what }
in
{ model | formValue <- newValue }
UpdateTrigger trigger ->
let
newValue = { formValue | trigger <- trigger }
in
{ model | formValue <- newValue }
As I plan to add a couple more of Update... clauses, it is helpful to abstract this out a bit.
The code is written the way it is because Elm does not accept inner record updates.
I think what you're looking for is the focus library:
Focus
A Focus is a way to work with particular parts of a large chunk of data. On the most basic level, it lets you get and set fields of a record in a simple and composable way. This means you could avoid writing special record update syntax and use something that composes much more elegantly.
It gives you the ability to write stuff like freeze in the following snippet:
mario =
{ super = False
, fire = False
, physics = { position = { x=3, y=4 }
, velocity = { x=1, y=1 }
}
}
freeze object =
set (physics => velocity) { x=0, y=0 } object
In the code example physics and velocity are Foci. You can create a focus with code like the following, to use your example:
formValue = Focus.create .formValue (\f r -> { r | formValue <- f r.formValue })
what = Focus.create .what (\f r -> { r | what <- f r.what })
trigger = Focus.create .trigger (\f r -> { r | trigger <- f r.trigger })
update : Action -> Model -> Model
update action model =
case action of
UpdateWhat w -> Focus.set (formValue => what) w model
UpdateTrigger t -> Focus.set (formValue => trigger) t model