I am having trouble finding an efficient asynchronous method to test whether an email that a user enters is unique. I don't want to use validates within my controller because I want to present a popup before the user submits the form.
I'm basically trying to do User.find(:all, :conditions => ["email == ?", current_user.email]) but from within the javascript on my html page.
You would need something like this:
A method in your controller that checks email uniqueness, like unique = (User.find(:all, :conditions => ["email == ?", current_user.email])).length == 0. Let it just return JSON like this: render json: unique. No need for a view.
A route to that method.
A function in JavaScript that sends an email to the above route and gets a JSON document in return.
Here's an untested example using jQuery:
function isEmailUnique(email) {
jQuery.get('/my-controller/test-email-uniqueness', email, function(json) {
if (json.unique) {
// Tell the user the email is in use.
}
});
}
That should do it. You'll need to work a little on the structure of the JSON document returned by the controller. Do no return the entire user record since this can give evil people access to stuff they shouldn't have access to. Preferably return something like { 'email': 'user#example.com', 'unique': true }
Hope it helps.
Related
I have a collection of data in a select box, let's say #users = User.all. On change, I would like to get a variable in javascript with the user that is selected, I mean something like this :
$("user_select").change(function(e){
e.preventDefault();
user_id = $(this).val();
user = <%= #user.find(<user_id>) %>
})
Is it possible? Or I have to put the whole collection in javascript variable and get it from there?
Is it possible?
Not like this, no. Your only two options are:
server-side lookup: Make another request to the server, in which you pass user_id and retrieve user data.
client-side lookup: As you mentioned, embed data from all users on the page and simply choose one of them, based on user_id.
I am thinking in a simple way, as #sergio-tulentsev said, what you are trying to do is not posble, but using more js, you don't need to find the user on the rails collection, if you already loaded all the users, then just past them to a javascript variable and on the change event, just select the one from there, something like this.
When you load your page with all the users, just save them on a javascript variable as json
var users = <%= #users.to_json.html_safe %>;
after that, on your event
$("user_select").change(function(e){
e.preventDefault();
user_id = $(this).val();
$.each(users, function(i, u) {
if (u.id == user_id) {
user = u
return;
}
});
})
with that you will have user with a json and all the values of the user there, you can then do something like user.name on javascript to get the values.
I used jquery because in you code example you are using it.
Let's say the user creates a new Person with a few PhoneNumbers. Everything is done through a single form, where you can dynamically add as many PhoneNumbers to the Person as you want. The user clicks the save button and whole form gets submitted to the server, after which a save response comes back from the server.
The important thing is, that i don't want to save the PhoneNumbers separately from the Person. I want the operation to be atomic - everything gets sent together in one request and either everything validates on the server side and gets saved together in one transaction, or nothing gets saved and error data returns.
Right now, to achieve it I have a savePerson action in my controller, where I do awful things like this:
person.get('phoneNumbers').setObjects([]);
phones.forEach((phone) => {
if (!!phone.phone) {
var p = null;
if (!phone.id) {
p = that.store.createRecord('phoneNumber', {
'person': person,
'number': phone.phone
});
person.get('phoneNumbers').pushObject(p);
} else {
p = that.store.peekRecord('phoneNumber', phone.id);
p.person = person;
p.number = phone.phone;
person.get('phoneNumbers').pushObject(p);
}
}
});
{...}
person.save().then(function() {
{...}
that.store.unloadAll('phoneNumber'); //needs to be done to remove records created by createRecord - their saved duplicates will come back after model reload
{...}
})
In the example above, in phones array there are regular non-model objects whose properties are bound to corresponding fields in PhoneNumber subforms in Person form (so in phones[1].phone there is the second phone number dynamically added by the user filling in the Person form).
I also have no idea how to properly handle server-side validation of the embedded objects. To validate the top level object (Person) I return error data compatible with JSON API specification like this:
{
"errors": [
{
"detail": "This value is invalid",
"source": {
"pointer": "data/attributes/firstName"
}
}
{...}
]
}
This works with Ember and eventually I have my errors in model and can retrieve them in the template with {{ get model.errors propertyName }}. But how to return errors referring to the nested objects? I have no idea unfortunately.
I tried to seek various solutions to my conundrums but to no avail. I couldn't find any examples regarding such situations unfortunatelly. But it seems pretty basic. Am I missing something fundamental?
I will be really grateful for any suggestions. Thanks.
Basically trying to modify the user that was just created by giving it an extra field called sid in it's profile object. I'm running this on server.js (the server code)
Accounts.onCreateUser(function (options, user) {
Meteor.users.update({_id: user._id}, {$set: {"user.profile.sid": [post.content]}});
});
console.log(JSON.stringify(user));
However, the user object does not show the sid field in it's output. Am I doing this in the wrong location or is my code wrong?
From the docs
The function you pass will be called with two arguments: options and user. The options argument comes from Accounts.createUser for password-based users or from an external service login flow. options may come from an untrusted client so make sure to validate any values you read from it. The user argument is created on the server and contains a proposed user object with all the automatically generated fields required for the user to log in, including the _id.
The function should return the user document (either the one passed in or a newly-created object) with whatever modifications are desired. The returned document is inserted directly into the Meteor.users collection.
So your code should be:
Accounts.onCreateUser(function (options, user) {
user.profile.sid = [post.content];
return user;
});
However be aware that anything in the user.profile object can be changed by your users.
profile: an Object which the user can create and update with any data. Do not store anything on profile that you wouldn't want the user to edit unless you have a deny rule on the Meteor.users collection.
Try this instead
Accounts.onCreateUser(function (options, user) {
user.profile.sid = [post.content];
return user;
});
From the documentation it reads (http://docs.meteor.com/#/full/accounts_oncreateuser):
The user argument is created on the server and contains a proposed user object...
So at this point it looks like the user does not actually exist in the database yet.
I have a very small Django app, mostly just for learning purposes. I am using the inbuilt User model provided by Django. To learn the functionality, I've created pages which allow me to create and edit users without having to go to the admin panel.
The register page allows me to very easily check for things like password and email validity, as when I POST to a View, I simply use user_form.is_valid() to check the fields are correct (username is less than 30 characters, password less than 128, other conditions...).
For my edit page, I wanted to make the content more responsive so I have made use of AJAX requests via JQuery, allowing me to perform actions without reloading the page. This works great, but it does leave me with the problem of checking validity, as I am not sending the form, I am just using Javascript to pick out the queries and send them in an AJAX request as such:
$.get('/dms/edit_user_changeuser/', {inputNameSend : $("#inputname").val(), usernameToSend : $("#usernameID").val(), emailToSend : $("#emailID").val(),passwordToSend : $("#passwordID").val(), disabledToSend : checkedVal}, function(data){
if(data != "success"){
$("#errorDisplay").show();
}else{
$("#savedDisplay").show();
$("#user_form").hide();
}
});
And this is how the associated View handles it:
#login_required
def user_edit_changeuser(request):
# Like before, get the request's context.
context = RequestContext(request)
inputname = request.GET['inputNameSend']
newUsername = request.GET['usernameToSend']
newEmail = request.GET['emailToSend']
newPassword = request.GET['passwordToSend']
if(request.GET['disabledToSend'] == "true"):
disabledBool = False
else:
disabledBool = True
try:
user_obj = User.objects.get(username=inputname)
print("retUser")
user_obj.username = newUsername
user_obj.email = newEmail
user_obj.is_active = disabledBool
user_obj.set_password(newPassword)
user_obj.save()
print(str(disabledBool))
return HttpResponse("success")
except Exception, e:
return HttpResponse(str(e))
This all works assuming input is valid, but is there something like User.checkValidPassword(newPassword) to manually check validity?
User instances have a method check_password which does exactly what you want it to do
user = User.object.get(username=inputname)
user.checK_password('a_password')
The above checks to see if the current users password matches what is saved in the db. If you were instead asking about validating to make sure the newPassword is valid ie. is the proper length, contains numbers, etc. There is no reason you cannot use a form to validate the user input, just as you would if it were not an AJAX based view
as a side note, it is not necessarly the best thing to catch all exceptions in python. It can mask all sorts of errors that you want to see fail!
if you are expecting that a user might not exist do it explicitly.
try:
user = User.object.get(username=inputname)
except User.DoesNotExist:
# all other expections will not be caught!
I am using javascript to validate the information a user has put into a form. I have two functions in my code which both need to check that the information in two text fields is the same. One function is called when the form is submitted, the other when something is typed into the second field.
However neither function seems to be able to access these variables. Google Developer tools shows their value to be Null. The code works fine when I declare the variables within each function but I thought it should be possible to declare them just once
var user1 = document.getElementById('user1');
var user2 = document.getElementById('user2');
function validateText() {
var message2 = document.getElementById('confirmMessage');
if(user1.value !== user2.value) {
message2.innerHTML = "Your usernames must be the same!";
return false;
}
}
function checkUser() {
//Store the Confimation Message Object ...
var message = document.getElementById('confirmMessage');
//Compare the values in the user field
//and the confirmation field
if(user1.value == user2.value) {
//The usernames match.
// tell the user that they have entered the correct password
message.innerHTML = "Passwords Match!"
}
}
you need to define these variables after the document is loaded.
var user1, user2;
document.onload = function () {
user1 = document.getElementById('user1');
user2 = document.getElementById('user2');
}
If the user1 and user2 elements are created by Javascript or by HTML that is placed after the JS (perhaps you are inserting this JS in the head section) then they still dont exist when you first run your script. This means that the getElementById variables will not find anything and return null.
You need to make sure that you call getElementByID after the apropriate elements have been created. ONe easy way to do that is put the calls inside the validation functions but another possibility would be to put it in an onLoad handler.
I would prefer sticking them in the validators though - getting elements by ID is not an expensive operation (so you don't need to worry about performance) and the closer you fetch the data to when you use it the less stuff to worry about.