Friends list on Firebase - ios

So far on my firebase I have something like:
Users
293840ajldkjfas0d9
username: Jill
09283049802930laks
username: Jack
I'm basically going to just have a text field and when someone hits the "add" button, a search through firebase gets done to make sure that username exists, and go from there on connecting the two as friends.
My question is I'm not understanding how I would sort through my data if it's structured like this? I might be totally missing something but is there a way to search through what I have now and say "Go to my users reference, go to through each UID and pull out the username and see if it matches what the user put in the text field, and if so grab the UID connected to the username"?
I'm almost thinking I need to have an entirely separate branch? that I have in addition to what I already have that looks like
Usernames
Jack
09283049802930laks
Jill
lasdjf9j09u90320j09
Which would then allow me to just go to my usernames and go through and check through the values inside that (jack/Jill) and then if it exists then pull that uid out of the username.
1) Do I need both of these branches or is there a way to accomplish what I'm trying to do with just my first?
2) How exactly do I check for that match? Would a query be used or just checking for Null somehow?
3) Is this even the right way to go about doing this? I've found little to no information on friends lists online so this is just all an assumption.
Any help is appreciated!

Using the below structure, you can check if a user exists with a single query. Here's all the code you need:
This is the db structure:
Users
293840ajldkjfas0d9
username: Jill
09283049802930laks
username: Jack
Here is the code:
var usernameEntered = self.usernameField.text!
var databaseReferenceQuery = self.ref.child("users").queryOrderedByChild("username").queryEqualToValue(usernameEntered).observeSingleEventOfType(.Value, withBlock: { (snapshot) in
if ( snapshot.value is NSNull ) {
// No user :(
} else {
// User exists! Do stuff!
}
}, withCancelBlock: { (error) in
// An error occurred
})
Once you have established a user exists, I can think of a few ways to go about getting the uid. The key is to find a place where both the uid and the username are stored.
Option 1:
Create another branch in the users db structure that stores the uid.
Set up this branch when the user is signed up.
Option 2:
Store the username as the displayName in the standard auth system and get the uid from there.
Set this up when the user signs up.
That's up to you.
Response to comments:
You can simply retrieve the key of the user in the table, however this will not allow access to any auth features and will not allow user accounts to be edited in any way.
Examples of situations where this can be useful include updating user info, deleting accounts etc.

Related

Swift Firebase update old data - Real Time Database Triggers

In the below image I have messages in my app, yet when a user say updates their profile image or name the data below becomes stale data. I have come across "Firebase Functions" and see that I can keep this data in-sync if I use Firebase Functions. Yet, only knowing Swift I am unsure how to implement Firebase Functions to keep my messages in-sync which the changing data in the user profiles. Can someone help me point in the right direction on how I implement this into my project? Haven't found any sample code in swift or any tutorials for that matter. Any help is greatly appreciated!
Based on the comments and the structure in the question, the reason the data is becoming stale is due to how the data is stored in Firebase.
One option is that when a message is sent, a node is written with the message and then a reference to the senders info. That keeps everything fresh and up-to-date at all times
So say we have a users node with users stored with the users UID as the key to each node
users
uid_0
user_name: "Peter"
user_age: "32"
gender: "Male"
business_name: "Peter's Plumbing Place"
url: "http:...."
type: "Customer"
uid_1
user_name: "Ralph"
user_age: "47"
gener: "Male"
business_name: "Ralph's Repair Room"
url: "http:...."
type: "Employee"
then we have messages
messages
msg_0
msg_text: "Here's a message!"
from_uid: "uid_0"
to_uid: "uid_1"
timestamp: "20180110"
Then, user uid_1 adds a query observer to the messages node for any messages where to_uid is uid_1 so they are notified of the incoming message. When they receive it, they will also know it was sent by uid_0 and can pull up their name, profile image, age etc.
That way, all data is kept in sync and current and no stale data exists.
This is a typical implementation of a structure for a messaging app.

Rails 5.1 has_many through - associated fields

