Setting up relationship table with Google Places API - geolocation

I am creating an iOS app. I am trying to set up a local table for storing data that is associated with a google place. I am having difficulty figuring out what to use as the primary key.
I read through the google place documentation, http://code.google.com/apis/maps/documentation/places/ and found that I can pass in my current location to retrieve a set of 'reference' id that can be used to get the place details. However, I cannot use that reference id as my primary key because "the same token is not guaranteed to be returned for any given Place across different searches." I want to reference the google place key in my database so that I can form a relationship with other tables in my database.
If I want to store local data based on the relationship of the google place, what would I use as the primary key? For instance, I want to store custom data like how many of my users 'liked' this google place in my database.

Store any reference key as the primary key in the db. now the thing is
A single place can have many reference ids but all reference ids will point to the single location.
eg if paris has 3 reference ids like
1233adasdadsa
2333asdasdads
2334adasdaads
but each reference id will point to paris.
This is called as reverse geocoding.

You should use the reference as the primary key. There is a small chance that the place may change (drift) over time, so the reference is not necessarily guaranteed.
From the API documentation you linked to:
reference contains a unique token that you can use to retrieve additional information about this place in a Place Details request. You can store this token and use it at any time in future to refresh cached data about this Place, but the same token is not guaranteed to be returned for any given Place across different searches.
You can use the id to verify whether you're referencing the same place in your searches. Ultimately, you'll need to set up some logic in your app to determine whether your reference brings up the same place (via ID).

Related

Sort by mutual connections in social-networking iOS application with data store in firestore

I am writing an application that will help users connect to each other based on a number of attributes (i.e. location, interests, etc). I am using firebase firestore to store all of my user data, which has fields like name, hometown, interests, classes, and connections, which is a list of UUID of the users they are connected to.
When I suggest other users for a user to connect with, I want to do so by the number of their mutual connections, however this is not explicitly a field in the database, since I would have to calculate and maintain that for every user in relation to every other user. Is there a way I can use firestore to query or order by a calculated property rather than a field in the database, or another way to store the mutual connections?
I know in theory I could pull all the users from the database and then locally calculate the number of mutual connections and sort the array, but that sounds horribly inefficient.
I have searched for existing solutions such as how facebook or linkedin would suggest friends or people you might know, but I can't find any concrete answers on how they did this, but those companies are not using firestore either. I am hoping someone has had this problem in the past and can help me out.
There is no way to perform a calculation on the data in a Firestore query. If you want to order or filter in a calculated value, you'll have to store that value in the database.
Typically you can either do this:
As you write the data from the client, you also update the calculated values.
In a Cloud Function that triggers when you write the data, and that then updates the calculated values.
In a Cloud Function that runs periodically, and that then updates the calculated values for all modified data.

Store and retrieve unique identifier from Core Data

iOS newb building an app to work with a website. Ultimately, I want to keep the app and backend on the website in sync.
Photos are saved on the website using the ID of the item. For the app, I would also like to save the photo with a unique number linked to the item.
On the website, the id of each item is simply the auto incremented number in a MYSQL table.
My understanding is autoincrementation is impossible in Core Data but it does create unique identifiers for each managed object.
How would I get and store this number in the core data database at the time the item is created for later retrieval?
Alternatively has anyone discovered a way to auto-increment in core data so as to give items numbers that could be used for storing photos. It would be nice to have a similar naming scheme for photos created by the app and those created through the website.
There is no 'built in' solution for creating an auto-incrementing id in Core Data.
One important thing you should recognize is that Core Data is an object graph not a relational database. This is very important in understanding how you should approach design with Core Data.
Yes, Core Data does create unique identifiers for objects in the form of GUIDs - so it's not a number, but rather 32 hexadecimal digits (Globally unigue identifier).
You can write a method that will get the next number in a sequence for an entity, but Core Data will not do it for you.
You may find the information in this question useful: Set auto increment in Core data iOS. I would not attempt to use NSManagedObjectID. This value can change.
My suggestion is that you allow the MySQL database to assign the id's and simply store that id in a number property in the Core Data object. For items originating in the app leave the id property blank until it has been sent to the MySQL database for persistence. Then, retrieve the Id that the database assigned it and set it to the Core Data object's property.

