How to pull data from Facebook hash with multiple entries with Ruby - ruby-on-rails-3

I have used OmniAuth to connect with Facebook. I am pulling various pieces of information and have no problem pulling information where there is only one type of it. For example, to get the email address, I just place the following in user.rb:
user.email = auth["info"]["email"]
The problem is with multiple entries. For example, for education, there are two results. One is a High School named Punahou School while the other is a College named University of Illinois at Urbana-Champaign.
education:
- !map:Hashie::Mash
school: !map:Hashie::Mash
id: "105510192816251"
name: Punahou School
type: High School
- !map:Hashie::Mash
school: !map:Hashie::Mash
id: "163536409904"
name: University of Illinois at Urbana-Champaign
type: College
I was able to pull the first school using:
if auth["extra"]["raw_info"]["education"]
user.school = auth["extra"]["raw_info"]["education"][0]["school"]["name"]
end
The problem with this is, it only pulls the first school which is the high school. I have a couple of questions here:
If I only want the College, how would I get it to pull University of Illinois at Urbana-Champaign? If there is a high school and college, I would want the code to only pick up whatever school is the college.
Now, let's say I want both the high school and college. How would I pull both and how would I mark that Punahou is the high school and UIUC is the college?
If there are multiple colleges, how would I pull the most recent college entry?

Had a similar question with OmniAuth and LinkedIn, came across your question and it helped me come up with a solution. LinkedIn's hash returns the three current positions in a form similar to Facebook's behavior above. Change [0] to [1] and it will pull the college in your example. Use separate lines for each entry you want. I found the LinkedIn hash returned the three current positions in order with the most recent entry being in the [0] position.

Related

How should I design my RESTful API in this case?

I've got a DB with a lot of people of type (PLAYER, DOCTOR, TEACHER) where each person has an ID and location ID. There're some common fields like first name, last name but also some fields that are specific on person's occupation: number of injuries / the most serious injury type for PLAYER, number of patients for DOCTOR and can_teach_math for TEACHER.
I want to build an API to compute total compensation of all these people that accepts a list of IDs (optional), list of location IDs (optional). For example, if someone passes 3 personIDm API should return a response with an array where each row corresponds to a specific person. If someone passes locationIDs - API should return all people who are living in that area.
Originally, I was thinking I could just return people ID:
request = {..., person_id:[person-123, person-456], location_id = [location-1, location-2]}
response = {
[person_id:person-123, first_name=Alex, compensation=100],
[person_id:person-456, first_name=Alex2, compensation=102],
# anyone who lives in location-1, location-2
[person_id:person-13, first_name=Alex3, compensation=50],
[person_id:person-12, first_name=Alex4, compensation=52],
}
However UI engineer showed up and said they want to see
also some fields that are specific on person's occupation: number of injuries / the most serious injury type for PLAYER, number of patients for DOCTOR and can_teach_math for TEACHER.
in a response even though it makes API denormalized. That said, it makes sense to me since loading all the object info through GET persons/{ID} might take quite a long time. Without going too much of the details, let's see we don't care about speed -- is the proper way to design RESTful API is not to return
also some fields that are specific on person's occupation: number of injuries / the most serious injury type for PLAYER, number of patients for DOCTOR and can_teach_math for TEACHER.

Database structure for students, every student has first name, last name, current reading lvl, last reading meeting date , last writing date

I am basically creating a spring boot project and need the structure of the database.
there are different tables i need to show on certain pages:
A page that shows all class students
so the columns would be:
their name
current reading level
data of last reading
meeting date of last writing meeting
A page that shows the Reading section
each row will be a student, so columns would be:
student name
current reading level
date of last reading meeting
next step
A page same for writing like reading
each row will be a student, so columns would be:
student name
current reading level
date of last writing meeting
next step
A page for a student for reading
this will be for an individual student for reading, so columns are:
date
reading level
type of conference
strength
teaching point
next step
A page for a student for writing
this will be for an individual student for writing, so columns are:
date
writing level
type of conference
strength
teaching point
next step
I am sorry if this is a noobish question, i really needed to start the project right because that's an actual thing that i want my wife who is a teacher to use for her class

Will First Name + Last Name + Date Of Birth combination be unique enough?