(See example schema image below)
I am attempting to query a single user from the users table using the email field, along with the id & key fields from the applications table. The results should contain the user found (if any), along with the application (referenced using the key & id fields) and the applications_users associated data.
I can easily write SQL manually to perform this operation:
SELECT
"users".*,
"applications_users"."scopes",
"jwt_applications".*
FROM
"users"
INNER JOIN
"applications_users" ON "applications_users"."user_id" = "users"."id"
INNER JOIN
"jwt_applications" ON "jwt_applications"."id" = "applications_users"."application_id"
WHERE
"users"."email" = 'rainbows#unicorns.net'
AND "jwt_applications"."id" = '01daafc9-2169-4c78-83e9-37ac0a473e3d'
AND "jwt_applications"."key" = 'follow_the_rainbow'
LIMIT 1
However, I cannot for the life of me get the query correct when using ActiveRecord.
These are the unsuccessful attempts I have made thus far:
user = User.where(email: args[:username]).joins(:applications).merge(
JwtApplication.where(id: args[:application][:id], key: args[:application][:key])
).take!
This gets the user correctly, however Rails performs a second SQL query when I attempt to access user.applications (and it also returns all applications associated with the user; so it appears to disregard the id & key conditions)
user = User.where(email: args[:username]).joins(:applications).merge(
JwtApplication.where(id: args[:application][:id], key: args[:application][:key])
).references(:applications_users).take!
This gets the user correctly and also the correct application (yay!), however Rails performs a second SQL query if I attempt to call user.applications_users -- it also returns a collection for all data inside the applications_users table (again, disregarding the id & key conditions)
user = User.where(email: args[:username]).joins(:applications).where(
jwt_applications: {
id: args[:application][:id],
key: args[:application][:key]
}
).take!
This gets the correct user, however Rails performs another SQL query when I attempt to access user.applications -- also returning all applications.
Anyway, hopefully a Rails genius can shed some light on this question! I will be the first to admit that I am by no means a Rails expert; I have spent the last 10 years of my professional career coding in PHP & C++, so please bear with me if this comes off as a stupid question :)
Not sure if this is something you're looking for but...
You can write ActiveRecord query like (join model should be implicitly added to your query):
User.joins(:applications).where(email: email).where(applications: { key: key, id: id})
Where email, key and id as params to pass to the query.
On top of that query you can use select fields to get everything you need:
user = User.joins(:applications).where(email: email).where(applications: { key: key, id: id}).select('users.*, applications.id as appid applications.key as appkey').first
That will give you back the user model (if present) or empty relation if nothing matches your criteria.
You can then call the fields like
user.appid
user.appkey
You can always call select ('users.*, application_users.scopes, applications.*) which will return you all the fields in single instance (still under User model) BUT duplicate fields like id will only be shown once, that's why it's better to grab just the fields you want and give them unique identifiers like I've shown with appid and appkey.
Again, might not be exactly what you're after, but hopefully it points you in the right direction!

Conditionals in an Active Record query

I have a large database of information. They are mostly patients. Some of them have email addresses and some of them don't. I can pull an additional email address by simply running
Patient.last.email
However I only want to see the patients who do not have email addresses. (I think its about half of the ones that I have)
I've tried both these below, but not having the best of luck.
Patient.includes(:email).where('email = ?', 'nil')
Patient.includes(:email).where('email = ?' 'nil').references(:email)
Would anyone know what I'm doing wrong?
Simple then.
Patient.where(email: nil)
Should get you your result.

How checking value from DB table?

I want create a simple checking value from database. Here is my code:
def check_user_name(name, email)
db_name = Customers.find_by_name(name).to_s
db_email = Customers.find_by_email(email).to_s
if name == db_name && email == db_email
return 'yes'
else
return 'no'
end
end
But I have allways 'no' variant....why ?
Because you are calling to_s on your Customers model and not actually getting the name. The two fetch lines you have should be:
Customers.find_by_name(name).name.to_s # to_s probably not necessary if you know this field is a string
Customers.find_by_email(email).email
But, you're making two separate requests to the database. I don't know what the purpose of this is (as you could be selecting two different Customers) but you could do:
if Customers.where(name: name, email: email).exists?
"yes"
else
"no"
end
Since you are, however, selecting by name and email - I would highly recommend that you make sure those fields are indexed because large tables with those requests will bog the server and make that route rather slow (I would actually recommend that you pursue other routes that are more viable, but I wanted to mention this).
When you give Customers.find_by_name(name), you will not get name of a customer. Actually it will return activerecord object, so from this object you need to get the name and email of a customer, like below,
name = Customers.find_by_name(name).name
email = Customers.find_by_email(email).email
Now you will get the exact name and email of matched data from DB.

Ejabber structures and roster

I'm a new to ejabberd but the first thing I noticed is the completely absence of documentation and code comments.
I have many doubts, but the main are:
inside the record jid what is the difference between user and luser, server and lserver, ... and ...?
-record(jid, {user, server, resource,
luser, lserver, lresource}).
what is useful for the record iq?
-record(iq, {id = "",
type,
xmlns = "",
lang = "",
sub_el}).
what is a subscription inside ejabber? a relation between two users?
what is the jid inside the roster?
I know that these questions can be also quite stupid, but I don't really know how to understand without asking, thanks
what is the difference between user and luser?
luser,lserver and lresource are the corresponding parts of the jid after being processed with the appropiate stringprep profile. See https://www.rfc-editor.org/rfc/rfc3920#section-3 . In short, inside ejabberd you will most likely always use the processed versions, and the raw ones only when serializing the JID back to the wire.
what is useful for the record iq?
it make it easier to match on the IQ namespace, id or type (get|set|error) than to retrieve that info from the underling xml each time.
what is a subscription inside ejabber? a relation between two users?
basically, yes. A subscription from user A to user B means A is interested in B presence. But the subscription can be in different states (as the other user has to accept it, etc.). See http://xmpp.org/rfcs/rfc3921.html#sub .
what is the jid inside the roster?
sorry, didn't understand you on that, what do you want to know?

Resources