hanreki 1.2.0 → 2.0.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: a867b87334a1a1be5954d74b9059cd465651f1a5
4
- data.tar.gz: 2961b20754273404809b8c9f8f1d2d789edfb879
3
+ metadata.gz: 5063f6f82205ddf8c8ba3393966f4e743e95c834
4
+ data.tar.gz: '06729fefac6d2ff13f70e81f4dede11d8940159b'
5
5
  SHA512:
6
- metadata.gz: a04b6f1fe15222d4de38772121cfe025a0df77008a58a726e09cec72bf0f2b4fa3650ac7ec4e4ef1f4ef1eca17d850bd8889369c920bab1dd332114a15d44709
7
- data.tar.gz: 8579bada5beea05a9b7cf71eea9e2e423a456425430e28034dc77e2c19e3a0f36cb2fba1db85351ac6b097a9bca8ec536c53036b288d96e2f466eb3d6ffed9e7
6
+ metadata.gz: ef56f66855bc14838ff616b045f9452def5b53fc7591f602ab9aec1a1bd16b32fe6cd06fcbdcbd4230bc642362bb4a0150a0603106deb5fb4ced4f60abb5757a
7
+ data.tar.gz: 979e7634f02f3b456c83e63d4f3b49cda6be01c9800f50aeb17aa750ff849e5b81a8a7620d4c52c03037d91aca304147f51907ca6742d4965f7fd0e57bcc7d9e
data/hanreki.gemspec CHANGED
@@ -24,7 +24,7 @@ Gem::Specification.new do |spec|
24
24
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
25
  spec.require_paths = ['lib']
26
26
 
27
- spec.required_ruby_version = '>= 2.1.0'
27
+ spec.required_ruby_version = '>= 2.2.0'
28
28
 
29
29
  spec.add_dependency 'thor', '~> 0.19'
30
30
  spec.add_dependency 'icalendar', '~> 2.3'
data/lib/hanreki/cli.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require 'date'
2
2
  require 'thor'
3
+ require 'hanreki/exceptions'
3
4
  require 'hanreki/schedule'
4
5
  require 'hanreki/time_util'
5
6
  require 'hanreki/version'
@@ -31,8 +32,7 @@ module Hanreki
31
32
 
32
33
  desc 'sync', 'Sync iCal, JSON, and JSONP'
33
34
  def sync
34
- schedule = Schedule.new
35
- schedule.load_master_files
35
+ schedule = load_schedule
36
36
  schedule.out_ical
37
37
  schedule.out_json
38
38
  schedule.out_jsonp
@@ -41,11 +41,7 @@ module Hanreki
41
41
  desc 'validate', 'Validate master files'
42
42
  def validate
43
43
  schedule = Schedule.new
44
- begin
45
- schedule.load_master_files
46
- rescue => e
47
- raise "validation error: #{e}"
48
- end
44
+ schedule = load_schedule
49
45
  end
50
46
 
51
47
  desc 'version', 'Show the version information'
@@ -56,6 +52,24 @@ module Hanreki
56
52
 
57
53
  private
58
54
 
55
+ def load_schedule()
56
+ schedule = Schedule.new
57
+ begin
58
+ schedule.load_master_files
59
+ rescue ValidationError => e
60
+ message = 'validation error'
61
+ if e.event
62
+ message += " at line #{e.event.line_number}" if e.event.line_number
63
+ message += " in #{e.event.filename}" if e.event.filename
64
+ message += "\n#{e.event.row.to_s.strip}" if e.event.row
65
+ end
66
+ message += "\n#{e}"
67
+ puts message
68
+ exit 1
69
+ end
70
+ schedule
71
+ end
72
+
59
73
  # Parse a string (YYYYMM) in options[:date] and returns [YYYY, MM]
60
74
  def parse_month_in_options(options, default = nil)
61
75
  date = options[:date]
data/lib/hanreki/event.rb CHANGED
@@ -1,10 +1,12 @@
1
1
  require 'icalendar'
2
+ require 'hanreki/exceptions'
2
3
  require 'hanreki/time_util'
3
4
 
4
5
  # Event of CAMPHOR- Schedule
5
6
  class Event
6
7
  using ExtendTime
7
8
  DOWS = %w(日 月 火 水 木 金 土)
9
+ attr_accessor :filename, :line_number, :row
8
10
  attr_accessor :start, :end
9
11
  attr_accessor :public_summary, :private_summary
10
12
  attr_accessor :url
@@ -23,29 +25,34 @@ class Event
23
25
  # month: String (e.g. 201510)
24
26
  # line: CSV::Row
25
27
  # (eg. [01, 水, 15:00, 20:00, "HOUSE 開館", "HOUSE 当番 @ivstivs", https://camph.net])
26
- def self.from_master(month, line)
27
- event = Event.new({})
28
+ def self.from_master(filename, line_number, month, line)
29
+ event = Event.new({
30
+ row: line,
31
+ filename: filename,
32
+ line_number: line_number,
33
+ })
28
34
  first_day = Date.parse("#{month}01")
35
+ raise ValidationError.new(event), 'invalid number of columns' unless line.length == 7
29
36
  day, dow, hour_start, hour_end, public_summary, private_summary, url = line.fields.map { |c| c.to_s.strip }
30
37
  # Zero-fill (eg. 1 -> 01, 02 -> 02)
31
38
  day = day.rjust(2, "0")
32
- raise ArgumentError, 'invalid day' unless day.length == 2
33
- raise ArgumentError, 'invalid day' unless (first_day...first_day.next_month).include?(Date.parse("#{month}#{day}"))
39
+ raise ValidationError.new(event), 'invalid day' unless day.length == 2
40
+ raise ValidationError.new(event), 'invalid day' unless (first_day...first_day.next_month).include?(Date.parse("#{month}#{day}"))
34
41
  event.start = Time.parse("#{month}#{day} #{hour_start} +09:00").getlocal("+09:00")