I need help with the algorithms/ database design for my current working on web-based application (I apologize for the long question in advance)
Application description:
I am building a customer check-in station (it's basically just a monitor that displays a webpage and was connected to a scanner) where customers who come into an office (similar to a library) can scan their office ID card (it has an unique bar code on it) to check-in, customer information (First name, Last name, date of birth, check-in time...) will be sent/saved onto server and the office administrator will be able to see who is in the office right now and do stuff...)
When creating ID card for a new customer, the only information needed is: first name, last name and date of birth (customer can be any ages from kids to elder) => system will generate a unique bar-code (16 digits) and print out a new ID card (with only the bar-code on it)
Problem:
If a customer forgot/ lost their ID card or sometimes the card is too old so the bar-code can't be scanned, customer can type in their first+last name and date of birth into the check-in station then system will search for (first name + last name + date of birth) and determine whether that customer existing and check them in. But it is possible that there is more than one person who has same name + birthday:
- system then can display all matched people to screen but how can customer know which one is them self?
- or that situation can be avoided if system would not allowing customer who has same name and dob to be saved the to database in first place. But then the customer who came "second" will be very upset that he/she can not have a card :))
Edit:
How do I deal with this problem, I mean this is just a office so we can not ask for SSN or driver license ... the check-in process have to be simple and quick some of them maybe a kids who don't have any ID or phone (they will come with their parents/guardians) and many of them are older people (older than 70, or even 80) they can't even type that why the "ID card - scanning idea is here to help them - all they need to do is scan their card... (I don't think they ever can remember the "security question"), SMS verify will not work (phone number may be changed, not all of customer have a phone, the carrier will be involved here (coverage, rate charge...) I don't want any of that ).
OK after read all your suggestion:
I am thinking about a 4 digit pass-code (like 3 digits security code in the back of a credit card) - it will be printed out in the ID card with the instructions and everything, this will be different from the unique customer number (used to scan), here how it works:
- when creating a new customer ID card, system will ask for an additional 4 digits pass-code and also print it out to the card, an algorithms also will be put there to make sure that customers who have same name + dob can't have same pass-code.
In case customer can't use/lost the card, after they entering name+dob to check-in, system only ask this 4-digit passcode if there are more than 1 matched person, otherwise if there is only 1 person matched, system will check-in them in right on.
if they ever forgot this pass code, I mean there is nothing else they can do for them self, the receptionist will have to somehow help them, what do you guys think, I am still open for suggestions?
My final solution:
Because the cards have nothing else (of customer information) rather than the bar code (customer number) on it so the best way is to preprint (pre-made)them, have them ready in the desk to give to new customers or for card replacement purposes.
When creating a new customer, receptionist will manually input first name + last name + dob + phone number (optional) + email (optional) + home address + customer number (as same as in the card that they about to give to the customer) +. submit, system will check for everything, if everything is good receptionist then give customer a new card => customer come back to check-in station and check-in.
When customers forgot card => they will need to see the receptionist => do verification process => receptionist will check them in manually.
When customer lost card or card is damaged => they will need to see the receptionist => do verification process => receptionist then give customer a replacement card => customer come back to check-in station and check-in.
Have each customer tell you two "security question" style data: Location of birth, favorite dish, ... These can serve as uniquifiers.
You can then prevent duplicates from being entered because in case there is a colliding registration the customer must simply chose a different question.
Some rambling thoughts:
You could assign users a PIN and use that to make the account unique. Presumably to insure that it is unique you would have to assign it, you can't let them invent one. (You could let them invent one and then verify it's unique. That might be good to allow people to use numbers that have some meaning to them so they can remember them.) The big catch to this is that if the person loses his PIN, you're stuck. If the PIN is printed on the card, then if the card is damaged or worn, yes, they could type in the PIN. But if they lost the card, they might have no other record of the PIN.
You could ask for their phone number and use that as an identifier. My grocery store does that for their discount card. I think almost everyone has a phone these days. For the small number who don't, you could generate a random number that looks like a phone number but is not valid (so it won't coincidentally duplicate any real phone number), and use it like a PIN. For example if you're in the US, you could make generated numbers all start 555-555 and then make the last 4 digits be like a PIN. Then the only people who would be a problem are those who don't have a phone AND who lost their card, which should be a very small number.
Is there any information in this system that is confidential, or are people committing to spending money? I mean, if someone walked up to a kiosk and typed in the name and birth-date of his next door neighbor and accessed that person's account, would that be a problem? You haven't said what the system does. If getting into the system gives someone access to the person's medical records or bank account or transcripts of his last confession to his priest, then you have to take steps to prevent unauthorized access, you can't let just anyone come up and claim to be someone else and get in. I'm reminded of a case a few years ago where a reporter got access to records of some politician's DVD rentals. He was apparently hoping to find that he had rented a lot of vile pornography or some such that he could use to embarrass the guy, though as it turned out it was mostly westerns. My point is that even seemingly innocent information could be embarrassing to someone under the right circumstances, so you have to be careful.
How often do people have lost or damaged cards? And are there clerks available who could help someone in such cases? That is, if 99% of the time someone comes in, swipes his card, and he's in and everything is good, and the number of times that someone has a lost or damaged card is very small, you could say that in those cases they have to go to a clerk and show the damaged card, or if they say they lost their card, show identification. Then the clerk can verify whatever and give them a new card. You could have the clerk search by name and have a screen that shows birth dates and addresses, ask the customer what their birth date and address is and if it matches one, give them a new card, if not, say I'm sorry you're not on file. This is quite different from a security point of view of showing the customer the list of birth dates and addresses and letting them pick one, as a customer could, (a) type in a common or overheard name and then pick any matching entry that shows up, or even (b) use this to find the address of someone they want to harass, and then you could be liable.
On the current project I met the same way to find a customer. The project is about TV stuff, so the second level of 'sieve' is address. And I think you need to expand the customer information: a username, an email, an avatar or something easy to remember (or send a SMS with code). Also you can add user friendly behavior: if a customer cannot decide which record about him/her, the customer should go through the wizard and add needed information. Yes, it's hard to find a general evidence for all customers, but you can support several kinds of extra information.
In other words: first name, last name, and birth date aren't enough for unambiguously getting a person.

