eventdb 0.0.1 → 0.1.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.
- checksums.yaml +4 -4
- data/.gemtest +0 -0
- data/Manifest.txt +15 -0
- data/README.md +29 -10
- data/Rakefile +0 -2
- data/bin/rubyconf +17 -0
- data/lib/eventdb/calendar.rb +73 -0
- data/lib/eventdb/database.rb +46 -0
- data/lib/eventdb/models.rb +12 -0
- data/lib/eventdb/reader.rb +178 -0
- data/lib/eventdb/rubyconf.rb +40 -0
- data/lib/eventdb/schema.rb +24 -0
- data/lib/eventdb/version.rb +2 -2
- data/lib/eventdb.rb +23 -0
- data/templates/CALENDAR.md.erb +24 -0
- data/test/data/RUBY.md +647 -0
- data/test/helper.rb +8 -0
- data/test/test_calendar.rb +50 -0
- data/test/test_database.rb +37 -0
- data/test/test_reader.rb +26 -0
- data/test/test_rubyconf.rb +21 -0
- data/test/test_version.rb +18 -0
- metadata +25 -31
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64679b23d00fead03540ef38cdabb5c89a5a21e2
|
4
|
+
data.tar.gz: 6ad469e6a30aadc53fc0fe9588523a5b3ee76a91
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2a24433d3494b0ca8f33f9026a16935f37926d6fa41c90296769f5fadca446c2751ed0673b9d5b9a541ab00ad83f369ef0348af9bedbf5dd089c9db1ded0f111
|
7
|
+
data.tar.gz: 5b20c163139483092d455bfe4364fc57e50e16c3c60ee7252225b81017be99bfe521483065c1defa721e904abb15d57c1327f43e3c100d7115e5c06df2cbc51d
|
data/.gemtest
ADDED
File without changes
|
data/Manifest.txt
CHANGED
@@ -2,5 +2,20 @@ HISTORY.md
|
|
2
2
|
Manifest.txt
|
3
3
|
README.md
|
4
4
|
Rakefile
|
5
|
+
bin/rubyconf
|
5
6
|
lib/eventdb.rb
|
7
|
+
lib/eventdb/calendar.rb
|
8
|
+
lib/eventdb/database.rb
|
9
|
+
lib/eventdb/models.rb
|
10
|
+
lib/eventdb/reader.rb
|
11
|
+
lib/eventdb/rubyconf.rb
|
12
|
+
lib/eventdb/schema.rb
|
6
13
|
lib/eventdb/version.rb
|
14
|
+
templates/CALENDAR.md.erb
|
15
|
+
test/data/RUBY.md
|
16
|
+
test/helper.rb
|
17
|
+
test/test_calendar.rb
|
18
|
+
test/test_database.rb
|
19
|
+
test/test_reader.rb
|
20
|
+
test/test_rubyconf.rb
|
21
|
+
test/test_version.rb
|
data/README.md
CHANGED
@@ -6,7 +6,7 @@ event.db models n tools
|
|
6
6
|
* bugs :: [github.com/textkit/event.db/issues](https://github.com/textkit/event.db/issues)
|
7
7
|
* gem :: [rubygems.org/gems/eventdb](https://rubygems.org/gems/eventdb)
|
8
8
|
* rdoc :: [rubydoc.info/gems/eventdb](http://rubydoc.info/gems/eventdb)
|
9
|
-
* forum :: [ruby-talk@ruby-lang.org](www.ruby-lang.org/en/community/mailing-lists)
|
9
|
+
* forum :: [ruby-talk@ruby-lang.org](http://www.ruby-lang.org/en/community/mailing-lists)
|
10
10
|
|
11
11
|
|
12
12
|
## Command-Line Tool Usage
|
@@ -18,15 +18,34 @@ The eventdb gem includes command-line tools to list upcoming events.
|
|
18
18
|
|
19
19
|
Use
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
21
|
+
~~~
|
22
|
+
$ rubyconf
|
23
|
+
~~~
|
24
|
+
|
25
|
+
to list the upcoming Ruby conferences from around the world. Will print:
|
26
|
+
|
27
|
+
~~~
|
28
|
+
Upcoming Ruby Conferences:
|
29
|
+
|
30
|
+
Jul/1+2 - RubyMotion Conference - #inspect @ Paris, France › Europe
|
31
|
+
Jul/20 - Brighton Ruby Conference @ Brighton, East Sussex › England (en) › Western Europe › Europe
|
32
|
+
Jul/31-Aug/2 - European Ruby Camp - eurucamp @ Berlin (Potsdam), Germany › Europe
|
33
|
+
Jul/31 - JRuby Conference Europe - JRubyConf EU @ Berlin (Potdam), Germany › Europe
|
34
|
+
Aug/1+2 - Burlington Ruby Conference @ Burlington, Vermont › New England › United States (us) › North America › America
|
35
|
+
Aug/21+22 - Madison+ Ruby @ Madison, Wisconsin › Great Lakes › United States (us) › North America › America
|
36
|
+
Sept/1–5 - Full Stack Fest - Barcelona Ruby Conference (BaRuCo) + Barcelona Future JS @ Barcelona, Catalonia › Spain / España (es) › Southern Europe › Europe
|
37
|
+
Sept/11+12 - RubyConf Taiwan @ Taipei › Taiwan (tw) › Asia
|
38
|
+
Sep/14+15 - RubyConf Portugal @ Braga › Portugal (pt) › Southern Europe › Europe
|
39
|
+
Sept/18+19 - RubyConf Brasil @ São Paulo › Brazil / Brasil (br) › South America › America
|
40
|
+
Sept/23-25 - Rocky Mountain Ruby Conference @ Boulder, Colorado › Rocky Mountains › United States (us) › North America › America
|
41
|
+
Sept/26 - Ruby Open Source Software (ROSS) Conference - ROSSConf @ Berlin, Germany › Europe
|
42
|
+
Oct/1+2 - ArrrCamp @ Ghent, Oost-Vlaanderen › Belgium / België / Belgique (be) › Western Europe › Europe
|
43
|
+
Oct/15+16 - RubyConf Colombia @ Medellin › Colombia (co) › South America › America
|
44
|
+
Oct/17+18 - European Ruby Konference - EuRuKo @ Salzburg, Austria › Europe
|
45
|
+
Nov/11+12 - RubyWorld Conference @ Matsue › Japan (jp) › Asia
|
46
|
+
|
47
|
+
More @ github.com/planetruby/awesome-events
|
48
|
+
~~~
|
30
49
|
|
31
50
|
|
32
51
|
|
data/Rakefile
CHANGED
data/bin/rubyconf
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
###################
|
4
|
+
# == DEV TIPS:
|
5
|
+
#
|
6
|
+
# For local testing run like:
|
7
|
+
#
|
8
|
+
# ruby -Ilib bin/rubyconf
|
9
|
+
#
|
10
|
+
# Set the executable bit in Linux. Example:
|
11
|
+
#
|
12
|
+
# % chmod a+x bin/rubyconf
|
13
|
+
#
|
14
|
+
|
15
|
+
require 'eventdb'
|
16
|
+
|
17
|
+
EventDb::RubyConf.new.print
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module EventDb
|
4
|
+
|
5
|
+
class EventCursor
|
6
|
+
def initialize( events )
|
7
|
+
@events = events
|
8
|
+
end
|
9
|
+
|
10
|
+
def each
|
11
|
+
state = State.new
|
12
|
+
@events.each do |event|
|
13
|
+
state.next( event )
|
14
|
+
yield( event, state )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class State
|
19
|
+
def initialize
|
20
|
+
@last_date = Date.new( 1971, 1, 1 )
|
21
|
+
@new_date = true
|
22
|
+
@new_year = true
|
23
|
+
@new_month = true
|
24
|
+
end
|
25
|
+
def new_date?() @new_date; end
|
26
|
+
def new_year?() @new_year; end
|
27
|
+
def new_month?() @new_month; end
|
28
|
+
|
29
|
+
def next( event )
|
30
|
+
if @last_date.year == event.start_date.year &&
|
31
|
+
@last_date.month == event.start_date.month
|
32
|
+
@new_date = false
|
33
|
+
@new_year = false
|
34
|
+
@new_month = false
|
35
|
+
else
|
36
|
+
@new_date = true
|
37
|
+
## new year?
|
38
|
+
@new_year = @last_date.year != event.start_date.year ? true : false
|
39
|
+
## new_month ?
|
40
|
+
@new_month = (@new_year == true || @last_date.month != event.start_date.month) ? true : false
|
41
|
+
end
|
42
|
+
@last_date = event.start_date
|
43
|
+
end
|
44
|
+
|
45
|
+
end # class State
|
46
|
+
|
47
|
+
end # class EventCursor
|
48
|
+
|
49
|
+
|
50
|
+
class EventCalendar
|
51
|
+
|
52
|
+
def initialize( events )
|
53
|
+
@events = events.sort { |l,r| r.start_date <=> l.start_date } ## sort events by date (newest first)
|
54
|
+
@tmpl = File.read_utf8( "#{EventDb.root}/templates/CALENDAR.md.erb" )
|
55
|
+
end
|
56
|
+
|
57
|
+
def events
|
58
|
+
## note: return new cursor -- use decorator (instead of extra loop arg, why? why not?
|
59
|
+
EventCursor.new( @events )
|
60
|
+
end
|
61
|
+
|
62
|
+
def render
|
63
|
+
ERB.new( @tmpl, nil, '<>' ).result( binding ) # <> omit newline for lines starting with <% and ending in %>
|
64
|
+
end
|
65
|
+
|
66
|
+
def save( path = './CALENDAR.md' ) ## use (rename to) save_as - why? why not??
|
67
|
+
File.open( path, 'w' ) do |f|
|
68
|
+
f.write( render )
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end # class EventCalendar
|
72
|
+
|
73
|
+
end # module EventDb
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module EventDb
|
4
|
+
|
5
|
+
class Database
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
## connect
|
9
|
+
|
10
|
+
ActiveRecord::Base.establish_connection( adapter: 'sqlite3',
|
11
|
+
database: ':memory:' )
|
12
|
+
|
13
|
+
LogDb.create # add logs table
|
14
|
+
ConfDb.create
|
15
|
+
|
16
|
+
CreateDb.new.up
|
17
|
+
ConfDb::Model::Prop.create!( key: 'db.schema.event.version', value: VERSION )
|
18
|
+
end
|
19
|
+
|
20
|
+
|
21
|
+
def add( events )
|
22
|
+
events.each do |ev|
|
23
|
+
|
24
|
+
## note: extract title from first (markdown) link
|
25
|
+
m = (ev.title =~ /^\[([^\]]+)\]/)
|
26
|
+
if m
|
27
|
+
title = $1
|
28
|
+
puts " adding #{title} #{ev.start_date.year}, #{ev.date}"
|
29
|
+
else
|
30
|
+
puts "warn: cannot find event title in #{ev.title}"
|
31
|
+
next # skip record; todo: issue error
|
32
|
+
end
|
33
|
+
|
34
|
+
Model::Event.create!(
|
35
|
+
title: title,
|
36
|
+
place: ev.place,
|
37
|
+
date: ev.date,
|
38
|
+
start_date: ev.start_date
|
39
|
+
)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end # class Database
|
44
|
+
|
45
|
+
end # module EventDb
|
46
|
+
|
@@ -0,0 +1,178 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
|
4
|
+
module EventDb
|
5
|
+
|
6
|
+
|
7
|
+
class EventReader
|
8
|
+
|
9
|
+
include LogUtils::Logging
|
10
|
+
|
11
|
+
|
12
|
+
Event = Struct.new( :title, :place, :date, :start_date)
|
13
|
+
|
14
|
+
def self.from_url( src ) # note: src assumed a string
|
15
|
+
worker = Fetcher::Worker.new
|
16
|
+
self.from_string( worker.read_utf8!( src ) )
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.from_file( path )
|
20
|
+
self.from_string( File.read_utf8( path ) )
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.from_string( text )
|
24
|
+
self.new( text )
|
25
|
+
end
|
26
|
+
|
27
|
+
|
28
|
+
def initialize( text )
|
29
|
+
@text = text
|
30
|
+
end
|
31
|
+
|
32
|
+
MONTH_EN_TO_MM = {
|
33
|
+
'Jan' => '1',
|
34
|
+
'Feb' => '2',
|
35
|
+
'Mar' => '3', 'March' => '3',
|
36
|
+
'Apr' => '4', 'April' => '4',
|
37
|
+
'May' => '5',
|
38
|
+
'Jun' => '6', 'June' => '6',
|
39
|
+
'Jul' => '7', 'July' => '7',
|
40
|
+
'Aug' => '8',
|
41
|
+
'Sep' => '9', 'Sept' => '9',
|
42
|
+
'Oct' => '10',
|
43
|
+
'Nov' => '11',
|
44
|
+
'Dec' => '12' }
|
45
|
+
|
46
|
+
MONTH_EN = MONTH_EN_TO_MM.keys.join('|') # e.g. 'Jan|Feb|March|Mar|...'
|
47
|
+
|
48
|
+
## examples:
|
49
|
+
## - 2015 @ Salzburg, Austria; Oct/17+18
|
50
|
+
## - 2015 @ Brussels / Brussel / Bruxelles; Jan/31+Feb/1
|
51
|
+
## - 2014 @ Porto de Galinhas, Pernambuco; Apr/24-27 (formerly: Abril Pro Ruby)
|
52
|
+
|
53
|
+
DATE_ENTRY_REGEX = /\s+
|
54
|
+
(?<year>201\d) ## year
|
55
|
+
\s+
|
56
|
+
@ ## at location
|
57
|
+
\s+
|
58
|
+
[^;]+ ## use ; as separator between place and date
|
59
|
+
;
|
60
|
+
\s+
|
61
|
+
(?<month_en>#{MONTH_EN})
|
62
|
+
\/
|
63
|
+
(?<day>[0-9]{1,2}) ## start date
|
64
|
+
/x
|
65
|
+
|
66
|
+
|
67
|
+
## example:
|
68
|
+
## - [RubyWorld Conference - rubyworldconf](http://www.rubyworld-conf.org/en)
|
69
|
+
|
70
|
+
LINK_ENTRY_REGEX = /\s+
|
71
|
+
\[
|
72
|
+
[^\]]+
|
73
|
+
\]
|
74
|
+
\(
|
75
|
+
[^\)]+
|
76
|
+
\)
|
77
|
+
/x
|
78
|
+
|
79
|
+
|
80
|
+
def read
|
81
|
+
|
82
|
+
events = []
|
83
|
+
stack = [] ## header/heading stack; note: last_stack is stack.size; starts w/ 0
|
84
|
+
|
85
|
+
last_link_entry = nil
|
86
|
+
|
87
|
+
@text.each_line do |line|
|
88
|
+
|
89
|
+
logger.debug "line: >#{line}<"
|
90
|
+
line = line.rstrip ## remove (possible) trailing newline
|
91
|
+
|
92
|
+
break if line =~ /^## More/ # stop when hitting >## More< section
|
93
|
+
next if line =~ /^\s*$/ # skip blank lines
|
94
|
+
|
95
|
+
m = nil
|
96
|
+
if line =~ /^[ ]*(#+)[ ]+/ ## heading/headers - note: must escpape #
|
97
|
+
s = StringScanner.new( line )
|
98
|
+
s.skip( /[ ]*/ ) ## skip whitespaces
|
99
|
+
markers = s.scan( /#+/)
|
100
|
+
level = markers.size
|
101
|
+
s.skip( /[ ]*/ ) ## skip whitespaces
|
102
|
+
title = s.rest.rstrip
|
103
|
+
|
104
|
+
logger.debug " heading level: #{level}, title: >#{title}<"
|
105
|
+
|
106
|
+
level_diff = level - stack.size
|
107
|
+
|
108
|
+
if level_diff > 0
|
109
|
+
logger.debug "[EventReader] up +#{level_diff}"
|
110
|
+
if level_diff > 1
|
111
|
+
logger.error "fatal: level step must be one (+1) is +#{level_diff}"
|
112
|
+
fail "[EventReader] level step must be one (+1) is +#{level_diff}"
|
113
|
+
end
|
114
|
+
elsif level_diff < 0
|
115
|
+
logger.debug "[EventReader] down #{level_diff}"
|
116
|
+
level_diff.abs.times { stack.pop }
|
117
|
+
stack.pop
|
118
|
+
else
|
119
|
+
## same level
|
120
|
+
stack.pop
|
121
|
+
end
|
122
|
+
stack.push( [level,title] )
|
123
|
+
logger.debug " stack: #{stack.inspect}"
|
124
|
+
|
125
|
+
elsif line =~ /^[ ]*-[ ]+/ ## list item
|
126
|
+
if( m=LINK_ENTRY_REGEX.match( line ) )
|
127
|
+
logger.debug " link entry: #{line}"
|
128
|
+
|
129
|
+
s = StringScanner.new( line )
|
130
|
+
s.skip( /[ ]*-[ ]*/ ) ## skip leading list
|
131
|
+
last_link_entry = s.rest.rstrip ## remove trailing spaces to
|
132
|
+
elsif( m=DATE_ENTRY_REGEX.match( line ) )
|
133
|
+
year = m[:year]
|
134
|
+
month_en = m[:month_en]
|
135
|
+
month = MONTH_EN_TO_MM[ month_en ]
|
136
|
+
day = m[:day]
|
137
|
+
start_date = Date.new( year.to_i, month.to_i, day.to_i )
|
138
|
+
## pp start_date
|
139
|
+
|
140
|
+
logger.debug " date entry: #{line}"
|
141
|
+
logger.debug " start_date: #{start_date}, year: #{year}, month_en: #{month_en}, month: #{month} day: #{day} => #{last_link_entry}"
|
142
|
+
|
143
|
+
s = StringScanner.new( line )
|
144
|
+
s.skip( /[ ]*-[ ]*/ ) ## skip leading list
|
145
|
+
s.skip_until( /@/ )
|
146
|
+
|
147
|
+
place = s.scan( /[^;]+/ ) ## get place (everything until ; (separator))
|
148
|
+
place = place.strip
|
149
|
+
logger.debug " place: #{place}, rest: >#{s.rest}<"
|
150
|
+
|
151
|
+
## note: cut of heading 1 (e.g. awesome-events title)
|
152
|
+
more_places = stack[1..-1].reverse.map {|it| it[1] }.join(' › ')
|
153
|
+
place = "#{place} › #{more_places}"
|
154
|
+
logger.debug " place: #{place}"
|
155
|
+
|
156
|
+
s.skip( /;/ )
|
157
|
+
s.skip( /[ ]*/ ) ## skip whitespaces
|
158
|
+
date = s.scan( /[^ ]+/ ) # e.g. everything untils first space (or end-of-line)
|
159
|
+
|
160
|
+
title = last_link_entry
|
161
|
+
|
162
|
+
event = Event.new( title, place, date, start_date )
|
163
|
+
## pp event
|
164
|
+
events << event
|
165
|
+
else
|
166
|
+
logger.debug " *** skip list item line: #{line}"
|
167
|
+
end
|
168
|
+
else
|
169
|
+
logger.debug " *** skip line: #{line}"
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
events
|
174
|
+
end
|
175
|
+
|
176
|
+
end # class EventReader
|
177
|
+
|
178
|
+
end # module EventDb
|
@@ -0,0 +1,40 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module EventDb
|
4
|
+
|
5
|
+
class RubyConf
|
6
|
+
|
7
|
+
def initialize
|
8
|
+
## turn down logger (default :debug?)
|
9
|
+
LogUtils::Logger.root.level = :info
|
10
|
+
|
11
|
+
r = EventDb::EventReader.from_url( "https://github.com/planetruby/awesome-events/raw/master/README.md" )
|
12
|
+
events = r.read
|
13
|
+
|
14
|
+
@db = EventDb::Database.new
|
15
|
+
@db.add( events )
|
16
|
+
end
|
17
|
+
|
18
|
+
def print
|
19
|
+
## get next 17 events
|
20
|
+
up = EventDb::Model::Event.limit( 17 )
|
21
|
+
.order( 'start_date' )
|
22
|
+
.where( 'start_date >= ?', Date.today )
|
23
|
+
## pp up.to_sql
|
24
|
+
## pp up
|
25
|
+
|
26
|
+
puts ''
|
27
|
+
puts ''
|
28
|
+
puts "Upcoming Ruby Conferences:"
|
29
|
+
puts ''
|
30
|
+
up.each do |e|
|
31
|
+
puts " #{e.date} - #{e.title} @ #{e.place}"
|
32
|
+
end
|
33
|
+
puts ''
|
34
|
+
puts " More @ github.com/planetruby/awesome-events"
|
35
|
+
puts ''
|
36
|
+
end
|
37
|
+
|
38
|
+
end # class RubyConf
|
39
|
+
|
40
|
+
end # module EventDb
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module EventDb
|
4
|
+
|
5
|
+
class CreateDb
|
6
|
+
|
7
|
+
def up
|
8
|
+
ActiveRecord::Schema.define do
|
9
|
+
|
10
|
+
create_table :events do |t|
|
11
|
+
t.string :title, null: false
|
12
|
+
t.string :place, null: false
|
13
|
+
t.string :date, null: false # note: full date range (start to end) for now as *string*
|
14
|
+
t.date :start_date, null: false ## use (rename) to start_at - why? why not?
|
15
|
+
|
16
|
+
t.timestamps
|
17
|
+
end
|
18
|
+
|
19
|
+
end # Schema.define
|
20
|
+
end # method up
|
21
|
+
|
22
|
+
end # class CreateDb
|
23
|
+
|
24
|
+
end # module EventDb
|
data/lib/eventdb/version.rb
CHANGED
data/lib/eventdb.rb
CHANGED
@@ -1,10 +1,33 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
|
+
# stdlibs
|
4
|
+
require 'pp'
|
5
|
+
require 'date'
|
6
|
+
require 'strscan' ## StringScanner lib
|
7
|
+
require 'erb'
|
8
|
+
|
9
|
+
# 3rd party libs (gems)
|
10
|
+
require 'props'
|
11
|
+
require 'logutils'
|
12
|
+
require 'textutils'
|
13
|
+
require 'props/activerecord'
|
14
|
+
require 'logutils/activerecord'
|
15
|
+
require 'fetcher'
|
3
16
|
|
4
17
|
# our own code
|
5
18
|
|
6
19
|
require 'eventdb/version' ## let version always go first
|
7
20
|
|
21
|
+
require 'eventdb/schema'
|
22
|
+
require 'eventdb/reader'
|
23
|
+
require 'eventdb/calendar'
|
24
|
+
|
25
|
+
require 'eventdb/models'
|
26
|
+
require 'eventdb/database'
|
27
|
+
|
28
|
+
require 'eventdb/rubyconf'
|
29
|
+
|
30
|
+
|
8
31
|
|
9
32
|
|
10
33
|
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Ruby Conference Calendar
|
2
|
+
|
3
|
+
NOTE: This page gets auto-generated from the [awesome-events](README.md) page @ Planet Ruby.
|
4
|
+
(Last update on <%= Date.today %>.) Do NOT edit this page, please update or edit conferences, camps, meetups etc.
|
5
|
+
on the [awesome-events](README.md) page. Anything missing? Contributions welcome. Thanks!
|
6
|
+
|
7
|
+
|
8
|
+
[2016](#2016) • [2015](#2015) • [2014](#2014) • [2013](#2013)
|
9
|
+
|
10
|
+
<% events.each do |ev,evd| %>
|
11
|
+
<% if evd.new_year? %>
|
12
|
+
|
13
|
+
## <%= ev.start_date.year %>
|
14
|
+
|
15
|
+
<% end %>
|
16
|
+
<% if evd.new_month? %>
|
17
|
+
|
18
|
+
**<%= Date::MONTHNAMES[ev.start_date.month] %>**
|
19
|
+
|
20
|
+
<% end %>
|
21
|
+
|
22
|
+
<%= ev.date %> • **<%= ev.title %>** @ <%= ev.place %>
|
23
|
+
|
24
|
+
<% end %>
|