0

I'm trying to insert Google Calendar events as illustrated here. If I send the request with values hardcoded like the example it works fine:

event = {'summary' => 'Summary',
         'location' => 'Location',
         'start' => { 'dateTime' => '2011-06-03T10:00:00.000-07:00' },
         'end' => { 'dateTime' => '2011-06-03T10:25:00.000-07:00' }}

But it fails silently if I try to send variables:

event = {'summary' => "#{params[:summary]}",
         'location' => "#{params[:location]}",
         'start' => { 'dateTime' => "#{params[:start_time]}" },
         'end' => { 'dateTime' => "#{params[:start_time]}" }}

It also fails if I format this way:

event = "{
          \"summary\": \"#{params[:summary]}\",
          \"location\": \"#{params[:location]}\",
          \"start\": { \"dateTime\": \"#{params[:start_time]}\" },
          \"end\": { \"dateTime\": \"#{params[:end_time]}\" }
        }"

I can get it to successfully post with the start_time and end_time formatted like this: Date.today.strftime("%Y-%m-%dT%l:%M:%S.000-07:00"), but that's less-than-ideal because I believe the start_time and end_time params are already Time objects.

The form is passing the parameters because I get this in the Rails console (authenticity_token omitted for brevity):

Started POST "/events" for 127.0.0.1 at 2015-04-15 08:53:36 -0600
Processing by EventsController#create as HTML
  Parameters: {"utf8"=>"✓",
               "authenticity_token"=>"...",
               "event"=>{"summary"=>"Summary",
                         "start_time(1i)"=>"2015",
                         "start_time(2i)"=>"4",
                         "start_time(3i)"=>"15",
                         "start_time(4i)"=>"14",
                         "start_time(5i)"=>"54",
                         "end_time(1i)"=>"2015",
                         "end_time(2i)"=>"4",
                         "end_time(3i)"=>"15",
                         "end_time(4i)"=>"14",
                         "end_time(5i)"=>"55",
                         "location"=>"Location"},
               "commit"=>"Create Event"}

Here is the relevant code:

client = Google::APIClient.new({:application_name => "PlannerApp",
                                :application_version => "1.0"})
client.authorization.access_token = t.fresh_token
service = client.discovered_api('calendar', 'v3')
client.execute(:api_method => service.events.insert,
               :parameters => {'calendarId' => 'primary'},
               :body => JSON.dump(event),
               :headers => {'Content-Type' => 'application/json'})

And here is what I get from Google (Authorization omitted for brevity):

Google::APIClient::Request Sending API request get https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest {
  "User-Agent"=>"PlannerApp/1.0 google-api-ruby-client/0.8.5 Mac OS X/10.10.2\n (gzip)",
  "Accept-Encoding"=>"gzip",
  "Content-Type"=>""}
Google::APIClient::Request Result: 200 {
  "expires"=>"Wed, 15 Apr 2015 14:58:37 GMT",
  "date"=>"Wed, 15 Apr 2015 14:53:37 GMT",
  "etag"=>"\"ye6orv2F-1npMW3u9suM3a7C5Bo/snCOExYvhrzEZTGzdubZtafuHVU\"",
  "vary"=>"Origin, X-Origin",
  "content-type"=>"application/json; charset=UTF-8",
  "x-content-type-options"=>"nosniff",
  "x-frame-options"=>"SAMEORIGIN",
  "x-xss-protection"=>"1; mode=block",
  "content-length"=>"93847",
  "server"=>"GSE",
  "cache-control"=>"public, max-age=300, must-revalidate, no-transform",
  "age"=>"0",
  "alternate-protocol"=>"443:quic,p=0.5",
  "connection"=>"close"}
Google::APIClient::Request Sending API request post https://www.googleapis.com/calendar/v3/calendars/primary/events {
  "User-Agent"=>"PlannerApp/1.0 google-api-ruby-client/0.8.5 Mac OS X/10.10.2\n (gzip)",
  "Content-Type"=>"application/json",
  "Accept-Encoding"=>"gzip",
  "Authorization"=>"Bearer ...",
  "Cache-Control"=>"no-store"}

How should I be formatting these event hash values to get a successful POST?

SOLUTION:

event = {'summary' => "#{params[:event][:summary]}",
         'location' => "#{params[:event][:location]}",
         'start' => { 'dateTime' => Time.new(params['event']['start_time(1i)'],
                                             params['event']['start_time(2i)'],
                                             params['event']['start_time(3i)'],
                                             params['event']['start_time(4i)'],
                                             params['event']['start_time(5i)'])
                                        .to_datetime.rfc3339,
                      'timeZone' => "America/Denver" },
         'end' => { 'dateTime' => Time.new(params['event']['end_time(1i)'],
                                           params['event']['end_time(2i)'],
                                           params['event']['end_time(3i)'],
                                           params['event']['end_time(4i)'],
                                           params['event']['end_time(5i)'])
                                      .to_datetime.rfc3339,
                    'timeZone' => "America/Denver" }}
crgolden
  • 4,332
  • 1
  • 22
  • 40

1 Answers1

0

Your params are nested. So it would be:

event = {'summary' => "#{params[:event][:summary]}",
     'location' => "#{params[:event][:location]}",
     'start' => { 'dateTime' => "#{params[:event][:start_time]}" },
     'end' => { 'dateTime' => "#{params[:event][:start_time]}" }}
aspencer8111
  • 786
  • 4
  • 9
  • Good catch - thanks! This solved the part of my question about the strings (`summary` and `location`), but not for the times (`start_time` and `end_time`). Do you have any idea on those? They are _time_ fields both in the database and on the form. `"#{params[:event][:start_time]}"` doesn't work, but according to the reference [here](https://developers.google.com/google-apps/calendar/v3/reference/events#resource), `dateTime` should receive a `datetime` value. I've also tried adding `'timeZone' => "America/Denver"` to the `start` and `end` hashes, but that doesn't work either. – crgolden Apr 15 '15 at 18:47
  • Based on the params you are getting back, you would have to build them up. Grrr...sorry SO submitted too early. See how your are getting your date in pieces? i.e. ```"start_time(1i)"=>"2015", "start_time(2i)"=>"4", # your month "start_time(3i)"=>"15", "start_time(4i)"=>"14", # your day "start_time(5i)"=>"54", "end_time(1i)"=>"2015" # your year``` – aspencer8111 Apr 15 '15 at 18:49
  • So to get the year piece (the year), you would use ```"#{params[:event][:start_time(1i)]}"``` – aspencer8111 Apr 15 '15 at 18:54
  • Also, whenever you get it working, can you mark this answer and the correct resolution? Thanks! – aspencer8111 Apr 15 '15 at 19:10
  • Thanks again for such a quick response! I am passing this: `"#{params[:event][:start_time[1]]}-#{params[:event][:start_time[2]]}-#{params[:event][:start_time[3]]}T#{params[:event][:start_time[4]]}:#{params[:event][:start_time[5]]}"` to `dateTime` and passing `"America/Denver"` to `'timeZone'`, but it's not working. Is that what you had in mind? I'm sure I'm missing something very simple in the formatting. – crgolden Apr 15 '15 at 19:36
  • I would do ```Time.new("#{params[:event][:start_time(1i)]}", "#{params[:event][:start_time(2i)]}", "#{params[:event][:start_time(3i)]}")``` or something similar depending on where the day, month, and year are actually coming from. You can continue that pattern to add hours and mins as well. – aspencer8111 Apr 15 '15 at 19:43
  • So the entire line would be something like: ```'start' => { 'dateTime' => Time.new("#{params[:event][:start_time(1i)]}", "#{params[:event][:start_time(2i)]}", "#{params[:event][:start_time(3i)]}")}``` Again, you may need to add hour/min/sec too, but just follow that pattern. – aspencer8111 Apr 15 '15 at 19:46
  • Ok, just got home and tried your suggestion... and a couple variations: `Time.new("#{params[:event][:start_time(1i)]}")` gives `syntax error, unexpected '(', expecting ']'`; `Time.new("#{params[:event][:start_time[(1i)]]}")` gives `can't convert 0+1i into Integer`; `Time.new("#{params[:event][:start_time[1]]}")` gives `argument out of range`. I appreciate all your help! – crgolden Apr 16 '15 at 06:45
  • OK. Sorry. I was overcomplicating it by tryting to force string interpolation where it didn't need to be. This has been tested and will work just fine: ```Time.new(params['event']['start_time(1i)'], params['event']['start_time(2i)'], params['event']['start_time(3i)'])``` – aspencer8111 Apr 16 '15 at 14:11
  • Thanks, but no luck. I parsed the JSON result and here's the error when I use your format: `{"error"=>{"errors"=>[{"domain"=>"global", "reason"=>"invalid", "message"=>"Invalid value for: Invalid format: \"2015-04-16 00:00:00 -0600\" is malformed at \" 00:00:00 -0600\""}], "code"=>400, "message"=>"Invalid value for: Invalid format: \"2015-04-16 00:00:00 -0600\" is malformed at \" 00:00:00 -0600\""}}` – crgolden Apr 16 '15 at 16:02
  • If I include seconds it looks like: `{"error"=>{"errors"=>[{"domain"=>"global", "reason"=>"invalid", "message"=>"Invalid value for: Invalid format: \"2015-04-16 16:06:00 -0600\" is malformed at \" 16:06:00 -0600\""}], "code"=>400, "message"=>"Invalid value for: Invalid format: \"2015-04-16 16:06:00 -0600\" is malformed at \" 16:06:00 -0600\""}}` – crgolden Apr 16 '15 at 16:08
  • Ah. yes. bc we have to pass it to Google in a specific datetime format of rfc3339. So append ```.to_datetime.rfc3339``` to the end. for a total line of: ```Time.new(params['event']['start_time(1i)'], params['event']['start_time(2i)'], params['event']['start_time(3i)'], params['event']['start_time(4i)'], params['event']['start_time(4i)']).to_datetime.rfc3339``` – aspencer8111 Apr 16 '15 at 17:04
  • 1
    Brilliant! That's the ticket. Thanks so much. I'll accept this and update my question with your solution. – crgolden Apr 16 '15 at 17:56