Single Table Inheritance (STI)... Multi Table Inheritance (MTI)... Polymorphic Associations

So I have found MANY posts on these subjects but none have answered my (probably very novice) question. I am brand new to Rails this month but I have been programming in OOL for a little while. I think my question might span multiple subjects about Ruby on Rails. I don't mind reading multiple blogs or tutorials to peace this all together.
I have 4 location models. Each have a "Name" attribute.
Country (has_many :states)
State (belongs_to :country has_many :counties has_many :cities, :through => :counties)
County (belongs_to :state has_many :cities)
City
My end goal is to have an autocomplete textbox for city, county, state. The user will select a country to narrow down the results. For example, the user will type in "SA" and the autocomplete textbox will show:
Kansas
Arkansas
Santa Clara County, California
San Jose, Santa Clara County, California
etc.
So I can easily return the text that I want displayed. Each model has something like:
def location_name
// the display name of this model. For example we want the County Model to return "Santa Clara County, California"
"#{name}, #{state.name}"
end
Solutions I tried to research:
Active Record Query Interface to make one select statement across the multiple tables. My goal would be to search across multiple models and get a single list of objects with the name containing the search text.
STI - Maybe create a Location model which all can inherit from but I couldn't find any basic tutorial online that include models with different attributes for each. Do I "generate" one model with all the fields that all 5 would need then just delete them from the auto generated .rb file? I assume I will then be able to use Location.where("name like ? and country_id = ?", params[:search], params[:country_id]) and get a full list of all location which fit the search parameters.
MTI - I looked at this since I'm not a big fan of excess columns in the DB that are mostly blank. For example :country_id would only be used by states. So it would be null for all counties and cities, etc. But all the tutorial seem to imply that STI would be the better way to go.
Polymorphic Associations - I just started looking into this a few hours ago. I found something about ":polymorphic => true" and I read another article that talked about a subclass feature.
I have spent quite a few days looking into the "right" way of doing this according to Ruby. I'd really like to learn and incorporate all that ruby has to offer. Thanks for any thought!
maybe you can watch this video for your further development too.
http://railscasts.com/episodes/88-dynamic-select-menus
one-to-many for your case should be alright i guess..
like this country has many states and the according state has many of cities.
correct me if im wrong ##

ActiveRecord - Retrieve one record for each association

Merchant has_many Shops
Shop belongs_to Merchant
i.e. One merchant (Starbucks) can have many shops locations.
I'm using Gecoder to get the nearby shops, e.g. #shops = Shop.near("Times Square").
I would like to return only 1 record for each merchant only. I.e. #shops only contain 1 Starbucks, 1 Subway, but is a collection.
Sorry I've been Googling and searching on SO to no avail. Perhaps I'm not using the right word to describe what I want. Thanks in advance.
To answer what you should be googling for, joined or combined queries within a scope will probably solve what you are looking to do. If you build a scope with :or logic combining queries, one each for each shop, limited to the first record, you should get what you are looking for.
I won't pretend that I understand Geocoder or advanced scopes enough to do this, but I found an example that shows this approach in another problem:
named_scope :or, lambda { |l, r| {
:conditions =>
"annotations.id IN (#{l.send(:construct_finder_sql,{:select => :id})}) or " +
"annotations.id IN (#{r.send(:construct_finder_sql,{:select => :id})})"
}}
This comes from this SO question: Combine two named scopes with OR (instead of AND)
Hope this helps you find the solution.
I googled a bit more and stumbled on group by for SQL.
If I have 4 shops belonging to 2 merchants near a location called "Raffles Place", within 1 kilometer.
Calling Shop.near("Raffles Place",1) returns 4 shops.
If I add a group to Shop.near("Raffles Place",1).group(:merchant_id), only 2 shops are returned.
This can be used with other conditions too, such as Shop.where(:featured=>true).group(:merchant_id) to only show 1 shop per featured merchant.