cronofy 0.5.3 → 0.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +59 -52
- data/lib/cronofy/client.rb +58 -9
- data/lib/cronofy/types.rb +19 -0
- data/lib/cronofy/version.rb +1 -1
- data/spec/lib/cronofy/client_spec.rb +188 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bc7139bd209e180668455e51a5973e065bedd6b2
|
4
|
+
data.tar.gz: 830ebcf54b85a0aba2150e30ca5e0b2d5d0f1ae4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d93493fd9c16426323f15d9ffeb0b726bcb2bfaf341f838687b360807ef1cea427a05dbffb5b010694ff30b40ea1f43579711e30c96e6c32c4c0f181a6cd6060
|
7
|
+
data.tar.gz: 49c9dd164f765ca56629514bfa6ef07f69d7859b3f77a8162b7912a07429e4fa5b94a65e4daedec6f32ee241d653aef129789078267aead1ab2d2d86734cc5f3
|
data/README.md
CHANGED
@@ -2,9 +2,8 @@
|
|
2
2
|
|
3
3
|
[![Build Status](https://travis-ci.org/cronofy/cronofy-ruby.svg?branch=master)](https://travis-ci.org/cronofy/cronofy-ruby)
|
4
4
|
[![Gem Version](https://badge.fury.io/rb/cronofy.svg)](http://badge.fury.io/rb/cronofy)
|
5
|
-
[![Join the chat at https://gitter.im/cronofy/cronofy-ruby](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/cronofy/cronofy-ruby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
6
5
|
|
7
|
-
[Cronofy](
|
6
|
+
[Cronofy](https://www.cronofy.com) - one API for all the calendars (Google, iCloud, Exchange, Office 365, Outlook.com)
|
8
7
|
|
9
8
|
## Installation
|
10
9
|
|
@@ -14,92 +13,98 @@ Add this line to your application's Gemfile:
|
|
14
13
|
gem 'cronofy'
|
15
14
|
```
|
16
15
|
|
17
|
-
And then
|
16
|
+
And then at your command prompt run:
|
18
17
|
|
19
|
-
|
18
|
+
```
|
19
|
+
bundle install
|
20
|
+
```
|
20
21
|
|
21
|
-
|
22
|
+
## Usage
|
22
23
|
|
23
|
-
|
24
|
+
In order to use the Cronofy API you will need to [create a developer account](https://app.cronofy.com/sign_up/new).
|
24
25
|
|
25
|
-
|
26
|
+
From there you can [create personal access tokens](https://app.cronofy.com/oauth/applications/5447ae289bd94726da00000f/tokens)
|
27
|
+
to access your own calendars, or you can [create an OAuth application](https://app.cronofy.com/oauth/applications/new)
|
28
|
+
to obtain an OAuth `client_id` and `client_secret` to be able to use the full
|
29
|
+
API.
|
26
30
|
|
27
|
-
|
31
|
+
## Creating a client
|
28
32
|
|
29
|
-
|
33
|
+
To make calls to the Cronofy API you must create a `Cronofy::Client`. This takes
|
34
|
+
four keyword arguments, all of which are optional:
|
30
35
|
|
31
36
|
```ruby
|
32
|
-
cronofy = Cronofy::Client.new
|
37
|
+
cronofy = Cronofy::Client.new(
|
38
|
+
client_id: 'CLIENT_ID',
|
39
|
+
client_secret: 'CLIENT_SECRET',
|
40
|
+
access_token: 'ACCESS_TOKEN',
|
41
|
+
refresh_token: 'REFRESH_TOKEN'
|
42
|
+
)
|
33
43
|
```
|
34
44
|
|
35
|
-
|
45
|
+
When using a [personal access token](https://app.cronofy.com/oauth/applications/5447ae289bd94726da00000f/tokens)
|
46
|
+
you only need to provide the `access_token` argument.
|
36
47
|
|
37
|
-
|
38
|
-
|
39
|
-
|
48
|
+
When working against your own OAuth application you will need to provide the
|
49
|
+
`client_id` and `client_secret` when [going through the authorization process](https://www.cronofy.com/developers/api/#authorization)
|
50
|
+
for a user, and when [refreshing an access token](https://www.cronofy.com/developers/api/#token-refresh).
|
40
51
|
|
41
|
-
|
52
|
+
If `client_id` and `client_secret` are not specified explicitly the values from
|
53
|
+
the environment variables `CRONOFY_CLIENT_ID` and `CRONOFY_CLIENT_SECRET` will
|
54
|
+
be used if present.
|
42
55
|
|
43
|
-
|
44
|
-
cronofy = Cronofy::Client.new(access_token: 'ACCESS_TOKEN', refresh_token: 'REFRESH_TOKEN')
|
45
|
-
```
|
56
|
+
## Authorization
|
46
57
|
|
47
|
-
|
58
|
+
[API documentation](https://www.cronofy.com/developers/api/#authorization)
|
48
59
|
|
49
|
-
Generate a link for a user to grant access
|
60
|
+
Generate a link for a user to grant access to their calendars:
|
50
61
|
|
51
62
|
```ruby
|
52
|
-
cronofy.user_auth_link('http://
|
63
|
+
authorization_url = cronofy.user_auth_link('http://yoursite.dev/oauth2/callback')
|
53
64
|
```
|
54
65
|
|
55
|
-
The
|
66
|
+
The callback URL is a page on your website that will handle the OAuth 2.0
|
67
|
+
callback and receive a `code` parameter. You can then use that code to retrieve
|
68
|
+
an OAuth token granting access to the user's Cronofy account:
|
56
69
|
|
57
70
|
```ruby
|
58
|
-
|
71
|
+
response = cronofy.get_token_from_code(code, 'http://yoursite.dev/oauth2/callback')
|
59
72
|
```
|
60
73
|
|
61
|
-
You should save the `access_token` and `refresh_token` for later use.
|
74
|
+
You should save the response's `access_token` and `refresh_token` for later use.
|
62
75
|
|
63
|
-
|
76
|
+
Note that the **exact same** callback URL must be passed to both methods for
|
77
|
+
access to be granted.
|
64
78
|
|
65
|
-
|
79
|
+
If you use the [omniauth gem](https://rubygems.org/gems/omniauth), you can use
|
80
|
+
our [omniauth-cronofy strategy gem](https://rubygems.org/gems/omniauth-cronofy)
|
81
|
+
to perform this process.
|
66
82
|
|
67
|
-
|
68
|
-
cronofy.list_calendars
|
69
|
-
```
|
83
|
+
## List calendars
|
70
84
|
|
71
|
-
|
72
|
-
version of the following JSON structure:
|
73
|
-
|
74
|
-
```json
|
75
|
-
{
|
76
|
-
"provider_name": "google",
|
77
|
-
"profile_name": "YYYYYYYY@gmail.com",
|
78
|
-
"calendar_id": "cal_YYYYYYYY-UNIQUE_CAL_ID_HERE-YYYYYYYY",
|
79
|
-
"calendar_name": "Office Calendar",
|
80
|
-
"calendar_readonly": false,
|
81
|
-
"calendar_deleted": false
|
82
|
-
}
|
83
|
-
```
|
85
|
+
[API documentation](https://www.cronofy.com/developers/api/#calendars)
|
84
86
|
|
85
|
-
|
87
|
+
Get a list of all the user's calendars:
|
86
88
|
|
87
89
|
```ruby
|
88
|
-
|
89
|
-
calendar.calendar_id
|
90
|
-
# => "cal_YYYYYYYY-UNIQUE_CAL_ID_HERE-YYYYYYYY"
|
90
|
+
calendars = cronofy.list_calendars
|
91
91
|
```
|
92
92
|
|
93
|
-
|
93
|
+
## Read events
|
94
|
+
|
95
|
+
[API documentation](https://www.cronofy.com/developers/api/#read-events)
|
96
|
+
|
97
|
+
Get a list of events from the user's calendars:
|
94
98
|
|
95
99
|
```ruby
|
96
100
|
events = cronofy.read_events
|
97
|
-
events.first
|
98
|
-
# => {"calendar_id" => ....}
|
99
101
|
```
|
100
102
|
|
103
|
+
Note that the gem handles iterating through the pages on your behalf.
|
101
104
|
|
102
|
-
|
105
|
+
## Create or update events
|
106
|
+
|
107
|
+
[API documentation](https://www.cronofy.com/developers/api/#upsert-event)
|
103
108
|
|
104
109
|
To create/update an event in the user's calendar:
|
105
110
|
|
@@ -118,7 +123,9 @@ event_data = {
|
|
118
123
|
cronofy.upsert_event(calendar_id, event_data)
|
119
124
|
```
|
120
125
|
|
121
|
-
|
126
|
+
## Delete events
|
127
|
+
|
128
|
+
[API documentation](https://www.cronofy.com/developers/api/#delete-event)
|
122
129
|
|
123
130
|
To delete an event from user's calendar:
|
124
131
|
|
@@ -128,6 +135,6 @@ cronofy.delete_event(calendar_id, 'uniq-id')
|
|
128
135
|
|
129
136
|
## Links
|
130
137
|
|
131
|
-
* [API
|
138
|
+
* [API documentation](https://www.cronofy.com/developers/api)
|
132
139
|
* [API mailing list](https://groups.google.com/d/forum/cronofy-api)
|
133
140
|
|
data/lib/cronofy/client.rb
CHANGED
@@ -177,7 +177,49 @@ module Cronofy
|
|
177
177
|
end
|
178
178
|
|
179
179
|
url = ::Cronofy.api_url + "/v1/events"
|
180
|
-
|
180
|
+
PagedResultIterator.new(PagedEventsResult, :events, access_token!, url, params)
|
181
|
+
end
|
182
|
+
|
183
|
+
# Public: Returns a lazily-evaluated Enumerable of FreeBusy that satisfy the
|
184
|
+
# given query criteria.
|
185
|
+
#
|
186
|
+
# options - The Hash options used to refine the selection (default: {}):
|
187
|
+
# :from - The minimum Date from which to return events
|
188
|
+
# (optional).
|
189
|
+
# :to - The Date to return events up until (optional).
|
190
|
+
# :tzid - A String representing a known time zone
|
191
|
+
# identifier from the IANA Time Zone Database
|
192
|
+
# (default: Etc/UTC).
|
193
|
+
# :include_managed - A Boolean specifying whether events that you
|
194
|
+
# are managing for the account should be
|
195
|
+
# included or excluded from the results
|
196
|
+
# (optional).
|
197
|
+
#
|
198
|
+
# The first page will be retrieved eagerly so that common errors will happen
|
199
|
+
# inline. However, subsequent pages (if any) will be requested lazily.
|
200
|
+
#
|
201
|
+
# See http://www.cronofy.com/developers/api/alpha#free-busy for reference.
|
202
|
+
#
|
203
|
+
# Returns a lazily-evaluated Enumerable of FreeBusy
|
204
|
+
#
|
205
|
+
# Raises Cronofy::CredentialsMissingError if no credentials available.
|
206
|
+
# Raises Cronofy::AuthenticationFailureError if the access token is no
|
207
|
+
# longer valid.
|
208
|
+
# Raises Cronofy::AuthorizationFailureError if the access token does not
|
209
|
+
# include the required scope.
|
210
|
+
# Raises Cronofy::InvalidRequestError if the request contains invalid
|
211
|
+
# parameters.
|
212
|
+
# Raises Cronofy::TooManyRequestsError if the request exceeds the rate
|
213
|
+
# limits for the application.
|
214
|
+
def free_busy(options = {})
|
215
|
+
params = FREE_BUSY_DEFAULT_PARAMS.merge(options)
|
216
|
+
|
217
|
+
FREE_BUSY_TIME_PARAMS.select { |tp| params.key?(tp) }.each do |tp|
|
218
|
+
params[tp] = to_iso8601(params[tp])
|
219
|
+
end
|
220
|
+
|
221
|
+
url = ::Cronofy.api_url + "/v1/free_busy"
|
222
|
+
PagedResultIterator.new(PagedFreeBusyResult, :free_busy, access_token!, url, params)
|
181
223
|
end
|
182
224
|
|
183
225
|
# Public: Deletes an event from the specified calendar
|
@@ -399,8 +441,13 @@ module Cronofy
|
|
399
441
|
|
400
442
|
private
|
401
443
|
|
402
|
-
|
444
|
+
FREE_BUSY_DEFAULT_PARAMS = { tzid: "Etc/UTC" }.freeze
|
445
|
+
FREE_BUSY_TIME_PARAMS = %i{
|
446
|
+
from
|
447
|
+
to
|
448
|
+
}.freeze
|
403
449
|
|
450
|
+
READ_EVENTS_DEFAULT_PARAMS = { tzid: "Etc/UTC" }.freeze
|
404
451
|
READ_EVENTS_TIME_PARAMS = %i{
|
405
452
|
from
|
406
453
|
to
|
@@ -460,10 +507,12 @@ module Cronofy
|
|
460
507
|
end
|
461
508
|
end
|
462
509
|
|
463
|
-
class
|
510
|
+
class PagedResultIterator
|
464
511
|
include Enumerable
|
465
512
|
|
466
|
-
def initialize(access_token, url, params)
|
513
|
+
def initialize(page_parser, items_key, access_token, url, params)
|
514
|
+
@page_parser = page_parser
|
515
|
+
@items_key = items_key
|
467
516
|
@access_token = access_token
|
468
517
|
@url = url
|
469
518
|
@params = params
|
@@ -473,15 +522,15 @@ module Cronofy
|
|
473
522
|
def each
|
474
523
|
page = @first_page
|
475
524
|
|
476
|
-
page.
|
477
|
-
yield
|
525
|
+
page[@items_key].each do |item|
|
526
|
+
yield item
|
478
527
|
end
|
479
528
|
|
480
529
|
while page.pages.next_page?
|
481
530
|
page = get_page(page.pages.next_page)
|
482
531
|
|
483
|
-
page.
|
484
|
-
yield
|
532
|
+
page[@items_key].each do |item|
|
533
|
+
yield item
|
485
534
|
end
|
486
535
|
end
|
487
536
|
end
|
@@ -511,7 +560,7 @@ module Cronofy
|
|
511
560
|
end
|
512
561
|
|
513
562
|
def parse_page(response)
|
514
|
-
ResponseParser.new(response).parse_json(
|
563
|
+
ResponseParser.new(response).parse_json(@page_parser)
|
515
564
|
end
|
516
565
|
end
|
517
566
|
end
|
data/lib/cronofy/types.rb
CHANGED
@@ -197,6 +197,25 @@ module Cronofy
|
|
197
197
|
coerce_key :events, Events
|
198
198
|
end
|
199
199
|
|
200
|
+
class FreeBusy < Hashie::Mash
|
201
|
+
include Hashie::Extensions::Coercion
|
202
|
+
|
203
|
+
coerce_key :start, EventTime
|
204
|
+
coerce_key :end, EventTime
|
205
|
+
end
|
206
|
+
|
207
|
+
module FreeBusyEnumerable
|
208
|
+
def self.coerce(values)
|
209
|
+
values.map { |v| FreeBusy.new(v) }
|
210
|
+
end
|
211
|
+
end
|
212
|
+
|
213
|
+
class PagedFreeBusyResult < Hashie::Mash
|
214
|
+
include Hashie::Extensions::Coercion
|
215
|
+
|
216
|
+
coerce_key :free_busy, FreeBusyEnumerable
|
217
|
+
end
|
218
|
+
|
200
219
|
class Profile < Hashie::Mash
|
201
220
|
end
|
202
221
|
end
|
data/lib/cronofy/version.rb
CHANGED
@@ -606,4 +606,192 @@ describe Cronofy::Client do
|
|
606
606
|
it_behaves_like 'a Cronofy request with mapped return value'
|
607
607
|
end
|
608
608
|
end
|
609
|
+
|
610
|
+
describe 'Free busy' do
|
611
|
+
describe '#free_busy' do
|
612
|
+
before do
|
613
|
+
stub_request(method, request_url)
|
614
|
+
.with(headers: request_headers,
|
615
|
+
body: request_body)
|
616
|
+
.to_return(status: correct_response_code,
|
617
|
+
headers: correct_response_headers,
|
618
|
+
body: correct_response_body.to_json)
|
619
|
+
|
620
|
+
stub_request(:get, next_page_url)
|
621
|
+
.with(headers: request_headers)
|
622
|
+
.to_return(status: correct_response_code,
|
623
|
+
headers: correct_response_headers,
|
624
|
+
body: next_page_body.to_json)
|
625
|
+
end
|
626
|
+
|
627
|
+
|
628
|
+
let(:request_url_prefix) { 'https://api.cronofy.com/v1/free_busy' }
|
629
|
+
let(:method) { :get }
|
630
|
+
let(:correct_response_code) { 200 }
|
631
|
+
let(:next_page_url) do
|
632
|
+
"https://next.page.com/08a07b034306679e"
|
633
|
+
end
|
634
|
+
|
635
|
+
let(:params) { Hash.new }
|
636
|
+
let(:request_url) { request_url_prefix + "?tzid=Etc/UTC" }
|
637
|
+
|
638
|
+
let(:correct_response_body) do
|
639
|
+
{
|
640
|
+
'pages' => {
|
641
|
+
'current' => 1,
|
642
|
+
'total' => 2,
|
643
|
+
'next_page' => next_page_url
|
644
|
+
},
|
645
|
+
'free_busy' => [
|
646
|
+
{
|
647
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
648
|
+
'start' => '2014-09-06',
|
649
|
+
'end' => '2014-09-08',
|
650
|
+
'free_busy_status' => 'busy',
|
651
|
+
},
|
652
|
+
{
|
653
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
654
|
+
'start' => '2014-09-13T19:00:00Z',
|
655
|
+
'end' => '2014-09-13T21:00:00Z',
|
656
|
+
'free_busy_status' => 'tentative',
|
657
|
+
}
|
658
|
+
]
|
659
|
+
}
|
660
|
+
end
|
661
|
+
|
662
|
+
let(:next_page_body) do
|
663
|
+
{
|
664
|
+
'pages' => {
|
665
|
+
'current' => 2,
|
666
|
+
'total' => 2,
|
667
|
+
},
|
668
|
+
'free_busy' => [
|
669
|
+
{
|
670
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
671
|
+
'start' => '2014-09-07',
|
672
|
+
'end' => '2014-09-09',
|
673
|
+
'free_busy_status' => 'busy',
|
674
|
+
},
|
675
|
+
{
|
676
|
+
'calendar_id' => 'cal_U9uuErStTG@EAAAB_IsAsykA2DBTWqQTf-f0kJw',
|
677
|
+
'start' => '2014-09-14T19:00:00Z',
|
678
|
+
'end' => '2014-09-14T21:00:00Z',
|
679
|
+
'free_busy_status' => 'tentative',
|
680
|
+
}
|
681
|
+
]
|
682
|
+
}
|
683
|
+
end
|
684
|
+
|
685
|
+
let(:correct_mapped_result) do
|
686
|
+
first_page_items = correct_response_body['free_busy'].map { |period| Cronofy::FreeBusy.new(period) }
|
687
|
+
second_page_items = next_page_body['free_busy'].map { |period| Cronofy::FreeBusy.new(period) }
|
688
|
+
|
689
|
+
first_page_items + second_page_items
|
690
|
+
end
|
691
|
+
|
692
|
+
subject do
|
693
|
+
# By default force evaluation
|
694
|
+
client.free_busy(params).to_a
|
695
|
+
end
|
696
|
+
|
697
|
+
context 'when all params are passed' do
|
698
|
+
let(:params) do
|
699
|
+
{
|
700
|
+
from: Time.new(2014, 9, 1, 0, 0, 1, '+00:00'),
|
701
|
+
to: Time.new(2014, 10, 1, 0, 0, 1, '+00:00'),
|
702
|
+
tzid: 'Etc/UTC',
|
703
|
+
include_managed: true,
|
704
|
+
}
|
705
|
+
end
|
706
|
+
let(:request_url) do
|
707
|
+
"#{request_url_prefix}?from=2014-09-01T00:00:01Z" \
|
708
|
+
"&to=2014-10-01T00:00:01Z&tzid=Etc/UTC&include_managed=true"
|
709
|
+
end
|
710
|
+
|
711
|
+
it_behaves_like 'a Cronofy request'
|
712
|
+
it_behaves_like 'a Cronofy request with mapped return value'
|
713
|
+
end
|
714
|
+
|
715
|
+
context 'when some params are passed' do
|
716
|
+
let(:params) do
|
717
|
+
{
|
718
|
+
from: Time.new(2014, 9, 1, 0, 0, 1, '+00:00'),
|
719
|
+
}
|
720
|
+
end
|
721
|
+
let(:request_url) do
|
722
|
+
"#{request_url_prefix}?from=2014-09-01T00:00:01Z" \
|
723
|
+
"&tzid=Etc/UTC"
|
724
|
+
end
|
725
|
+
|
726
|
+
it_behaves_like 'a Cronofy request'
|
727
|
+
it_behaves_like 'a Cronofy request with mapped return value'
|
728
|
+
end
|
729
|
+
|
730
|
+
context "when unknown flags are passed" do
|
731
|
+
let(:params) do
|
732
|
+
{
|
733
|
+
unknown_bool: true,
|
734
|
+
unknown_number: 5,
|
735
|
+
unknown_string: "foo-bar-baz",
|
736
|
+
}
|
737
|
+
end
|
738
|
+
|
739
|
+
let(:request_url) do
|
740
|
+
"#{request_url_prefix}?tzid=Etc/UTC" \
|
741
|
+
"&unknown_bool=true" \
|
742
|
+
"&unknown_number=5" \
|
743
|
+
"&unknown_string=foo-bar-baz"
|
744
|
+
end
|
745
|
+
|
746
|
+
it_behaves_like 'a Cronofy request'
|
747
|
+
it_behaves_like 'a Cronofy request with mapped return value'
|
748
|
+
end
|
749
|
+
|
750
|
+
context "next page not found" do
|
751
|
+
before do
|
752
|
+
stub_request(:get, next_page_url)
|
753
|
+
.with(headers: request_headers)
|
754
|
+
.to_return(status: 404,
|
755
|
+
headers: correct_response_headers)
|
756
|
+
end
|
757
|
+
|
758
|
+
it "raises an error" do
|
759
|
+
expect{ subject }.to raise_error(::Cronofy::NotFoundError)
|
760
|
+
end
|
761
|
+
end
|
762
|
+
|
763
|
+
context "only first period" do
|
764
|
+
before do
|
765
|
+
# Ensure an error if second page is requested
|
766
|
+
stub_request(:get, next_page_url)
|
767
|
+
.with(headers: request_headers)
|
768
|
+
.to_return(status: 404,
|
769
|
+
headers: correct_response_headers)
|
770
|
+
end
|
771
|
+
|
772
|
+
let(:first_period) do
|
773
|
+
Cronofy::FreeBusy.new(correct_response_body["free_busy"].first)
|
774
|
+
end
|
775
|
+
|
776
|
+
subject do
|
777
|
+
client.free_busy(params).first
|
778
|
+
end
|
779
|
+
|
780
|
+
it "returns the first period from the first page" do
|
781
|
+
expect(subject).to eq(first_period)
|
782
|
+
end
|
783
|
+
end
|
784
|
+
|
785
|
+
context "without calling #to_a to force full evaluation" do
|
786
|
+
subject { client.free_busy(params) }
|
787
|
+
|
788
|
+
it_behaves_like 'a Cronofy request'
|
789
|
+
|
790
|
+
# We expect it to behave like a Cronofy request as the first page is
|
791
|
+
# requested eagerly so that the majority of errors will happen inline
|
792
|
+
# rather than lazily happening wherever the iterator may have been
|
793
|
+
# passed.
|
794
|
+
end
|
795
|
+
end
|
796
|
+
end
|
609
797
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cronofy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sergii Paryzhskyi
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2015-
|
12
|
+
date: 2015-10-09 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: oauth2
|