How in Sinatra would I check that the term the user has input into a form already exists in your database? - sql

Making a budget app while learning to use Ruby/Sinatra/SQL. Part of it involves letting the user add new vendors that they can assign transactions to. My add transaction and add vendor functions both work, but one thing I'd like to do is be able to throw up an error if the vendor that the user is trying to add - eg 'Amazon' is already in the database, before returning to my index of vendors.
The closest that I've come to getting something working is making the name column of the vendor table UNIQUE. But if I enter a name that's already in existence in the field, I get the "PG::UniqueViolation" error.
Is there a way to tell Sinatra that you don't want this error to flag up, you just want to redirect back to the index of vendors without the repeated value.
My working submission form currently looks like:
<div id="new-transaction">
<form action="/vendors/create" method="POST">
<label for="name">New vendor name:</label>
<input type="text" name="name" id="vendorName" />
<input type="submit" value="Add new vendor" id="btn-new-vendor">
</form>
</div>

Go ahead and use that error as a response to work with in your app. You can add a begin/rescue/end block to your method:
# some code before
begin
DB.add_your_vendor_method
rescue
go_back_to_index
end
show_value_to_user
# some code after
You can make that block error specific, too. There is some nice write up on ruby error handling over at http://rubylearning.com/satishtalim/ruby_exceptions.html

Related

Assertion error when IDs are same for different behaviors of an element

I am dabbling with a Role based access situation and am sort of stuck on the assertion.
For the Full Access the field is like so
<input class="clickable_input clickable_timeholder ui-autocomplete-input ui-widget ui-widget-content ui-corner-left hidden" data-old-value="12:00 am" type="text" value="12:00 am" name="program_constraint[event_window_constraints_attributes][0][local_start_time]" id="program_constraint_event_window_constraints_attributes_0_local_start_time" autocomplete="off" role="textbox" aria-autocomplete="list" aria-haspopup="true">
For the Readonly access the field is like so
<input class="hidden clickable_input clickable_timeholder" data-old-value="12:00 am" type="text" value="12:00 am" name="program_constraint[event_window_constraints_attributes][0][local_start_time]" id="program_constraint_event_window_constraints_attributes_0_local_start_time"></input>
I would like to work with only 1 selector that is the one with the full access and then check for exists or not to pass or fail the case.
I end up with the below assertion error primarily because both the conditions use the same ID and the only difference is in their class name. I have not found a good example yet to handle this. Being still a week old into working w/TestCafe, I understand the DOM model perfectly fine, I can't seem to quite incorporate this into a page model effectively and keep hitting a wall.
expected true to be falsy
This is my Selector definition in the page model:
this.eventWindowStartTime = Selector("#program_constraint_event_window_constraints_attributes_0_local_start_time")
my Test code for the assertion
await t.expect(programOptionsConstraintsPage.eventWindowStartTime.exists).notOk()
You can use the filter method to find only an element with a particular css class.
For example:
Selector('#input_id').filter('.ui-widget')

Vue.js if statement with two variables

I need to check if the current user is the author of the question to allow him to see/use the delete question button.
But with my implementation I can´t see the button at all:
<form #submit.prevent="deleteQuestion(question.id)">
<input type="submit" v-if="this.currentUser === question.author" value="Löschen"/>
</form>
I get question.author with a JSON request , currentUser is set during the login.
Thanks for taking the time,
Fierl.
this.currentUser and question.author are not the same objects, even though they might contain the same data. This is why the comparison fails.
Your user objects probably have an id property (or some other primary key). Compare against that instead.
<input type="submit" v-if="this.currentUser.id === question.author.id" value="Löschen"/>

Selenium access a form field with bad id

Looking for the best approach to enter / read a value from a form field that lacks human readable ids / references.
The basic outline looks like
<div id="form-2143">
<div id="numberfield-1234">
<label id="numberfield-1234-label">
<span class="x-form-label">Field Name 1</span>
</label>
<div id="numberfield-1234-body">
<div id="numberfield-1234-wrap">
<input id="numberfield-1234-input" class="form-field" componentid="numberfield-1234">
</div>
</div>
</div>
...
</div>
There are more class defs and attributes involved, but above is the "basics" I have to work with.
This form has a number of entries, and there are more forms like it, so I am looking for a way to search for the label name, and access the input field within the same container.
I lack control of the site and cannot edit the HTML structure of the site; meaning I cannot give sensible names to the ids, but want to avoid hard referencing the poor names. Any suggestions on how to get Robot Framework & selenium to reference these elements?
Highlighting Andersson's answer in the comments
Using the XPath
//label[span[text()="Field Name 1"]]/following-sibling::div//input
Works for the above example.
The key part that answers the question of how to reference nearby elements is
/following-sibling

