add_to_google_cal 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 974e4024ca9a078dc6c7d24f223fb5d6a0d323a9
4
+ data.tar.gz: 02c37e7e1f828a1f1b805c2f6433b7271defc479
5
+ SHA512:
6
+ metadata.gz: c8fed9839c9f837d72a9e7c20089f3fb513796d37140527677f7e1ccd24f94dab1a41a2d07c05320f871917ec2b2fe9712337b6dac6b74cf639dd87afa33c237
7
+ data.tar.gz: b50b98a6b89fa8793e3e5978d932ef9123c8988110c52368ed0e1ff999be4350da25a654139ebd433320791e3a9570e01de91ed9b90af2bc4813405419850f61
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ *.sqlite3
4
+ .bundle
5
+ .config
6
+ .yardoc
7
+ Gemfile.lock
8
+ InstalledFiles
9
+ _yardoc
10
+ coverage
11
+ doc/
12
+ lib/bundler/man
13
+ pkg
14
+ rdoc
15
+ spec/reports
16
+ test/tmp
17
+ test/version_tmp
18
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color --profile
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm --create ruby-2.0.0-p247@add-to-google-cal
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in add_to_google_cal.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Charles Bergeron
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ # AddToGoogleCal
2
+
3
+ A view layer helper which takes an object (such as an ActiveRecord instance from your database) and generates an "Add To Google Calendar" URL based on it's attributes.
4
+
5
+ This follows the ISO RFC-2445 calendar standard of using `dtstart`, `dtend`, `summary`, etc. You can customize these fields to match your implementation (ie. `start_date`, `end_date`, `event_name`, etc). Details on this below.
6
+
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'add_to_google_cal'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install add_to_google_cal
21
+
22
+ ## Usage
23
+
24
+ ### ActiveRecord:
25
+
26
+ class Wedding < AR::Base
27
+
28
+ has_google_cal
29
+
30
+ end
31
+
32
+ Wedding.first.to_google_cal
33
+
34
+ # TODO: Support custom column names, ie:
35
+ has_google_cal {
36
+ :dtstart_attribute => 'crazy_date_start_column_name'
37
+ }
38
+
39
+ ### Generic Object:
40
+
41
+ require 'ostruct'
42
+ object = OpenStruct.new({
43
+ :summary => "Super awesome event coming up in 2009, y'all!",
44
+ :dtstart => '2019-03-07'
45
+ })
46
+
47
+ AddToGoogleCal::Builder.new(object).call
48
+ => "https://www.google.com/calendar/render?action=TEMPLATE&dates=20190726T000000Z/20190726T000000Z& ..." (or something like this)
49
+
50
+ ### Ruby Hash:
51
+
52
+ attributes = {
53
+ {
54
+ dtstart: Time.utc(2013, 01, 03, 12, 00),
55
+ dtend: Time.utc(2013, 01, 03, 14, 00),
56
+ summary: 'This is the Title of the Event'
57
+ }
58
+ }
59
+
60
+ AddToGoogleCal::Builder.new(attributes).call
61
+ => 'https://www.google.com/calendar/render?action=TEMPLATE&dates=20130103T120000Z/20130103T140000Z&text=This+is+the+Title+of+the+Event'
62
+
63
+
64
+ ### erb might look like:
65
+
66
+ <%= link_to("Add To Google Calendar", AddToGoogleCal.new(object).call) %>
67
+
68
+
69
+ ## TODO:
70
+
71
+ * Handle converting various types of date/time objects
72
+ * Finish the argument validation for required fields
73
+ * Support objects / structs
74
+
75
+ * Finish implementing the ActiveRecord hook
76
+ * Support custom column names in has_google_cal AR mixin
77
+
78
+
79
+ ## Thanks To
80
+
81
+ @pcreux and everyone else who has colloborated / paired on this project.
82
+
83
+
84
+
85
+ ## Contributing
86
+
87
+ 1. Fork it
88
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
89
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
90
+ 4. Push to the branch (`git push origin my-new-feature`)
91
+ 5. Create new Pull Request
92
+
93
+
94
+
95
+ ## Why?
96
+
97
+ I was working on [Handcrafted Video Wedding Invites](http://www.craftedtoyou.com/) and this project was born out of a need to allow wedding guests quickly adding a wedding event to their Google Calendar.
98
+
99
+ http://www.craftedtoyou.com/
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'add_to_google_cal/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "add_to_google_cal"
8
+ spec.version = AddToGoogleCal::VERSION
9
+ spec.authors = ["Charles Bergeron"]
10
+ spec.email = ["hello@charlesbergeron.ca"]
11
+ spec.description = %q{A view layer helper which takes an object (such as an ActiveRecord instance from your database) and generates an "Add To Google Calendar" URL based on it's attributes.}
12
+ spec.summary = %q{Google Calendar anchor href link url helper presenter.}
13
+ spec.homepage = "https://github.com/chuckbergeron/add_to_google_cal"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'activerecord', '>= 3.0'
22
+ spec.add_development_dependency 'bundler', '>= 1.3'
23
+ # spec.add_development_dependency 'pry-debugger'
24
+ spec.add_development_dependency 'rake'
25
+ spec.add_development_dependency 'rspec', '>= 2.0'
26
+ spec.add_development_dependency 'sqlite3'
27
+ end
28
+
Binary file
@@ -0,0 +1,59 @@
1
+ require_relative 'add_to_google_cal/builder'
2
+ require_relative 'add_to_google_cal/version'
3
+
4
+ require 'active_record'
5
+ require 'cgi'
6
+ # require 'pry-debugger'
7
+
8
+ # TODO: DRY this up!
9
+ module AddToGoogleCal
10
+
11
+ module ClassMethods
12
+
13
+ # Options Example (in your model):
14
+ # has_google_cal { summary_field: 'event_name' }
15
+ #
16
+ def has_google_cal(options = {})
17
+ cattr_accessor :summary_field, :dtstart_field, :dtend_field
18
+ self.dtstart_field = (options[:dtstart_field] || :dtstart).to_s
19
+ self.dtend_field = (options[:dtend_field] || :dtend).to_s
20
+ self.summary_field = (options[:summary_field] || :summary).to_s
21
+
22
+ include AddToGoogleCal::InstanceMethods
23
+ end
24
+
25
+ end
26
+
27
+ module InstanceMethods
28
+
29
+ def to_gcal
30
+ dtstart_field = self.class.dtstart_field
31
+ dtend_field = self.class.dtend_field
32
+ summary_field = self.class.summary_field
33
+
34
+ unless self.respond_to?(dtstart_field)
35
+ raise ArgumentError, "#{self} does not have a #{dtstart_field}"
36
+ end
37
+
38
+ unless self.respond_to?(dtend_field)
39
+ raise ArgumentError, "#{self} does not have a #{dtend_field}"
40
+ end
41
+
42
+ unless self.respond_to?(summary_field)
43
+ raise ArgumentError, "#{self} does not have a #{summary_field}"
44
+ end
45
+
46
+ hash = {
47
+ dtstart: self.send(dtstart_field),
48
+ dtend: self.send(dtend_field),
49
+ summary: self.send(summary_field)
50
+ }
51
+
52
+ AddToGoogleCal::Builder.new(hash).call
53
+ end
54
+
55
+ end
56
+
57
+ end
58
+
59
+ ActiveRecord::Base.send :extend, AddToGoogleCal::ClassMethods
@@ -0,0 +1,55 @@
1
+ module AddToGoogleCal
2
+
3
+ class Builder
4
+
5
+ attr_accessor :hash
6
+
7
+ def initialize(object_or_hash)
8
+ self.hash = object_or_hash
9
+ validate!
10
+ end
11
+
12
+ # Output Examples:
13
+ #
14
+ # https://www.google.com/calendar/render?action=TEMPLATE&dates=20190726T000000Z/20190726T000000Z&sprop=website:http://john-and-marie.craftedtoyou.com&text=John+Dylan+%26+Marie+Skye&location=New+York+City+%40+12%3A00+am&sprop=name:John+Dylan+%26+Marie+Skye&details=Any+notes%2C+descriptions%2C+links%2C+or+reminders+can+be+written+here%21Accomodations%3A+Sudden+Valley+Golf+Resort+%26+Casino%0D%0A%0D%0AGroup+Name%3A+John+Dylan+%26+Marie+Skye+Wedding%0D%0A%0D%0AGroup+Reservation+%23%3A+149602%0D%0A%0D%0ARates%3A+%24149+-+%24179%0D%0A%0D%0ACut-off+date%3A+July+30%2C+2014%0D%0A%0D%0AReservations+line%3A+1.866.555.5555%0D%0A"
15
+ # https://www.google.com/calendar/render?action=TEMPLATE&dates=20131119T180000/20131119T210000&text=%23VANRUBY+Hack+Night&location=Launch+Academy+(%23300+-+128+West+Hastings+Street,+Vancouver,+BC,+Canada)&details=Vancouver+Ruby+Meetup+Group%0ATuesday,+November+19+at+6:00+PM%0A%0A%23VANRUBY+hack+nights++Every+2+weeks+on+Tuesday+we+get+together+to+hack+on+cool+stuff.+Bring+a+your+laptop+and+hack+away+on+your+favourite+open+source+...%0A%0ADetails:+http://www.meetup.com/vancouver-ruby/events/149547312/&add=chuck.bergeron@gmail.com&ctok=Y2h1Y2suYmVyZ2Vyb25AZ21haWwuY29t&sf=true&output=xml
16
+ def call
17
+ attributes = {
18
+ dates: "#{format_time(@hash[:dtstart])}/#{format_time(@hash[:dtend])}",
19
+ text: encode_string(@hash[:summary])
20
+ }
21
+
22
+ attributes.merge!(details: encode_string(@hash[:description])) unless @hash[:description].blank?
23
+ attributes.merge!(location: encode_string(@hash[:location])) unless @hash[:location].blank?
24
+
25
+ url = "https://www.google.com/calendar/render?action=TEMPLATE"
26
+
27
+ attributes.each do |key, value|
28
+ url << "&#{key}=#{value}"
29
+ end
30
+
31
+ url
32
+ end
33
+
34
+ private
35
+
36
+ def validate!
37
+ msg = "- Object must be a Date, DateTime or Time object."
38
+ raise(ArgumentError, ":dtstart #{msg} #{hash[:dtstart].class} given") unless hash[:dtstart].kind_of? Time
39
+ raise(ArgumentError, ":dtend #{msg} #{hash[:dtend].class} given") unless hash[:dtend].kind_of? Time
40
+
41
+ raise(ArgumentError, ":summary must be a string") unless hash[:summary].kind_of? String
42
+ raise(ArgumentError, ":summary must not be blank") if hash[:summary].blank?
43
+ end
44
+
45
+ def encode_string(str)
46
+ CGI.escape(str)
47
+ end
48
+
49
+ def format_time(time)
50
+ time.utc.strftime('%Y%m%dT%H%M%SZ')
51
+ end
52
+
53
+ end
54
+
55
+ end
@@ -0,0 +1,5 @@
1
+ module AddToGoogleCal
2
+
3
+ VERSION = "1.0.0"
4
+
5
+ end
@@ -0,0 +1,69 @@
1
+ require 'spec_helper'
2
+
3
+ describe AddToGoogleCal::Builder do
4
+
5
+ let(:default_attributes) {
6
+ {
7
+ dtstart: Time.utc(2013, 01, 03, 12, 00),
8
+ dtend: Time.utc(2013, 01, 03, 14, 00),
9
+ summary: 'This is the Title of the Event'
10
+ }
11
+ }
12
+
13
+ subject { AddToGoogleCal::Builder.new(default_attributes) }
14
+
15
+ it "generates the dates" do
16
+ expect(subject.call).to include("&dates=20130103T120000Z/20130103T140000Z")
17
+ end
18
+
19
+ it 'maps summary to text' do
20
+ expect(subject.call).to include("&text=This+is+the")
21
+ end
22
+
23
+ it 'supports a location' do
24
+ subject.hash.merge!(location: "Vancouver, BC")
25
+
26
+ subject.call.should include("&location=Vancouver%2C+BC")
27
+ end
28
+
29
+ it 'maps description to details' do
30
+ subject.hash.merge!(description: "Hey: How@are.you & there!")
31
+
32
+ subject.call.should include("&details=Hey%3A+How%40are.you+%26+there%21")
33
+ end
34
+
35
+ it "should raise ArgumentError for a dtstart that is not a date/time" do
36
+ subject.hash[:dtstart] = ''
37
+ expect { subject.send(:validate!) }.to raise_error(ArgumentError)
38
+ end
39
+
40
+ it "should raise ArgumentError for a dtend that is not a date/time" do
41
+ subject.hash[:dtend] = ''
42
+ expect { subject.send(:validate!) }.to raise_error(ArgumentError)
43
+ end
44
+
45
+ it "should raise ArgumentError for a summary that is not stringify'able or is blank" do
46
+ subject.hash[:summary] = ''
47
+ expect { subject.send(:validate!) }.to raise_error(ArgumentError)
48
+ end
49
+
50
+ # AR Implementation
51
+ describe "has_google_cal" do
52
+
53
+ it "builds the add to google cal link" do
54
+ wedding = Wedding.create(default_attributes)
55
+ expect(wedding.to_gcal).to include("&dates=20130103T120000Z/20130103T140000Z")
56
+ end
57
+
58
+ it "accepts options" do
59
+ event = EventNonStandardColumns.create({
60
+ start_time: Time.utc(2013, 01, 03, 12, 00),
61
+ end_time: Time.utc(2013, 01, 03, 14, 00),
62
+ event_name: 'This is the Title of the Event'
63
+ })
64
+ expect(event.to_gcal).to include("&dates=20130103T120000Z/20130103T140000Z")
65
+ end
66
+
67
+ end
68
+
69
+ end
@@ -0,0 +1,11 @@
1
+ require 'add_to_google_cal'
2
+
3
+ sqlite_file = File.dirname(__FILE__) + "/support/add_to_google_cal.sqlite3"
4
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => sqlite_file)
5
+
6
+ load File.dirname(__FILE__) + '/support/schema.rb'
7
+ load File.dirname(__FILE__) + '/support/models.rb'
8
+
9
+ RSpec.configure do |config|
10
+
11
+ end
@@ -0,0 +1,13 @@
1
+ class Wedding < ActiveRecord::Base
2
+
3
+ has_google_cal
4
+
5
+ end
6
+
7
+ class EventNonStandardColumns < ActiveRecord::Base
8
+
9
+ has_google_cal :summary_field => :event_name,
10
+ :dtstart_field => :start_time,
11
+ :dtend_field => :end_time
12
+
13
+ end
@@ -0,0 +1,21 @@
1
+ ActiveRecord::Schema.define do
2
+
3
+ self.verbose = false
4
+
5
+ create_table :weddings, :force => true do |t|
6
+ t.string :summary
7
+ t.datetime :dtstart
8
+ t.datetime :dtend
9
+
10
+ t.timestamps
11
+ end
12
+
13
+ create_table :event_non_standard_columns, :force => true do |t|
14
+ t.string :event_name
15
+ t.datetime :start_time
16
+ t.datetime :end_time
17
+
18
+ t.timestamps
19
+ end
20
+
21
+ end
metadata ADDED
@@ -0,0 +1,137 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: add_to_google_cal
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Charles Bergeron
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-12-04 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - '>='
18
+ - !ruby/object:Gem::Version
19
+ version: '3.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - '>='
25
+ - !ruby/object:Gem::Version
26
+ version: '3.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - '>='
32
+ - !ruby/object:Gem::Version
33
+ version: '1.3'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - '>='
39
+ - !ruby/object:Gem::Version
40
+ version: '1.3'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '2.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '2.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ description: A view layer helper which takes an object (such as an ActiveRecord instance
84
+ from your database) and generates an "Add To Google Calendar" URL based on it's
85
+ attributes.
86
+ email:
87
+ - hello@charlesbergeron.ca
88
+ executables: []
89
+ extensions: []
90
+ extra_rdoc_files: []
91
+ files:
92
+ - .gitignore
93
+ - .rspec
94
+ - .rvmrc
95
+ - Gemfile
96
+ - LICENSE.txt
97
+ - README.md
98
+ - Rakefile
99
+ - add_to_google_cal.gemspec
100
+ - lib/.DS_Store
101
+ - lib/add_to_google_cal.rb
102
+ - lib/add_to_google_cal/.DS_Store
103
+ - lib/add_to_google_cal/builder.rb
104
+ - lib/add_to_google_cal/version.rb
105
+ - spec/lib/add_to_google_cal_spec.rb
106
+ - spec/spec_helper.rb
107
+ - spec/support/models.rb
108
+ - spec/support/schema.rb
109
+ homepage: https://github.com/chuckbergeron/add_to_google_cal
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - '>='
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - '>='
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.0.14
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Google Calendar anchor href link url helper presenter.
133
+ test_files:
134
+ - spec/lib/add_to_google_cal_spec.rb
135
+ - spec/spec_helper.rb
136
+ - spec/support/models.rb
137
+ - spec/support/schema.rb