Ruby on Rails - Implementing UUID as Primary Key With Existing Schema

Currently I am creating a RESTful API for a mobile application. The RESTful API has a number of end points that allow users to exchange personal information between each other. I was testing how secure these endpoints were and quickly realized that if a third party managed to gain access to the API they could easily look up other user's information by guessing their user id or using an automated script to collect a wide range of personal information. This was due to the fact that I was using a primary key that was a simple auto-incremented integer which made it predictable and easy to determine other user's ids. I immediately began looking for something that didn't follow a distinct pattern. I came across UUIDs and decided to implement them with my existing rails app.
Was this a wise decision? I definitely see the upside to using UUIDs but upon further research I found that there were a number of negatives to this approach. Many sources claim that using UUIDs will cause performance issues with large tables. Are UUIDs right for my situation?
My second question is about implementing this in an existing Ruby on Rails application. I made the switch to UUIDs by following this article: http://rny.io/rails/postgresql/2013/07/27/use-uuids-in-rails-4-with-postgresql.html. I ran into an issue with enabling the uuid-ossp extension. I created a migration and put enable_extension 'uuid-ossp' inside the change function. I then changed the existing migrations to support UUIDs as their primary key and ran rake db:drop db:create db:migrate to recreate the database with the edited migrations. This failed with the error PG::UndefinedFunction: ERROR: function uuid_generate_v4() does not exist. I quickly realized that this was because I had created the migration that enabled the uuid-ossp extension after the migrations that I had edited to use UUIDs. When I changed the time stamp in the name of the migration to a date that preceded all migrations the db:migrate command completed with no errors. This felt very hack and defeated the purpose of having migrations. What is the correct way of adding this extension via a migration?
Edit in response to comments:
So a number of comments were made that suggested that I should just be properly authenticating users and checking their permissions before allowing them to view certain data. I have user authentication built into my application but will better explain my situation and why I needed something more than auto-incremented primary keys.
I have a number of users on this application and each user has the ability to create private and public contacts. Public contacts are viewable by everyone using the mobile application. Private contacts can only be viewed by the user who created them. However, a user can share their private contacts with other users by showing other users with the mobile application a QR code that has the contacts ID encoded into it. When the user decodes the contact ID a request is sent to the backend to notify the backend that the user is now an owner of that private contact. This allows the second user to now receive updates from that private contact. This is a large feature of my application. The aim here is to force people to have to exchange these contacts in person and to disallow others from seeing these contacts unless this process has happened.
Implementing this concept proved to be fairly tricky as all users could potentially share all private contacts with any other user on the system. I found this extremely hard to implement using permissions as which contacts a user can view is constantly changing.
Originally I implemented this with auto-incremented integers as my primary key for the contact IDs. It worked but forced me to create a very insecure API endpoint that essentially would take a user ID and a private contact ID as parameters and would add that user as an owner of that contact. Because auto-incremented IDs are so predictable a user with access to the API could essentially loop through a sequence of numbers calling the endpoint each time, pass the sequence number in as the contact ID and add themselves as owners to contacts that hadn't been shared with them. This would by pass the whole process of having to share the contact in person and in large defeats the purpose of having my mobile application.
I decided I needed something less predictable, completely random and unique to each private contact. I found UUIDs while doing research to solve this problem and changed the contact ID in my model to be of type UUID. Are UUIDs the best way to solve this? Should I use something else? Have I gone about solving this problem the wrong way?
Are UUIDs the best way to solve this?
You could use them as a solution. If you do, you should build a new contacts table and model instead of trying to migrate the old model. As well as being tricky to implement, any migration would immediately make existing contact/invite emails invalid (since they contain the old id). Briefly support both models, and retire the old auto-incrementing id model once you are happy that traffic using it is no longer important to your application.
There is still a flaw - your contact share links will now be long-lasting, and if anyone gets access to a contact's id for any reason, and know enough to construct the URL for gaining that user as a contact, then they gain the ability to share it to themselves and anyone else completely outside of the control of your application. This because you are relying on knowledge of the id as the only thing preventing access to the contact details.
Should I use something else?
In my opinion, yes. Use a separate nonce or one-off code model (with UUIDs, or an indexed column containing a long random string - you could use SecureRandom for this) that can grant rights to complete the sharing. When someone wants to share a contact, create the nonce object with details about what is being shared - e.g. the contact_id - and use it to generate email link pointing to a route that will find the nonce and allow access to the resource.
The model doesn't need to be called "Nonce" or contain that as a column, this is just a common name for the pattern. Instead you might call the new model "ContactShare" and the secret property "link_code".
This will allow you to resolve access to contacts using your app's permissions model as normal, and block the possible misuse of sharing links. When the controller with the nonce id or code is invoked, create permissions at that point in order to grant access to the contacts. Then expire or delete the nonce, so it cannot be re-used. I prefer expiry, so you can track usage - this can be as simple as a used boolean column that you update once the sharing request has succeeded.
Note I am not referring to Rack::Auth::Digest nonce routine, which is specific to server authentication. I did not find a RoR pre-built nonce model, but it is possible it goes under a different name.

