How to insert Foreign Key values from Form Input? - yesod

Say I have the following relations :
Section
name Text
UniqueSection name
Subject
name Text
UniqueSubject name
Faculty
name Text
UniqueFaculty name
Assignment
section SectionId
faculty FacultyId
subject SubjectId
UniqueAssignment section subject
Handler:
postNewAssignmentR :: Handler Html
postNewAssignmentR = do
-- don't know what to use instead xxxField for SectionId/FacultyId/SubjectId
sec <- runInputPost $ ireq xxxField "section"
fac <- runInputPost $ ireq xxxField "faculty"
sub <- runInputPost $ ireq xxxField "subject"
runDB $ insert $ Assignment sec fac sub
setMessage "Created new Assignment"
redirect AssignmentsR
If "section", "faculty", and "subject" are dropdowns inputs with their corresponding Ids as values(in Text we get from runInputPost), how to convert them to sectionId, facultyId,..etc ?
or should I go for any other approach to insert foreign keys ?

I just realized you are not generating the forms using Yesod so my original suggestion below may not work. You can probably get the input value as an Int and then use fKey = Key $ PersistInt64 intReturnValue
Unsure if the code below will work for your case:
You can use selectField to get a list of Section Names and then populate it in your dropdown -- the values should map to IDs automatically. I don't use Input Forms but guessing something like this should work:
<*> ireq (selectField sections) "Section Name"
where
sections = do
entities <- runDB $ selectList [] [Asc SectionName]
optionsPairs $ map (\e -> (sectionName $ entityVal e, entityKey e)) entities

Related

Reading from file and creating a data in haskell

