diff --git a/Gemfile b/Gemfile index 034ba3f..7328790 100644 --- a/Gemfile +++ b/Gemfile @@ -2,12 +2,12 @@ source 'https://rubygems.org' ruby '2.0.0' -gem 'activesupport' gem 'chronic' gem 'haml' gem 'minitest' gem 'newrelic_rpm' gem 'pry' +gem 'rake' gem 'sass' gem 'sinatra' gem 'sinatra-contrib' diff --git a/Gemfile.lock b/Gemfile.lock index 33fc7ee..3190211 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,68 +1,85 @@ GEM remote: https://rubygems.org/ specs: - activesupport (3.2.14) - i18n (~> 0.6, >= 0.6.4) - multi_json (~> 1.0) - backports (3.3.3) - chronic (0.9.1) - coderay (1.0.9) + addressable (2.3.5) + atomic (1.1.14) + backports (3.3.5) + buftok (0.2.0) + chronic (0.10.2) + coderay (1.1.0) daemons (1.1.9) + descendants_tracker (0.0.3) + equalizer (0.0.9) eventmachine (1.0.3) - faraday (0.8.7) - multipart-post (~> 1.1) - haml (4.0.3) + faraday (0.8.8) + multipart-post (~> 1.2.0) + haml (4.0.4) tilt - i18n (0.6.4) - method_source (0.8.1) - minitest (5.0.6) - multi_json (1.7.7) + http (0.5.0) + http_parser.rb + http_parser.rb (0.6.0) + json (1.8.1) + memoizable (0.4.0) + thread_safe (~> 0.1.3) + method_source (0.8.2) + minitest (5.2.0) + multi_json (1.8.2) multipart-post (1.2.0) - newrelic_rpm (3.6.0.78) - pry (0.9.12.2) - coderay (~> 1.0.5) + newrelic_rpm (3.7.1.180) + pry (0.9.12.4) + coderay (~> 1.0) method_source (~> 0.8) slop (~> 3.4) rack (1.5.2) - rack-protection (1.5.0) + rack-protection (1.5.1) rack rack-test (0.6.2) rack (>= 1.0) - sass (3.2.9) + rake (10.1.1) + sass (3.2.13) simple_oauth (0.2.0) - sinatra (1.4.3) + sinatra (1.4.4) rack (~> 1.4) rack-protection (~> 1.4) tilt (~> 1.3, >= 1.3.4) - sinatra-contrib (1.4.0) + sinatra-contrib (1.4.2) backports (>= 2.0) - eventmachine + multi_json rack-protection rack-test - sinatra (~> 1.4.2) + sinatra (~> 1.4.0) tilt (~> 1.3) - slop (3.4.5) - thin (1.5.1) + slop (3.4.7) + thin (1.6.1) daemons (>= 1.0.9) - eventmachine (>= 0.12.6) + eventmachine (>= 1.0.0) rack (>= 1.0.0) + thread_safe (0.1.3) + atomic tilt (1.4.1) - timecop (0.6.2.2) - twitter (4.8.1) - faraday (~> 0.8, < 0.10) - multi_json (~> 1.0) - simple_oauth (~> 0.2) + timecop (0.7.0) + twitter (5.4.1) + addressable (~> 2.3) + buftok (~> 0.2.0) + descendants_tracker (~> 0.0.3) + equalizer (~> 0.0.9) + faraday (>= 0.8, < 0.10) + http (~> 0.5.0) + http_parser.rb (~> 0.6.0) + json (~> 1.8) + memoizable (~> 0.4.0) + simple_oauth (~> 0.2.0) PLATFORMS ruby DEPENDENCIES - activesupport chronic haml minitest newrelic_rpm pry + rake sass sinatra sinatra-contrib diff --git a/README.md b/README.md index d984e75..53d049a 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ TWITTER_OAUTH_TOKEN TWITTER_OAUTH_TOKEN_SECRET ``` -(you can get these from [@bostonaholic](https://twitter.com/bostonaholic)) +Ask [@bostonaholic](https://twitter.com/bostonaholic) for these if you'll be needing them. ## Development @@ -21,4 +21,4 @@ If you're using `foreman` to start the server, you can put the environment varia ### Run the Tests -`$ ruby test/*.rb` +`$ rake test` diff --git a/Rakefile b/Rakefile new file mode 100644 index 0000000..9e5874b --- /dev/null +++ b/Rakefile @@ -0,0 +1,5 @@ +task :default => [:test] + +task :test do + ruby "-Ilib test/*.rb --pride" +end diff --git a/data/meetings.yml b/data/meetings.yml new file mode 100644 index 0000000..12752c2 --- /dev/null +++ b/data/meetings.yml @@ -0,0 +1,29 @@ +01/15/14: + +TBD: + speakers: + - name: John Andrews + link: https://twitter.com/xandrews + talk: Friend + + - name: Matthew Boston + link: http://www.matthewboston.com + talk: Building a Scrabble Solver + + - name: Joshua Eckroth + link: http://www.cse.ohio-state.edu/~eckroth/ + talk: Loom + + - name: Matthew Boston + link: http://www.matthewboston.com + talk: 'Workshop: Building a Noir web app' + + - name: Matthew Boston + link: http://www.matthewboston.com + talk: Bringing Clojure into Your Existing Java App + + fotm: + - talk: into + - talk: iterate + - talk: 'merge-with' + - talk: defrecord diff --git a/meeting_archives.yml b/data/meetings_2012.yml similarity index 100% rename from meeting_archives.yml rename to data/meetings_2012.yml diff --git a/meetings.yml b/data/meetings_2013.yml similarity index 70% rename from meetings.yml rename to data/meetings_2013.yml index 3211f6d..6301e82 100644 --- a/meetings.yml +++ b/data/meetings_2013.yml @@ -88,35 +88,3 @@ talk: zipmap 12/11/13: - -TBD: - speakers: - - name: John Andrews - link: https://twitter.com/xandrews - talk: Friend - - - name: Matthew Boston - link: http://www.matthewboston.com - talk: Building a Scrabble Solver - - - name: Joshua Eckroth - link: http://www.cse.ohio-state.edu/~eckroth/ - talk: Loom - - - name: Matthew Boston - link: http://www.matthewboston.com - talk: 'Workshop: Building a Noir web app' - - - name: Matthew Boston - link: http://www.matthewboston.com - talk: 'Testing in Clojure: core.test vs. speclj vs. Midje' - - - name: Matthew Boston - link: http://www.matthewboston.com - talk: Bringing Clojure into Your Existing Java App - - fotm: - - talk: into - - talk: iterate - - talk: merge-with - - talk: defrecord diff --git a/lib/config.rb b/lib/config.rb index 953152f..71be3e5 100644 --- a/lib/config.rb +++ b/lib/config.rb @@ -3,7 +3,7 @@ set :sass, { :style => :compact } end -Twitter.configure do |config| +twitter_client = Twitter::REST::Client.new do |config| config.consumer_key = ENV['TWITTER_CONSUMER_KEY'] config.consumer_secret = ENV['TWITTER_CONSUMER_SECRET'] config.oauth_token = ENV['TWITTER_OAUTH_TOKEN'] diff --git a/lib/meeting.rb b/lib/meeting.rb index 6bc0e0d..edfa346 100644 --- a/lib/meeting.rb +++ b/lib/meeting.rb @@ -1,24 +1,19 @@ -require 'yaml' +require 'chronic' class Meeting - attr_accessor :date, :speakers, :fotm + attr_reader :date, :speakers, :fotm - def initialize(date = Time.now.beginning_of_day) - @date = date - - next_meeting_talks = self.class.info[date.strftime("%D")] - - @speakers = next_meeting_talks['speakers'] || [] rescue [] - @fotm = next_meeting_talks['fotm'] || [] rescue [] + def initialize(date, info={}) + @date = Chronic.parse("#{date} at 6:00PM") + @speakers = info.fetch("speakers") rescue [] + @fotm = info.fetch("fotm") rescue [] end - def self.info - YAML::load(File.open('meetings.yml')) + def no_speakers? + @speakers.nil? or @speakers.empty? end - def self.dates - info.keys.grep(/(\d+)\/(\d+)\/(\d+)/) do |m| - Date.new(2000 + $3.to_i, $1.to_i, $2.to_i) - end + def no_fotm? + @fotm.nil? or @fotm.empty? end end diff --git a/lib/meeting_date_calculator.rb b/lib/meeting_date_calculator.rb new file mode 100644 index 0000000..bc06094 --- /dev/null +++ b/lib/meeting_date_calculator.rb @@ -0,0 +1,32 @@ +require 'chronic' + +class MeetingDateCalculator + WEDNESDAY = 3 + + def self.next + next_meeting_date = next_first_wednesday + Time.new next_meeting_date.year, next_meeting_date.month, next_meeting_date.day + end + + private + + def self.next_first_wednesday + today = Chronic.parse('today') + next_wednesday = Chronic.parse('next wednesday') + if within_first_week? today and wednesday? today + today + elsif within_first_week? next_wednesday + next_wednesday + else + Chronic.parse('first wednesday next month') + end + end + + def self.within_first_week?(date) + date.day <= 7 + end + + def self.wednesday?(date) + WEDNESDAY == date.wday + end +end diff --git a/lib/meeting_dates.rb b/lib/meeting_dates.rb deleted file mode 100644 index d7390af..0000000 --- a/lib/meeting_dates.rb +++ /dev/null @@ -1,24 +0,0 @@ -require 'active_support/all' -require 'meeting' -require 'chronic' - -class MeetingDates - SIX_OCLOCK = 18.hours - WEDNESDAY = 3 - - def self.next - now = Time.now - if self.within_first_week(now) - if now.wday != WEDNESDAY - next_meeting_day = Chronic.parse('next wednesday') - end - else - next_meeting_day = Chronic.parse('first wednesday next month') - end - Meeting.new((next_meeting_day || now).beginning_of_day + SIX_OCLOCK) - end - - def self.within_first_week(d) - d.day <= 7 - end -end diff --git a/lib/meeting_info_finder.rb b/lib/meeting_info_finder.rb new file mode 100644 index 0000000..10bd231 --- /dev/null +++ b/lib/meeting_info_finder.rb @@ -0,0 +1,17 @@ +require 'yaml' +require 'meeting' + +class MeetingInfoFinder + attr_reader :meetings + + def initialize(filename) + yaml = YAML.load_file(filename) + @meetings = yaml.reject{|k| k == "TBD"}.inject([]) do |meetings, (date, info)| + meetings << Meeting.new(date, info) + end + end + + def find(date) + @meetings.bsearch {|meeting| meeting.date >= date} + end +end diff --git a/script/test b/script/test index 90a6105..9857b2d 100755 --- a/script/test +++ b/script/test @@ -1 +1 @@ -ruby ./test/* --pride +ruby -Ilib ./test/* --pride diff --git a/server.rb b/server.rb index b1f8448..d6782f5 100644 --- a/server.rb +++ b/server.rb @@ -2,16 +2,18 @@ require 'sinatra/namespace' require 'haml' require 'sass' -require 'meeting_dates' require 'config' require 'helpers' + require 'twitter' +require 'meeting_info_finder' +require 'meeting_date_calculator' + ## VIEWS get '/' do - # @next_meeting = MeetingDates.next - @next_meeting = Meeting.new(Date.new(2013,12,11) + 18.hours) - + @next_meeting = MeetingInfoFinder.new('./data/meetings.yml') + .find(MeetingDateCalculator.next) @mailing_list = "http://groups.google.com/group/columbusclojure" @twitter_url = "https://twitter.com/columbusclojure" @@ -20,7 +22,7 @@ namespace '/api' do get '/tweets', :provides => 'json' do - Twitter.user_timeline("columbusclojure").to_json + twitter_client.user_timeline("columbusclojure").to_json end end diff --git a/test/test_meeting_date_calculator.rb b/test/test_meeting_date_calculator.rb new file mode 100644 index 0000000..a401842 --- /dev/null +++ b/test/test_meeting_date_calculator.rb @@ -0,0 +1,41 @@ +require 'minitest/autorun' +require 'meeting_date_calculator' +require 'timecop' + +class TestMeetings < Minitest::Test + def test_next_meeting_is_wednesday + next_meeting = MeetingDateCalculator.next + assert_equal MeetingDateCalculator::WEDNESDAY, next_meeting.wday + end + + def test_next_meeting_is_next_month + Timecop.freeze(Time.new(2013, 8, 10)) do + next_meeting = MeetingDateCalculator.next + assert_equal 9, next_meeting.month + end + end + + def test_next_meeting_is_this_month + Timecop.freeze(Time.new(2013, 8, 1)) do + next_meeting = MeetingDateCalculator.next + assert_equal 8, next_meeting.month + assert_equal 7, next_meeting.day + end + end + + def test_next_meeting_is_today + Timecop.freeze(Time.new(2013, 8, 7)) do + next_meeting = MeetingDateCalculator.next + assert_equal 8, next_meeting.month + assert_equal 7, next_meeting.day + end + end + + def test_next_meeting_in_first_week_not_today + Timecop.freeze(Time.new(2013, 9, 7)) do + next_meeting = MeetingDateCalculator.next + assert_equal 10, next_meeting.month + assert_equal 2, next_meeting.day + end + end +end diff --git a/test/test_meeting_dates.rb b/test/test_meeting_dates.rb deleted file mode 100644 index 82e45a0..0000000 --- a/test/test_meeting_dates.rb +++ /dev/null @@ -1,44 +0,0 @@ -APP_LIB = File.expand_path(File.dirname(__FILE__) + '/../lib') -$LOAD_PATH.unshift(APP_LIB).uniq! - -require 'minitest/autorun' -require 'meeting_dates' -require 'timecop' - -class TestMeetingDates < Minitest::Test - def setup - @next_meeting_date = MeetingDates.next.date - end - - def test_next_meeting_is_wednesday - assert_equal MeetingDates::WEDNESDAY, @next_meeting_date.wday - end - - def test_next_meeting_is_six_oclock - assert_equal 18, @next_meeting_date.hour - assert_equal 0, @next_meeting_date.min - end - - def test_next_meeting_is_today - Timecop.freeze(Time.new(2013, 8, 7)) do - assert_equal 8, MeetingDates.next.date.month - assert_equal 7, MeetingDates.next.date.day - end - Timecop.return - end - - def test_next_meeting_is_within_the_first_week - Timecop.freeze(Time.new(2013, 8, 1)) do - assert_equal 8, MeetingDates.next.date.month - assert_equal 7, MeetingDates.next.date.day - end - Timecop.return - end - - def test_next_meeting_is_next_month - Timecop.freeze(Time.new(2013, 8, 10)) do - assert_equal 9, MeetingDates.next.date.month - end - Timecop.return - end -end diff --git a/views/speakers.haml b/views/speakers.haml index 9b6895c..8da4894 100644 --- a/views/speakers.haml +++ b/views/speakers.haml @@ -4,7 +4,7 @@ %section %ul - - if next_meeting.speakers.empty? && next_meeting.fotm.empty? + - if next_meeting.no_speakers? && next_meeting.no_fotm? = haml :call_for_speakers, :locals => {:mailing_list => mailing_list} - else = haml :speakers_list, :locals => {:speakers => next_meeting.speakers, :fotm => next_meeting.fotm}