Permalink
Browse files

Ok, so there's a lot to explain here. Suffice it to say I'm going to …

…skip that and say that you can now read only a list of calendars, a single calendar, and any events related to a single calendar. The only caveat is that you cannot see who the attendees are do to some xpath bug I'll work out later. I've also started working on the views and controllers for calendars. If you are poking around / routes to CalendarsController#index . Enjoy.
  • Loading branch information...
1 parent 9827240 commit d1b001e1f18f3c544dd29595e97e839ec5be4f04 @m3talsmith committed May 6, 2009
@@ -4,7 +4,7 @@
class ApplicationController < ActionController::Base
helper :all # include all helpers, all the time
protect_from_forgery # See ActionController::RequestForgeryProtection for details
-
+
# Scrub sensitive parameters from your log
# filter_parameter_logging :password
end
@@ -0,0 +1,2 @@
+class Calendars::EventsController < ApplicationController
+end
@@ -0,0 +1,10 @@
+class CalendarsController < ApplicationController
+ def index
+ @calendars = Calendar.find(:all)
+ end
+
+ def show
+ @calendar = Calendar.find(params[:id])
+ logger.debug @calendar
+ end
+end
@@ -0,0 +1,2 @@
+module Calendars::EventsHelper
+end
@@ -0,0 +1,2 @@
+module CalendarsHelper
+end
View
@@ -0,0 +1,3 @@
+class Calendar < ActiveCalendarEngine::Calendar
+ has_google_options :google_service => "cl", :google_feed => "http://www.google.com/calendar/feeds/default/allcalendars/full"
+end
@@ -0,0 +1,6 @@
+<ul class="calendar_list">
+ <% @calendars.each do |calendar| %>
+ <li><%= link_to calendar.title, calendar_path(calendar.id) %>
+ <% end %>
+ <li class="note">Create a new calendar</li>
+</ul>
No changes.
@@ -0,0 +1,13 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
+ "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+
+<html>
+ <head>
+ </head>
+ <body>
+ <div id="content">
+ <%= yield %>
+ </div>
+ </body>
+</html>
View
@@ -1,43 +1,4 @@
ActionController::Routing::Routes.draw do |map|
- # The priority is based upon order of creation: first created -> highest priority.
-
- # Sample of regular route:
- # map.connect 'products/:id', :controller => 'catalog', :action => 'view'
- # Keep in mind you can assign values other than :controller and :action
-
- # Sample of named route:
- # map.purchase 'products/:id/purchase', :controller => 'catalog', :action => 'purchase'
- # This route can be invoked with purchase_url(:id => product.id)
-
- # Sample resource route (maps HTTP verbs to controller actions automatically):
- # map.resources :products
-
- # Sample resource route with options:
- # map.resources :products, :member => { :short => :get, :toggle => :post }, :collection => { :sold => :get }
-
- # Sample resource route with sub-resources:
- # map.resources :products, :has_many => [ :comments, :sales ], :has_one => :seller
-
- # Sample resource route with more complex sub-resources
- # map.resources :products do |products|
- # products.resources :comments
- # products.resources :sales, :collection => { :recent => :get }
- # end
-
- # Sample resource route within a namespace:
- # map.namespace :admin do |admin|
- # # Directs /admin/products/* to Admin::ProductsController (app/controllers/admin/products_controller.rb)
- # admin.resources :products
- # end
-
- # You can have the root of your site routed with map.root -- just remember to delete public/index.html.
- # map.root :controller => "welcome"
-
- # See how all your routes lay out with "rake routes"
-
- # Install the default routes as the lowest priority.
- # Note: These default routes make all actions in every controller accessible via GET requests. You should
- # consider removing the them or commenting them out if you're using named routes and resources.
- map.connect ':controller/:action/:id'
- map.connect ':controller/:action/:id.:format'
+ map.resources :calendars
+ map.root :controller => "calendars", :action => "index"
end
@@ -28,6 +28,26 @@ def initialize
end
end
+ def to_s
+ self.inspect
+ end
+
+ # -- id methods --
+ # I needed to add these because Rails routing would blow up if a qualified
+ # url were added as an id.
+ def id
+ return @id
+ end
+
+ def id=(google_id)
+ @id = self.class.escape_id(google_id)
+ end
+
+ def feed_id
+ return self.class.unescape_id(self.id)
+ end
+ # --
+
class << self
def find(*args)
@@ -45,10 +65,18 @@ def find(*args)
response, data = get_authenticated_feed(args.first)
@data = {:response => response, :data => data}
end
-
+
return @data ? @data : false
end
+ def unescape_id(id)
+ return id.gsub("%2F", "/").gsub("%3A", ":").gsub("%2E", ".")
+ end
+
+ def escape_id(id)
+ return id.gsub("/", "%2F").gsub(":", "%3A").gsub(".", "%2E")
+ end
+
def has_google_options(*args)
google_options(args.extract_options!)
end
@@ -1,12 +1,16 @@
+require 'active_calendar_engine/event'
+
+class Event < ActiveCalendarEngine::Event; end
+
module ActiveCalendarEngine
class Calendar < ActiveCalendarEngine::Base
has_google_options :google_service => "cl", :google_feed => "http://www.google.com/calendar/feeds/default/allcalendars/full"
attr_accessors(
- :links, :author, :id,
+ :links, :author,
:published_on, :updated_on, :title,
- :timezone, :access_level, :summary, :raw_data
+ :timezone, :access_level, :summary, :raw_data, :events
)
def initialize(*args)
@@ -23,10 +27,11 @@ def to_s
end
def events
- self.class.parse_single_calendar( self.class.find( self.links[:self] ) )
+ @events ||= Event.find_and_extract_events( self.links[:alternate] )
end
class << self
+
def calendars
return self.find(:all)
end
@@ -39,10 +44,10 @@ def find(*args)
super args.first, options
return parse_calendar_data(@data[:data])
when :first
- super args.first
+ super self.unescape_id(args.first)
return parse_single_calendar(@data[:data])
else
- super args.first
+ super self.unescape_id(args.first)
return parse_single_calendar(@data[:data])
end
end
@@ -67,6 +72,7 @@ def initialize_calendar_properties
class << self
def parse_single_calendar(data)
+ return self.parse_calendar_data(data).first
end
def parse_calendar_data(data)
@@ -90,9 +96,8 @@ def parse_calendar_data(data)
end
# --
- calendars << self.new(
+ calendar = self.new(
:raw_data => entry,
- :id => entry.css('id').first.content,
:author => author_data,
:access_level => "#{entry.xpath('//gCal:accesslevel').first.attribute('value')}",
:summary => (entry.xpath('//summary').length > 0 ? entry.xpath('//summary').first.content : nil),
@@ -102,6 +107,9 @@ def parse_calendar_data(data)
:updated_on => entry.css('updated').first.content,
:links => link_data
)
+ calendar.id = link_data[:self]
+
+ calendars << calendar
end
return calendars
@@ -0,0 +1,134 @@
+module ActiveCalendarEngine
+ class Event < ActiveCalendarEngine::Base
+
+ has_google_options :google_service => "cl", :google_feed => "http://www.google.com/calendar/feeds/default/allcalendars/full"
+
+ attr_accessors(
+ :published_on, :updated_on, :title, :content, :links, :author,
+ :event_status, :who, :where, :when, :raw_data, :comments
+ )
+
+ def initialize(*args)
+ initialize_event_properties
+
+ attributes = args.extract_options!
+ attributes.each_pair do |key, value|
+ instance_variable_set("@#{key}", value) if instance_variable_get("@#{key}")
+ end
+ end
+
+ class << self
+
+ def find(*args)
+ super self.unescape_id(args.first)
+ return parse_event_data(@data[:data])
+ end
+
+ def extract_events(data)
+ return self.parse_event_data(data)
+ end
+
+ def find_and_extract_events(feed)
+ return self.find(feed)
+ end
+
+ end
+
+ private
+
+ def initialize_event_properties
+ @links = {}
+ @comments = []
+ @author = {:email => "", :name => ""}
+ @who = [] # {:email => "", :name => "", :status => ""}
+ @where = String.new
+ @when = {:start_time => Time.now.xmlschema, :end_time => Time.new.in(3600).xmlschema, :reminders => []}
+ @event_status = "confirmed"
+ @id = String.new
+ @title = String.new
+ @content = String.new
+ %w(published updated).each do |dated|
+ instance_variable_set("@#{dated}_on", Time.now.xmlschema)
+ end
+ @raw_data = ""
+ end
+
+ class << self
+ def parse_event_data(data)
+ events = []
+ document = Nokogiri::XML.parse(data)
+
+ document.css('entry').each do |entry|
+ # -- lazy data --
+ author_data = {}
+ entry.css('author').first.children.each do |child|
+ author_data[eval(":#{child.name}")] = child.text unless child.name == "text"
+ end
+
+ link_data = {}
+ entry.css('link').each do |link|
+ unless link.attribute('rel').value =~ /http/
+ link_data[eval(":#{link.attribute('rel').value}")] = link.attribute('href').value
+ end
+ end
+
+ comment_data = []
+ entry.xpath('//gd:comments').each do |comment|
+ comment.xpath('//gd:feedlink').each do |link|
+ comment_data << link.attribute('href').value
+ end
+ end
+
+ who_data = []
+ entry.xpath('//gd:who').each do |who|
+ user = {
+ :name => who.attribute('valueString').value,
+ :email => who.attribute('email').value,
+ :status => who.xpath('//gd:attendeeStatus').first.attribute('value').value.split(".").last
+ }
+ who_data << user
+ end
+
+ whin = entry.xpath('//gd:when').first
+ whin_data = {}
+ whin_data = {
+ :start_time => whin.attribute('startTime').value,
+ :end_time => whin.attribute('endTime').value,
+ :reminders => []
+ }
+
+ reminders = []
+ whin.xpath('//gd:reminder').each do |reminder|
+ rd = {
+ :minutes => reminder.attribute('minutes').value,
+ :method => reminder.attribute('method').value
+ }
+ reminders << rd
+ end
+ whin_data[:reminders] = reminders
+ # --
+
+ event = self.new(
+ :raw_data => entry,
+ :comments => comment_data,
+ :author => author_data,
+ # :who => who_data,
+ :where => entry.xpath('//gd:where').first.attribute('valueString').value,
+ :when => whin_data,
+ :event_status => entry.xpath('//gd:eventStatus').first.attribute('value').value.split(".").last,
+ :title => entry.css('title').first.content,
+ :content => (entry.xpath('//content').length > 0 ? entry.xpath('//content').first.content : nil),
+ :published_on => entry.css('published').first.content,
+ :updated_on => entry.css('updated').first.content,
+ :links => link_data
+ )
+ event.id = link_data[:alternate]
+
+ events << event
+ end
+
+ return events
+ end
+ end
+ end
+end
Oops, something went wrong.

0 comments on commit d1b001e

Please sign in to comment.