cal-invite 0.1.2 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CACHING.md +148 -0
- data/CHANGELOG.md +8 -0
- data/README.md +148 -17
- data/lib/cal_invite/caching.rb +74 -0
- data/lib/cal_invite/configuration.rb +39 -3
- data/lib/cal_invite/event.rb +76 -67
- data/lib/cal_invite/providers/base_provider.rb +55 -57
- data/lib/cal_invite/providers/google.rb +5 -1
- data/lib/cal_invite/providers/ical.rb +46 -13
- data/lib/cal_invite/providers/ics.rb +41 -18
- data/lib/cal_invite/providers/ics_content.rb +111 -0
- data/lib/cal_invite/providers/office365.rb +7 -7
- data/lib/cal_invite/providers/outlook.rb +8 -5
- data/lib/cal_invite/providers/yahoo.rb +7 -4
- data/lib/cal_invite/providers.rb +4 -2
- data/lib/cal_invite/version.rb +1 -1
- data/lib/cal_invite.rb +6 -0
- metadata +20 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 100b68a6d13bbb3b58234eee38701ffc1c6d215daf126ba98c89e249829d716e
|
4
|
+
data.tar.gz: ed0388023bf7245fb09c14294ce91610c189996f7c49cf246f47589efd17c1d2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9755f61af9fbed611988f3355647991c4dabe8b9a1f4ff3c0c8e77aa0c9d2c744e270aa09e01c0f7284fd0c40bce1af07a0a0a68f557e19be901969a89f32c3d
|
7
|
+
data.tar.gz: 18b4e856b14b6d5a49a2dce096b56e8b068813f058cf6648ceb9f37f04d5793454ff46bb1a7f1ed4e1f35f1e8faa796595915e84334d9763323b814744d47808
|
data/CACHING.md
ADDED
@@ -0,0 +1,148 @@
|
|
1
|
+
## Caching
|
2
|
+
|
3
|
+
CalInvite supports flexible caching options when used within a Rails application. You can configure the cache store to use any of Rails' supported cache stores including memory store, Redis, or a custom cache store implementation.
|
4
|
+
|
5
|
+
### Basic Configuration
|
6
|
+
|
7
|
+
Configure caching in your Rails application's initializer:
|
8
|
+
|
9
|
+
```ruby
|
10
|
+
# config/initializers/cal_invite.rb
|
11
|
+
CalInvite.configure do |config|
|
12
|
+
# Use Rails.cache by default
|
13
|
+
config.cache_store = Rails.cache
|
14
|
+
|
15
|
+
# Optional: Set a custom prefix for cache keys
|
16
|
+
config.cache_prefix = 'my_app_cal_invite'
|
17
|
+
|
18
|
+
# Optional: Set cache expiration (in seconds)
|
19
|
+
config.cache_expires_in = 3600 # 1 hour
|
20
|
+
end
|
21
|
+
```
|
22
|
+
|
23
|
+
### Available Cache Stores
|
24
|
+
|
25
|
+
CalInvite supports the following cache stores:
|
26
|
+
|
27
|
+
1. Memory Store (default)
|
28
|
+
```ruby
|
29
|
+
config.cache_store = :memory_store
|
30
|
+
```
|
31
|
+
|
32
|
+
2. Null Store (for disabling caching)
|
33
|
+
```ruby
|
34
|
+
config.cache_store = :null_store
|
35
|
+
```
|
36
|
+
|
37
|
+
3. Custom Cache Store
|
38
|
+
```ruby
|
39
|
+
# Any object that implements read/write/delete methods
|
40
|
+
config.cache_store = MyCacheStore.new
|
41
|
+
```
|
42
|
+
|
43
|
+
4. Rails Cache
|
44
|
+
```ruby
|
45
|
+
# Use your Rails application's configured cache
|
46
|
+
config.cache_store = Rails.cache
|
47
|
+
```
|
48
|
+
|
49
|
+
### Cache Configuration Options
|
50
|
+
|
51
|
+
- `cache_store`: The storage mechanism for cached data
|
52
|
+
- `cache_prefix`: Prefix for all cache keys (default: 'cal_invite')
|
53
|
+
- `cache_expires_in`: Default cache expiration time in seconds
|
54
|
+
- `timezone`: Default timezone for cache keys (default: 'UTC')
|
55
|
+
|
56
|
+
### Custom Cache Adapters
|
57
|
+
|
58
|
+
You can implement custom cache adapters by creating a class that responds to the following methods:
|
59
|
+
|
60
|
+
```ruby
|
61
|
+
class CustomCacheStore
|
62
|
+
def read(key)
|
63
|
+
# Implementation for retrieving cached value
|
64
|
+
end
|
65
|
+
|
66
|
+
def write(key, value, options = {})
|
67
|
+
# Implementation for storing value in cache
|
68
|
+
# options may include :expires_in
|
69
|
+
end
|
70
|
+
|
71
|
+
def delete(key)
|
72
|
+
# Implementation for removing cached value
|
73
|
+
end
|
74
|
+
|
75
|
+
def clear
|
76
|
+
# Implementation for clearing all cached values
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
# Configure CalInvite to use your custom cache store
|
81
|
+
CalInvite.configure do |config|
|
82
|
+
config.cache_store = CustomCacheStore.new
|
83
|
+
end
|
84
|
+
```
|
85
|
+
|
86
|
+
### Automatic Cache Invalidation
|
87
|
+
|
88
|
+
The cache is automatically invalidated in the following scenarios:
|
89
|
+
|
90
|
+
1. When event attributes are updated via `update_attributes`
|
91
|
+
2. When a new calendar URL is generated
|
92
|
+
3. When the configuration changes
|
93
|
+
|
94
|
+
### Best Practices
|
95
|
+
|
96
|
+
1. **Cache Store Selection**: Choose an appropriate cache store based on your needs:
|
97
|
+
- Use `:memory_store` for development and small applications
|
98
|
+
- Use Rails.cache for production applications
|
99
|
+
- Implement a custom cache store for specific requirements
|
100
|
+
|
101
|
+
2. **Cache Key Management**:
|
102
|
+
- The gem automatically generates unique cache keys based on event attributes
|
103
|
+
- Keys include a prefix for namespace isolation
|
104
|
+
- Consider your timezone settings when debugging cache issues
|
105
|
+
|
106
|
+
3. **Expiration Strategy**:
|
107
|
+
- Set appropriate expiration times based on your use case
|
108
|
+
- Consider using shorter expiration times for frequently changing data
|
109
|
+
- Use `nil` expiration for permanent caching (until manual invalidation)
|
110
|
+
|
111
|
+
### Example Rails Integration
|
112
|
+
|
113
|
+
Here's a complete example of setting up caching in a Rails application:
|
114
|
+
|
115
|
+
```ruby
|
116
|
+
# config/initializers/cal_invite.rb
|
117
|
+
CalInvite.configure do |config|
|
118
|
+
if Rails.env.production?
|
119
|
+
# Use Rails cache in production
|
120
|
+
config.cache_store = Rails.cache
|
121
|
+
config.cache_expires_in = 1.hour
|
122
|
+
else
|
123
|
+
# Use memory store in development
|
124
|
+
config.cache_store = :memory_store
|
125
|
+
config.cache_expires_in = 5.minutes
|
126
|
+
end
|
127
|
+
|
128
|
+
config.cache_prefix = "cal_invite:#{Rails.env}"
|
129
|
+
config.timezone = 'UTC'
|
130
|
+
end
|
131
|
+
```
|
132
|
+
|
133
|
+
### Testing with Caching
|
134
|
+
|
135
|
+
When writing tests that involve caching:
|
136
|
+
|
137
|
+
```ruby
|
138
|
+
# In your test setup
|
139
|
+
CalInvite.configure do |config|
|
140
|
+
config.cache_store = :memory_store
|
141
|
+
config.cache_expires_in = 3600 # 1 hour in seconds
|
142
|
+
end
|
143
|
+
|
144
|
+
# Clear cache between tests
|
145
|
+
def setup
|
146
|
+
CalInvite.configuration.cache_store.clear
|
147
|
+
end
|
148
|
+
```
|
data/CHANGELOG.md
CHANGED
@@ -2,6 +2,14 @@
|
|
2
2
|
|
3
3
|
## [Released]
|
4
4
|
|
5
|
+
## [v0.1.3] - 2024-12-19
|
6
|
+
|
7
|
+
- Apple iCal and ics file can now be either generated or wrap to be downloaded
|
8
|
+
- Add Caching management support
|
9
|
+
- Add CACHING.md for more details about how to use caching in a Rails app
|
10
|
+
- Updating the README file to reflect latest usage changes
|
11
|
+
- Minor bug fixes and improvments.
|
12
|
+
|
5
13
|
## [v0.1.2] - 2024-12-17
|
6
14
|
|
7
15
|
- Add support to Microsoft office 365 calendar invite URL
|
data/README.md
CHANGED
@@ -4,7 +4,6 @@ A Ruby gem for generating calendar invitations across multiple calendar platform
|
|
4
4
|
|
5
5
|
[](https://badge.fury.io/rb/cal-invite)
|
6
6
|

|
7
|
-
|
8
7
|
[]
|
9
8
|
|
10
9
|
## Compatibility
|
@@ -15,7 +14,7 @@ A Ruby gem for generating calendar invitations across multiple calendar platform
|
|
15
14
|
## Supported Calendar Platforms
|
16
15
|
|
17
16
|
Direct Integration:
|
18
|
-
- Apple iCal
|
17
|
+
- Apple iCal (with proper timezone support)
|
19
18
|
- Microsoft Outlook
|
20
19
|
- Microsoft Outlook 365
|
21
20
|
- Google Calendar
|
@@ -52,21 +51,47 @@ $ gem install cal-invite
|
|
52
51
|
|
53
52
|
### Basic Event Creation
|
54
53
|
|
54
|
+
Important notes:
|
55
|
+
- Always provide times in UTC
|
56
|
+
- Use the timezone parameter to specify the display timezone
|
57
|
+
- Location and URL are handled separately for better calendar integration
|
58
|
+
|
55
59
|
```ruby
|
56
|
-
#
|
60
|
+
# Create an event with physical location
|
57
61
|
event = CalInvite::Event.new(
|
58
62
|
title: "Team Meeting",
|
59
|
-
start_time: Time.current,
|
60
|
-
end_time: Time.current + 2.hours,
|
63
|
+
start_time: Time.current.utc, # Always use UTC times
|
64
|
+
end_time: Time.current.utc + 2.hours,
|
61
65
|
description: "Weekly team sync",
|
62
|
-
location: "Conference Room A",
|
63
|
-
|
66
|
+
location: "Conference Room A", # Physical location
|
67
|
+
timezone: "America/New_York", # Display timezone
|
64
68
|
attendees: ["person@example.com"],
|
65
69
|
show_attendees: true,
|
66
|
-
timezone: "America/New_York",
|
67
70
|
notes: "Please bring your laptop"
|
68
71
|
)
|
69
72
|
|
73
|
+
# Create an event with both physical and virtual locations
|
74
|
+
event = CalInvite::Event.new(
|
75
|
+
title: "Hybrid Meeting",
|
76
|
+
start_time: Time.current.utc,
|
77
|
+
end_time: Time.current.utc + 2.hours,
|
78
|
+
description: "Weekly team sync",
|
79
|
+
location: "Conference Room A", # Physical location
|
80
|
+
url: "https://zoom.us/j/123456789", # Virtual meeting URL
|
81
|
+
timezone: "America/New_York",
|
82
|
+
attendees: ["person@example.com"],
|
83
|
+
show_attendees: true
|
84
|
+
)
|
85
|
+
|
86
|
+
# All-day event
|
87
|
+
event = CalInvite::Event.new(
|
88
|
+
title: "Company All-Day Event",
|
89
|
+
start_time: Date.today.beginning_of_day.utc,
|
90
|
+
end_time: Date.today.end_of_day.utc,
|
91
|
+
all_day: true,
|
92
|
+
timezone: "America/New_York"
|
93
|
+
)
|
94
|
+
|
70
95
|
# Multi-day event
|
71
96
|
event = CalInvite::Event.new(
|
72
97
|
title: "Training Workshop",
|
@@ -82,19 +107,125 @@ event = CalInvite::Event.new(
|
|
82
107
|
],
|
83
108
|
description: "Advanced Ruby Training",
|
84
109
|
location: "Training Center",
|
85
|
-
url: "https://zoom.us/j/123456789",
|
110
|
+
url: "https://zoom.us/j/123456789", # Virtual meeting URL kept separate
|
86
111
|
timezone: "America/New_York",
|
87
112
|
notes: "Bring your own laptop"
|
88
113
|
)
|
89
114
|
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
115
|
+
# Generate calendar URLs
|
116
|
+
ical_url = event.generate_calendar_url(:ical)
|
117
|
+
google_url = event.generate_calendar_url(:google)
|
118
|
+
outlook_url = event.generate_calendar_url(:outlook)
|
119
|
+
outlook365_url = event.generate_calendar_url(:office365)
|
120
|
+
yahoo_url = event.generate_calendar_url(:yahoo)
|
121
|
+
```
|
122
|
+
|
123
|
+
### Implementing ICS Downloads
|
124
|
+
|
125
|
+
To enable ICS file downloads in your application, you'll need to:
|
126
|
+
|
127
|
+
1. Create an endpoint that will handle the download request
|
128
|
+
2. Generate the ICS content
|
129
|
+
3. Send the file to the user
|
130
|
+
|
131
|
+
Here's a basic example of the controller logic:
|
132
|
+
|
133
|
+
```ruby
|
134
|
+
# In your controller action
|
135
|
+
def download_calendar
|
136
|
+
event = # ... your event creation logic ...
|
137
|
+
|
138
|
+
content = CalInvite::Providers::Ics.new(event).generate
|
139
|
+
filename = "#{event.title.downcase.gsub(/[^0-9A-Za-z.\-]/, '_')}_#{Time.now.strftime('%Y%m%d')}.ics"
|
140
|
+
|
141
|
+
send_data(
|
142
|
+
content,
|
143
|
+
filename: filename,
|
144
|
+
type: 'text/calendar; charset=UTF-8',
|
145
|
+
disposition: 'attachment'
|
146
|
+
)
|
147
|
+
end
|
96
148
|
```
|
97
149
|
|
150
|
+
You can implement this in any controller and route that makes sense for your application's architecture.
|
151
|
+
|
152
|
+
### ICS File Generation
|
153
|
+
|
154
|
+
The gem provides two ways to generate ICS files:
|
155
|
+
|
156
|
+
1. Direct content generation:
|
157
|
+
```ruby
|
158
|
+
event = CalInvite::Event.new(
|
159
|
+
title: "Meeting",
|
160
|
+
start_time: Time.current.utc,
|
161
|
+
end_time: Time.current.utc + 1.hour,
|
162
|
+
timezone: "America/New_York"
|
163
|
+
)
|
164
|
+
|
165
|
+
# Generate ICS content
|
166
|
+
content = CalInvite::Providers::Ics.new(event).generate
|
167
|
+
```
|
168
|
+
|
169
|
+
2. Rails controller integration:
|
170
|
+
```ruby
|
171
|
+
# In your controller
|
172
|
+
def download_ics
|
173
|
+
event = CalInvite::Event.new(
|
174
|
+
title: "Meeting",
|
175
|
+
start_time: Time.current.utc,
|
176
|
+
end_time: Time.current.utc + 1.hour,
|
177
|
+
timezone: "America/New_York"
|
178
|
+
)
|
179
|
+
|
180
|
+
content = CalInvite::Providers::Ics.new(event).generate
|
181
|
+
filename = "#{event.title.downcase.gsub(/[^0-9A-Za-z.\-]/, '_')}_#{Time.now.strftime('%Y%m%d')}.ics"
|
182
|
+
|
183
|
+
send_data(
|
184
|
+
content,
|
185
|
+
filename: filename,
|
186
|
+
type: 'text/calendar; charset=UTF-8',
|
187
|
+
disposition: 'attachment'
|
188
|
+
)
|
189
|
+
end
|
190
|
+
```
|
191
|
+
|
192
|
+
### Important Notes
|
193
|
+
|
194
|
+
1. Time Handling:
|
195
|
+
- Always provide times in UTC to the Event constructor
|
196
|
+
- Use the timezone parameter to specify the display timezone
|
197
|
+
- All-day events should use beginning_of_day.utc and end_of_day.utc
|
198
|
+
|
199
|
+
2. Location and URL:
|
200
|
+
- Physical location goes in the `location` parameter
|
201
|
+
- Virtual meeting URL goes in the `url` parameter
|
202
|
+
- They are handled separately for better calendar integration
|
203
|
+
|
204
|
+
3. ICS Files:
|
205
|
+
- Both Apple iCal and standard ICS files now properly handle timezones
|
206
|
+
- Attendees are properly formatted with RSVP options
|
207
|
+
- Virtual meeting URLs are properly separated from physical locations
|
208
|
+
|
209
|
+
## Caching Support
|
210
|
+
|
211
|
+
CalInvite includes built-in caching support to improve performance when generating calendar URLs. To enable caching in your Rails application:
|
212
|
+
|
213
|
+
```ruby
|
214
|
+
# config/initializers/cal_invite.rb
|
215
|
+
CalInvite.configure do |config|
|
216
|
+
# Use Rails cache by default
|
217
|
+
config.cache_store = Rails.cache
|
218
|
+
|
219
|
+
# Optional: Set cache prefix
|
220
|
+
config.cache_prefix = 'my_app_cal_invite'
|
221
|
+
|
222
|
+
# Optional: Set expiration time (in seconds)
|
223
|
+
config.cache_expires_in = 3600 # 1 hour
|
224
|
+
end
|
225
|
+
```
|
226
|
+
|
227
|
+
For detailed information about configuring caching in Rails applications and available options, see our [Caching Guide](https://github.com/the-pew-inc/cal-invite/blob/master/CACHING.md)
|
228
|
+
|
98
229
|
## Development
|
99
230
|
|
100
231
|
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
@@ -105,7 +236,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
|
|
105
236
|
|
106
237
|
Add test(s) as necessary.
|
107
238
|
|
108
|
-
Run all the tests before
|
239
|
+
Run all the tests before submitting: `bundle exec rake test`
|
109
240
|
|
110
241
|
## Contributing
|
111
242
|
|
@@ -117,4 +248,4 @@ The gem is available as open source under the terms of the [MIT License](https:/
|
|
117
248
|
|
118
249
|
## Code of Conduct
|
119
250
|
|
120
|
-
Everyone interacting in the Cal::Invite project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/the-pew-inc/cal-invite/blob/master/CODE_OF_CONDUCT.md).
|
251
|
+
Everyone interacting in the Cal::Invite project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/the-pew-inc/cal-invite/blob/master/CODE_OF_CONDUCT.md).
|
@@ -0,0 +1,74 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# lib/cal_invite/caching.rb
|
4
|
+
require 'active_support/concern'
|
5
|
+
|
6
|
+
module CalInvite
|
7
|
+
module Caching
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
class_methods do
|
11
|
+
def fetch_from_cache(key, options = {}, &block)
|
12
|
+
full_key = generate_cache_key(key)
|
13
|
+
store = CalInvite.configuration.cache_store
|
14
|
+
|
15
|
+
if store.respond_to?(:fetch)
|
16
|
+
store.fetch(full_key, options, &block)
|
17
|
+
else
|
18
|
+
cached = store.read(full_key)
|
19
|
+
return cached if cached
|
20
|
+
|
21
|
+
value = block.call
|
22
|
+
store.write(full_key, value, options)
|
23
|
+
value
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def write_to_cache(key, value, options = {})
|
28
|
+
full_key = generate_cache_key(key)
|
29
|
+
options[:expires_in] ||= CalInvite.configuration.cache_expires_in
|
30
|
+
CalInvite.configuration.cache_store.write(full_key, value, options)
|
31
|
+
end
|
32
|
+
|
33
|
+
def read_from_cache(key)
|
34
|
+
full_key = generate_cache_key(key)
|
35
|
+
CalInvite.configuration.cache_store.read(full_key)
|
36
|
+
end
|
37
|
+
|
38
|
+
def clear_cache!
|
39
|
+
store = CalInvite.configuration.cache_store
|
40
|
+
if store.respond_to?(:delete_matched)
|
41
|
+
store.delete_matched("#{CalInvite.configuration.cache_prefix}:*")
|
42
|
+
else
|
43
|
+
store.clear
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def clear_event_cache!(event_id)
|
48
|
+
delete_cache_pattern("events:#{event_id}")
|
49
|
+
end
|
50
|
+
|
51
|
+
def clear_provider_cache!(provider)
|
52
|
+
delete_cache_pattern("providers:#{provider}")
|
53
|
+
end
|
54
|
+
|
55
|
+
def generate_cache_key(*parts)
|
56
|
+
([CalInvite.configuration.cache_prefix] + parts).join(':')
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def delete_cache_pattern(pattern)
|
62
|
+
store = CalInvite.configuration.cache_store
|
63
|
+
full_pattern = generate_cache_key(pattern)
|
64
|
+
|
65
|
+
if store.respond_to?(:delete_matched)
|
66
|
+
store.delete_matched("#{full_pattern}:*")
|
67
|
+
else
|
68
|
+
# Fallback for stores that don't support pattern deletion
|
69
|
+
store.delete(full_pattern)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -1,13 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# lib/cal_invite/configuration.rb
|
2
|
-
module
|
4
|
+
module CalInvite
|
3
5
|
class Configuration
|
4
|
-
|
6
|
+
attr_reader :cache_store, :cache_prefix, :cache_expires_in, :webhook_secret, :timezone
|
5
7
|
|
6
8
|
def initialize
|
7
|
-
@cache_store =
|
9
|
+
@cache_store = nil
|
8
10
|
@cache_prefix = 'cal_invite'
|
11
|
+
@cache_expires_in = 24.hours # now this will work with active_support loaded
|
9
12
|
@webhook_secret = nil
|
10
13
|
@timezone = 'UTC'
|
11
14
|
end
|
15
|
+
|
16
|
+
def cache_store=(store)
|
17
|
+
@cache_store = case store
|
18
|
+
when :memory_store
|
19
|
+
ActiveSupport::Cache::MemoryStore.new
|
20
|
+
when :null_store
|
21
|
+
ActiveSupport::Cache::NullStore.new
|
22
|
+
when Symbol
|
23
|
+
raise ArgumentError, "Unsupported cache store: #{store}"
|
24
|
+
else
|
25
|
+
# Allow custom cache store objects that respond to read/write/delete
|
26
|
+
unless store.respond_to?(:read) && store.respond_to?(:write) && store.respond_to?(:delete)
|
27
|
+
raise ArgumentError, "Custom cache store must implement read/write/delete methods"
|
28
|
+
end
|
29
|
+
store
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def cache_prefix=(prefix)
|
34
|
+
@cache_prefix = prefix.to_s
|
35
|
+
end
|
36
|
+
|
37
|
+
def cache_expires_in=(duration)
|
38
|
+
@cache_expires_in = duration.to_i
|
39
|
+
end
|
40
|
+
|
41
|
+
def webhook_secret=(secret)
|
42
|
+
@webhook_secret = secret
|
43
|
+
end
|
44
|
+
|
45
|
+
def timezone=(tz)
|
46
|
+
@timezone = tz.to_s
|
47
|
+
end
|
12
48
|
end
|
13
49
|
end
|