hanreki 1.2.0 → 2.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.
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
  - - ">="