How can I efficiently pull specific information from JSON - ruby

I currently have a public Google calendar that I am successfully pulling JSON data down using Google's API.
I am using HTTParty to convert the JSON to a ruby object.
response = HTTParty.get('http://www.google.com/calendar/feeds/colorado.edu_mdpltf14q21hhg50qb3e139fjg#group.calendar.google.com/public/full?alt=json&orderby=starttime&max-results=15&singleevents=true&sortorder=ascending&futureevents=true')
I want to retrieve many titles, event names, start times, end times ect. I can get these with commands like
response["feed"]["title"["$t"]
for the calendar's title, and
response["feed"]["entry"][0]["title"]["$t"]
for the event's title.
My question is two-fold. One, Is there a simpler way to pull this data? Two, how can I go about pulling multiple events information? I tried:
response.each do |x| response["feed"]["title"]["$t"]
but that spits out a no implicit conversion of string into integer error.

Based on your examples this should do it
response["feed"]["entry"].map {|entry| entry["title"]["$t"] }

response['feed']['entry'] is a simple array of hashes. It is probably best to extract that array to a temporary variable with
entries = response['feed']['entry']
thereafter your code it depends entirely on what you need to achieve. For instance, using the URL that you have provided
puts entries.length
shows
2
And
entries.each do |entry|
puts entry['title']['$t']
end
gives
NEW EVENT
Future EVENT
If we can help you to achieve something specific then please alter your answer or ask for clarification in a comment.

Related

Watir: Retrieve all dynamic HTML elements that match an attribute?

I am trying to scrape dynamic content with Watir and I am stuck.
Basically, I know that I can use
browser.element(css: ".some_class").wait_until_present
in order to scrape only when "some_class" is loaded.
The problem is that it is only giving me the first element having this class name and I want all of them.
I also know I can use
browser.spans(css: ".some_class")
in order to collect ALL the classes having this name, the problem is that I can't combine it with "wait_until_present" (it gives me an error). And spans on his own is not working because the content is not loaded yet, the page is using javascript
Is there a way to combine both? That means waiting for the class_name to be loaded AND select all the elements matching this class name, not just the first one?
I've been stuck for ages...
Thanks a lot for your help
There currently isn't anything in Watir for waiting for a collection of elements (though I had been recently thinking about adding something). For now, you just have to manually wait for an element to appears and then get the collection.
The simplest one is to call both of your lines:
browser.element(css: ".some_class").wait_until_present
browser.spans(css: ".some_class")
If you wanted to one-liner it, you could use #tap:
browser.spans(css: ".some_class").tap { |c| c[0].wait_until_present }
#=> Watir::SpanCollection
Note that if you are just checking the class name, you might want to avoid writing the CSS-selector. Not only is it easier to read without it, it won't be as performant.
browser.spans(class: "some_class").tap { |c| c[0].wait_until_present }

Ruby viewpoint with EWS

I am trying to get started using viewpoint against EWS within Ruby, and it's not making a lot of sense at the moment. I am wondering where I can get some good example code, or some pointers? I am using 1.0.0-beta.
For example: I know the name of the calendar folder I want to use, so I could search for it, but how to access methods in that folder once I find it? What are the appropriate parameters, etc...
Any advice?
If you haven't read it yet I would recommend the README file in the repository. It has a couple of examples that should put you on the right path. Also, the generated API documentation should give you enough to work with.
http://rubydoc.info/github/WinRb/Viewpoint/frames
At a very basic level you can get all of your calendar events with the following code:
calendar = client.get_folder :calendar
events = calendar.items
I hope that gives you a little more to get started with.
Follow-up:
Again, I would point you to the API docs for concrete methods like #items. There are however dynamically added methods depending on the type that you can fetch with obj.ews_methods. In the case of CalendarItem one of those methods is #name so you can call obj.name to get the folder name. The dynamic methods are all backed by a formatted Hash based on the returned SOAP packet. You can see it in its raw format by issuing obj.ews_item
Cheers,
Dan

How to push to an array without explicit declaration?

I have an array of Rails app User objects (users) and I am gathering email entries from these objects in a new array. I am tired of doing:
emails = []
users.each {|user| emails << user.email}
Is there a way to declare and use an array in a single go in an enumerator block like that?
Use #collect method
users.collect {|user| user.email }
# in short
users.collect(&:email)
collect emails will be nice to read rather than map emails, so I will use #collect. But both the methods are synonym of each other.
There is #each_with_object method.
users.each_with_object( [] ) {|user, emails| emails << user.email}
Not really a good example, collect works much better here, since you need an array. However, if you ever happen to use a different container, not an array (maybe some custom class), this might be handy.
And I also have to note that it looks much like ActiveRecord usage, since it's about Rails. So you might find #pluck useful:
I can't provide an equal piece of code here, because I have no idea what do you have in users. But here's a similar snippet:
User.all.pluck(:email)

Twitter Ruby Gem - get friends names and ids, nothing more

Is it possible to simply get the people you are following with just an id and full name? I do not need any of the additional data, it's a waste of bandwidth.
Currently the only solution I have is:
twitter_client = Twitter::Client.new
friend_ids = twitter_client.friend_ids['ids']
friends = twitter_client.users(friend_ids).map { |f| {:twitter_id => f.id, :name => f.name} }
is there anyway to just have users returned be an array of ids and full names? better way of doing it than the way depicted above? preferably a way to not filter on the client side.
The users method uses the users/lookup API call. As you can see on the page, the only param available is include_entities. The only other method which helps you find users has the same limitation. So you cannot download only the needed attributes.
The only other thing I'd like to say is that you could directly use the friends variable, I don't see any benefit of running the map on it.

Query a Django queryset without creating a new queryset?

Not even sure I'm stating the question correctly. Here's the situation. I have a queryset generated by accessing the foreign key relationship. Using the standard Blog/Entry models in the Django documentation, let's say I have selected a blog and now have a set of entries:
entries = Blog.objects.get(id=1).entry_set.all()
So we have some entries for the blog, possibly zero. I'd like to then say construct a calendar and indicate which days have blog entries. So my thinking is to iterate over list of days in the month or whatever, and check the entries queryset for an entry with that date. Question is, what is the best way to do this? My first thought was to do something like
dayinfo = [] # we will iterate over this in the template
for curday in month:
dayinfo.append({'day':curday, 'entry':entries.filter(day=curday)})
Problem is that the filter call returns a new queryset, and that generates a new sql call for each loop iteration. I just need to pluck the entry object from entries if it exists and stick it into my calendar. So what is the best way to do this? I did get this to work:
dayinfo.append({'day':day, 'entry':[e for e in entries if e.day == curday][0]})
That does not generate new sql calls. But it sure seems ugly.
Resist the urge to put everything on one line - I think the code would be cleaner with something like this:
from collections import defaultdict
calendar = defaultdict(list)
for entry in entries:
calendar[entry.day].append(entry)
The defaultdict part is simple but you might want to initialize it with all of the days in a month if you're just planning to use a for loop in the template. Also note that if you're using Django 1.1 you can use the new annotate() method to simply calculate the post count if you're not actually planning to generate links to individual posts.

Resources