Keep reference of ABPerson in CoreData

I'm trying to keep the phone's contacts in my app up to date, in a persistent way. For that I'm thinking of using Core Data.
My plan right now seems highly suboptimal :
Browse the address book and every ABPerson in it
Store every field in a CoreData persistent store
Store the image in a separate file with an unique name and a reference in another "Contact" field.
And I do this every time the app comes in foreground in case the user would change one of his contact's name or picture, etc.
Some of my users have more than 2500 contacts, sometimes the operation lasts up to 10 seconds.
My question is :
Is there a way to keep some kind of reference to my ABPerson in coredata, so I can always load my ABPerson properties everywhere instead of Contact properties? (which would then always be up to date).
And I'm not even sure it's the right decision :
Should I always use the ABRecord that I find with a reference?
Should I always use my own copied data that I update regularly (from the ABAddressBook)?
If not, do you guys think I'm doing this in a decent way or would you suggest something else?
EDIT:
As asked in the comments:
I need to keep the contacts up to date simply to use their firstname, lastname and picture properties. If I notice the ABRecord changes, I'll update the related custom objects accordingly and that's it. I won't really need anything else afterwards (until they're edited again)
Thanks
Obtain and store only the ABRecord's unique identifier value. This is the one persistent way to reliably refer to the same person repeatedly and consistently.
You can always get all the other info out of the contacts database by using this unique identifier.
In iOS, call ABRecordGetRecordID to obtain the person's unique ID. Store that. When you later want to obtain the corresponding person, call ABAddressBookGetPersonWithRecordID.

What is the right way to handle permalinks when the page depends on the session?

Here's the situation: I've got an application where you begin at a screen showing a list of countries. You choose a country, and this becomes the ambient country that the application uses until you change it. This ambient country is stored in the Session so the application doesn't have to pass around a CountryId in every single url. But I also want to support permalinks to country specific content, so I guess there needs to be a "Get Permalink" button, which creates a permalink that does contain the CountryId, because it obviously has to work independent of the current session.
Here's the question: My understanding is that because selecting a country changes the session state, one should only do it via POST. But then if the user comes in via GET with a permalink containing, e.g. CountryId=123, what should happen? Should the page update the Session with country 123? In this case, it would be breaking the rule that you can change the session ONLY via POST. But if it doesn't change the session, then all the code that relies on the session won't work, and I'd have to have code redundant ways to generate the page.
OR, should the page have some sort of mechanism for saying "use the session value, but override with any query string value if there is one (and don't modify the session at all)?
OR, am I misunderstanding the POST rule entirely?
The real issue here is the fact that you are using a Session. You cannot provide permalinks because the data that you have stored in the session might have expired when the user follows this links later. So you must somehow persist this data into a more durable datastore when someone requests you to generate a permalink. So when a user asks for a permalink you will go ahead and persist all those search criteria that were used to perform the search into your data store and obtain an unique id that will allow you to fetch them later. Then give the user the following permalink: /controller/search/id where the id represents the unique identifier tat will allow you to fetch the criteria from your data store, perform the search and reconstruct the page as it was.

Resources