35
42
  event.end = Time.parse("#{month}#{day} #{hour_end} +09:00").getlocal("+09:00")
36
43
  event.public_summary = public_summary unless public_summary.empty?
37
44
  event.private_summary = private_summary unless private_summary.empty?
38
45
  event.url = url unless url.empty?
39
46
  # 曜日はインスタンス変数に保持しないのでここでチェックする
40
- raise ArgumentError, 'invalid day of the week' unless DOWS.include? dow
41
- raise ArgumentError, 'invalid day of the week' unless DOWS[event.start.wday] == dow
47
+ raise ValidationError.new(event), 'invalid day of the week' unless DOWS.include? dow
48
+ raise ValidationError.new(event), 'invalid day of the week' unless DOWS[event.start.wday] == dow
42
49
  event.validate
43
50
  event
44
51
  end
45
52
 
46
53
  def to_h(type, time_type = :time)
47
- fail ArgumentError, 'Invalid type' unless [:public, :private].include?(type)
48
- fail ArgumentError, 'Invalid time_type' unless [:time, :string].include?(time_type)
54
+ fail ValidationError.new(self), 'invalid type' unless [:public, :private].include?(type)
55
+ fail ValidationError.new(self), 'invalid time_type' unless [:time, :string].include?(time_type)
49
56
  hash = {
50
57
  start: @start,
51
58
  end: @end,
@@ -82,35 +89,35 @@ class Event
82
89
  # イベントのバリデーションを行う
83
90
  # バリデーションに成功した場合は true を返し, 失敗した場合は例外を送出する
84
91
  def validate
85
- raise ArgumentError, 'invalid start & end' if @start > @end
92
+ raise ValidationError.new(self), 'invalid start & end' if @start > @end
86
93
 
87
94
  if @public_summary.nil? and @private_summary.nil?
88
- raise ArgumentError, 'both summaries are not set'
95
+ raise ValidationError.new(self), 'both summaries are not set'
89
96
  end
90
97
 
91
98
  if @public_summary == 'Open'
92
99
  if @start == @end
93
- raise ArgumentError, '"open" event should have duration'
100
+ raise ValidationError.new(self), '"open" event should have duration'
94
101
  end
95
102
  end
96
103
 
97
104
  if @private_summary == 'Closed'
98
105
  if not @public_summary.nil?
99
- raise ArgumentError, 'invalid public summary for a closed event'
106
+ raise ValidationError.new(self), 'invalid public summary for a closed event'
100
107
  end
101
108
 
102
109
  if not @start.is_midnight_in_jst
103
- raise ArgumentError, 'start must be 0:00 for a closed event'
110
+ raise ValidationError.new(self), 'start must be 0:00 for a closed event'
104
111
  end
105
112
 
106
113
  if not @end.is_midnight_in_jst
107
- raise ArgumentError, 'end must be 0:00 for a closed event'
114
+ raise ValidationError.new(self), 'end must be 0:00 for a closed event'
108
115
  end
109
116
  end
110
117
 
111
118
  unless @url.nil?
112
119
  unless @url.start_with?('http://') or @url.start_with?('https://')
113
- raise ArgumentError, 'invalid url scheme'
120
+ raise ValidationError.new(self), 'invalid url scheme'
114
121
  end
115
122
  end
116
123
 
@@ -0,0 +1,8 @@
1
+ class ValidationError < StandardError
2
+ attr_reader :event
3
+
4
+ def initialize(event)
5
+ super
6
+ @event = event
7
+ end
8
+ end
@@ -19,8 +19,8 @@ class ICalendar
19
19
  end
20
20
 
21
21
  def set_event(event, type)
22
- fail ArgumentError, 'Invalid date' unless event.start && event.end
23
- fail ArgumentError, 'Invalid type' unless [:public, :private].include?(type)
22
+ fail ValidationError.new(event), 'invalid date' unless event.start && event.end
23
+ fail ValidationError.new(event), 'invalid type' unless [:public, :private].include?(type)
24
24
  @calendar.event do |e|
25
25
  e.dtstart = event.start
26
26
  e.dtend = event.end
@@ -35,7 +35,7 @@ class Schedule
35
35
  @events = Dir.glob('master/*.csv').flat_map do |f|
36
36
  month = f.match(/master\/(\d+).csv/)[1]
37
37
  CSV.open(f, headers: true) do |csv|
38
- csv.map { |line| Event.from_master(month, line) }
38
+ csv.map { |row| Event.from_master(f, $., month, row) }
39
39
  end
40
40
  end
41
41
  end
@@ -1,3 +1,3 @@
1
1
  module Hanreki
2
- VERSION = '1.2.0'
2
+ VERSION = '2.0.0'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hanreki
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 2.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - CAMPHOR-
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2017-05-03 00:00:00.000000000 Z
11
+ date: 2017-08-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -110,6 +110,7 @@ files:
110
110
  - lib/hanreki.rb
111
111
  - lib/hanreki/cli.rb
112
112
  - lib/hanreki/event.rb
113
+ - lib/hanreki/exceptions.rb
113
114
  - lib/hanreki/i_calendar.rb
114
115
  - lib/hanreki/schedule.rb
115
116
  - lib/hanreki/schema.json
@@ -127,7 +128,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
127
128
  requirements:
128
129
  - - ">="
129
130
  - !ruby/object:Gem::Version
130
- version: 2.1.0
131
+ version: 2.2.0
131
132
  required_rubygems_version: !ruby/object:Gem::Requirement
132
133
  requirements:
133
134
  - - ">="