flask - user input (login/password) to a python variable

I'm trying to learn about login/password/user session stuff in flask.
i found this link and have been trying to understand the code it provides (on the bottom of the page, the largest piece of code).
http://thecircuitnerd.com/flask-login-tokens/
The link doesn't provide, though, the contents of the login.html file.
So far, the way i've been handling forms in flask requires me to specify to the render_template function what user input will be attributed to each python variable. But since the author didn't do it, i suppose his method of getting the user input should be different than that.
If you look at the login route handler in the code you linked you'll see that it uses request.form to get out two variables, 'username' and 'password':
#app.route("/login/", methods=["GET", "POST"])
def login_page():
"""
Web Page to Display Login Form and process form.
"""
if request.method == "POST":
user = User.get(request.form['username'])
#If we found a user based on username then compare that the submitted
#password matches the password in the database. The password is stored
#is a slated hash format, so you must hash the password before comparing
#it.
if user and hash_pass(request.form['password']) == user.password:
login_user(user, remember=True)
return redirect(request.args.get("next") or "/")
return render_template("login.html")
The simplest way to do this would be with the following HTML:
<form action="/login/" method="POST">
<input name="username" placeholder="username">
<input type="password" name="password" placeholder="password">
<input type="submit" value="Login">
</form>
This will not re-populate the username if the user mis-types their username or password, nor will it give the user any indication that they failed to login. They will just see the login form again. However, this is just some example code, so it's understandable that the author chose to leave out useful code that would obscure the point he was trying to make.

HTML text input and using the input as a variable in a script(tcl)/sql(sqlite)

I'm very VERY new at this whole web thing. And I'm just very confused in general. Basically, what I want to do is take an input via text using HTML and adding that input to database, table trans. Should be simple but I am lost.
<li>Transaction Number</li>
<li><input type=|text| name=|tnumber| </li> // do i need to use value?
<li>Employee Name</li>
<li><input type=|text| name=|ename| </li>
<li><input type=|SUBMIT| value=|Add|></li>
......
......
sqlite3 db $::env(ROOT)/database.db
db eval {INSERT INTO trans VALUES ($tnumber, $ename)}
db close
They are both in a same file and there are only two fields to the database to keep things simple. What I can see here is that tnumber and ename aren't declared as variables. So how do I do that so that the text input is assigned to respective variables?
You're after the ncgi package (in Tcllib), which you can use to decode the values in the form and extract them into variables. To do this, you'd have a webpage with a form like this:
<form method="POST" action="/cgi-bin/addTransaction.tcl">
<li>Transaction Number: <input type="text" name="tnumber">
<li>Employee Name: <input type="text" name="ename">
<li><input type="submit" value="Add">
</form>
(I'll not go into much more depth with the details of writing a form on a webpage.)
Then, in your program (addTransaction.tcl) you do something like this:
package require ncgi
package require sqlite3
ncgi::parse
set xact [ncgi::value "tnumber"]
set name [ncgi::value "ename"]
sqlite3 db $::env(ROOT)/database.db
db eval {INSERT INTO trans VALUES ($xact, $name)}
db close
Note that I've changed the names of the variables to be different from the ones in the webform. This is to show that they do not need to be the same. A few other things to note are that you can make the transaction number field optional (supply a default via the second optional argument to ncgi::value) and it might also be better to do generation of transaction ids in the database (but that's another separate question; I've focussed in this answer on how to couple from the web into SQLite).
Of more interest is the fact that the above code is free of SQL injection attacks. However, whenever you come to taking the contents of the database and sending it back out to the web, you'll need to be careful again or you'll leave open XSS attacks. That's when the html package (Tcllib again) is useful, since it lets you generate correct hazard-free output with minimal effort. But that's another question...