I have been trying to a read file creating data in haskell. i have the following data type constructed:
data Participant = Participant {name:: String, age:: Int,
country:: String, }
The text file i have is in this format
Jack 21 England
Natalie 20 France
Sophie 24 France
Each word corresponds to name age and country respectivly. I want to read the file and create a list of participants. But IO:String seem to be a pain in the neck. Do you have a suitable soliton for this problem.
IO isolation is not a defect, but a feature of Haskell, and one of its clear success.
If you want to serialize data to file, and load data back into your program, you don't have to do that by hand. Use any serializing library, there are many of them. You can also use the great Aeson library, that can convert your data in JSON and load them back.
If you want to do that by hand for any reason, you must first define your own file format, and have it unambiguous. For example, what happens on your example if name contains a space ?
Then you should define a function that can parse one line of your file format and produce a Participant readParticipant :: String -> Maybe Participant. Notice the maybe, because if the string is ill-formated, your function won't be able to create a participant out of its hat, so it will produce a Nothing.
Then you can have a function that parse a list of participants (notice the plural) readParticipants :: String -> [Participants]. No Maybe here because the list itself allows for failure.
Now you can have a tiny IO function that will read the file content, and run readParticipants on it.
readParticipantsIO :: IO [Participants]
readParticipantsIO = readParticipants <$> readFile "participants.data"
-- alternative definition, exact same behaviour in this case
readParticipantsIO :: IO [Participants]
readParticipantsIO = do
content <- readFile "participants.data"
return $ readParticipants content
The lines and words functions can be used to split the string into a list of strings, and then you can package these strings into a list of Participant.
import Text.Read (readMaybe)
data Participant = Participant { name :: String, age :: Int, country :: String }
parseParticipants :: String -> [Participant]
parseParticipants fileContents = do
[name', age', country'] <- words <$> lines fileContents
Just age'' <- return (readMaybe age')
return (Participant { name = name', age = age'', country = country' })
main :: IO ()
main = do
participants <- parseParticipants <$> readFile "yourfile.txt"
-- do things with the participants
return ()

How to merge two list and make a dictionary using vim in vscode?

Imagine we have two list in two files,
file 1: contact_list_names.txt like:
Ali
James
Amir
Jones
Sarah
file 2 :contact_phones.txt like:
12344
43211
09876
67890
12309
I know that we can select all using gg then v then Shift + g to select all , but when you paste using p key its not pasting every number in front of its contact name ...
So how to paste the numbers in front of its related contact name ?
The problem using the clipboard to paste columns side by side is the type of selection of it, see here:
:echo getregtype('+')
if it returns a lowercase v, it means the type is characterwise.
if it returns an uppercase V, it means the type is linewise.
if it returns ^V{some number}, it means the type is blockwise, and the width of the block is {some number}.
But we can change it this way (making the clipboard register blockwise):
:call setreg('+',#+,'b')
Now if you try to paste a new column before or after the first one
you will succeed!
Here a function to get the content of the clipboard and paste after
the current column
fun! GiveItaNameYouWant()
call setreg('+',#+,'b')
normal gg
execute "normal! A \<esc>"
execute "normal! \"+p"
endfun
If you copy this function to the clipboard and load it into the memory just run:
:#+
Now put the cursor at the first column and run:
:call GiveItaNameYouWant()
Note: I am referring only to the clipboard register but you can also make these changes on the primary register selection "*", in the yank register "0" and default register '"' and a-z ones.
References: https://stackoverflow.com/a/48678100/2571881

Python dictionary map to SQL query string

I have a python dictionary that maps column names from a source table to a destination table.
Dictionary:
tablemap_computer = {
'ComputerID' : 'computer_id',
'HostName' : 'host_name',
'Number' : 'number'
}
I need to dynamically produce the following query string, such that it will update properly when new column name pairs are added to the dictionary.
ComputerID=%(computer_id)s, HostName=%(host_name), Number=%(number)s
What is a good way to do this?
I have a start at this but it is very messy and has an extra comma at the end of the last element.
queryStrInsert = ''
for tm_key, tm_val in tablemap_computer.items():
queryStrInsert += tm_key+'=%('+tm_val+')s,'
You might want to try using join and list comprehension.
query = ', '.join([key + '=%(' + value + ')s' for key, value in tablemap_computer.items()])
Using the dictionary you gave as an example one would end up with the following string:
HostName=%(host_name)s, Number=%(number)s, ComputerID=%(computer_id)s

Isolating the elements of a row in python

I am working on a project where i am trying to plot the rainfall pattern of various states of my country. By using this command i fetch the data from my database:
cur.execute('SELECT JAN,FEB,MAR,APR,MAY,JUN,JUL,AUG,SEP,OCT,NOV,DECEMBER FROM Rainfall_In_Cm where STATE_UT = %s && DISTRICT = %s' ,(state , district))
The result comes in the form of a list with 1 element(the 1 row from the query output) :
(Decimal('17.5'), Decimal('9.9'), Decimal('8.9'), Decimal('4.0'), Decimal('9.3'), Decimal('53.8'), Decimal('227.1'), Decimal('280.90'), Decimal('125.4'), Decimal('28.1'), Decimal('5.0'), Decimal('4.7'))
Now i want all the elements to be in form of a list that i can use with matplotlib to plot a graph and I want to remove 'Decimal' string from infront of every value . How can i do it?
Your result is a tuple, not a list, but that is not a problem.
Casting should work for these Decimal objects. You can use a list comprehension:
#Data from your example
foo = (Decimal('17.5'), Decimal('9.9'), Decimal('8.9'), Decimal('4.0'), Decimal('9.3'), Decimal('53.8'), Decimal('227.1'), Decimal('280.90'), Decimal('125.4'), Decimal('28.1'), Decimal('5.0'), Decimal('4.7'))
bar = [float(i) for i in foo]
If you want to have rather integers, use:
bar = [int(i) for i in foo]

Displaying list of tuples

displayContacts :: Contact ->[String]
displayContacts [] = []
displayContacts (x :xs) = [show (x)] ++ displayContacts (xs)
after performing above function following result showing with exta "\" why is that and how to overcome this
["(\"Fazaal\",\"Naufer\",7712345678)","(\"Tharanga\",\"Chandasekara\",779876543)","
(\"Ruaim\",\"Mohomad\",7798454545)","(\"Yasitha\",\"Lokunarangoda\",7798121212)","
(\"Rochana\",\"Wimalasena\",779878787)","(\"Navin\",\"Dhananshan\",77987345678)","
( \"Akila\",\"Silva\",7798123123)","(\"Sudantha\",\"Gunawardana\",779812456)"]
i want to display this as "Fazaal" "Naufer" 7712345678 likewise
in my function contact is list of tupples :- [("Isuru","Ranaisnghe",123)]
When you show a string, show "hello", the show instance for String adds in quotes, which are escaped when GHCi prints out a data structure.
There are a few solutions, depending on what your goal is. If you just want cleaner output in GHCi then:
putStrLn $ unlines $ displayContacts contact