eventdb 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2d91e1c94dd25984b6b985b0106bfe94db09db38
4
- data.tar.gz: e8bc94ec6d9527974ace944adf3bc12f0aeaf16d
3
+ metadata.gz: 64679b23d00fead03540ef38cdabb5c89a5a21e2
4
+ data.tar.gz: 6ad469e6a30aadc53fc0fe9588523a5b3ee76a91
5
5
  SHA512:
6
- metadata.gz: 9cec63f13c4c8f7fc3d7592ea0f688d0e0d3c689270ed78661d661285fee8446331d62b4b1557fa5e0de35275d7525c9074e67420793f00cc42e2e05621dbfd5
7
- data.tar.gz: 3470dfeda3f8aab58873fc339aec102e7acf9f2d5df519753b6f77049d74ac5aba1f7987b7ad2d3121675e1d9e4a175ab406a38dedd81cf85d4f0aea965b58dd
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
- $ rubyconf
22
-
23
- to list the upcoming Ruby conferences from around the world.
24
-
25
-
26
-
27
- ## Usage
28
-
29
- to be done
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
@@ -27,8 +27,6 @@ Hoe.spec 'eventdb' do
27
27
  ['logutils-activerecord', '>= 0.2.1'],
28
28
 
29
29
  ## 3rd party
30
- ['gli', '>= 2.13.1'],
31
- ['rubyzip'], ## todo: pull in via textutils ??
32
30
  ['fetcher', '>= 0.4.5'],
33
31
  ['activerecord'], # NB: will include activesupport,etc.
34
32
  ['sqlite3']
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,12 @@
1
+ # encoding: utf-8
2
+
3
+ module EventDb
4
+ module Model
5
+
6
+ class Event < ActiveRecord::Base
7
+
8
+ end # class Event
9
+
10
+ end # module Model
11
+ end # module EventDb
12
+
@@ -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
@@ -3,8 +3,8 @@
3
3
  module EventDb
4
4
 
5
5
  MAJOR = 0 ## todo: namespace inside version or something - why? why not??
6
- MINOR = 0
7
- PATCH = 1
6
+ MINOR = 1
7
+ PATCH = 0
8
8
  VERSION = [MAJOR,MINOR,PATCH].join('.')
9
9
 
10
10
  def self.version
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 %>