2 SafeYAML::OPTIONS[:default_mode] = :safe
5 MEMBERS_ROOT = 'Membres'
6 MEMBER_FIELDS = [:name, :address, :email, :membership_fee_paid_on]
7 MEMBER_MANDATORY_FIELDS = [:name, :email]
9 class Member < Struct.new(*MEMBER_FIELDS)
12 Dir.glob("#{MEMBERS_ROOT}/*.mdwn").sort.collect do |file|
13 member_id = File.basename(file).gsub(/\.mdwn$/, '')
18 def filename_for_id(member_id)
19 "Membres/%06d.mdwn" % member_id
22 def read_from_git(ref, file)
23 IO.popen(['git', 'show', "#{ref}:#{file}"]) do |f|
24 member_id = File.basename(file).gsub(/\.mdwn$/, '')
25 Member.new(member_id, f.read)
30 attr_reader :member_id
32 def initialize(member_id, page_content=nil)
33 unless member_id =~ /\A\d{6}\z/
34 raise ArgumentError.new('bad member id format')
36 @member_id = member_id
38 page_content = File.open(Member.filename_for_id(member_id)).read
40 unless page_content.start_with?("---\n")
41 raise ArgumentError.new('content is not a proper YAML document')
43 data = YAML.load(page_content)
44 MEMBER_FIELDS.each do |field|
45 self[field] = data[field.to_s]
47 # Immutability for the win
48 MEMBER_FIELDS.each do |field|
49 instance_eval{ undef :"#{field}=" }
51 MEMBER_MANDATORY_FIELDS.each do |sym|
52 raise ArgumentError.new('missing mandatory fields') unless self[sym]
54 if membership_fee_paid_on && !membership_fee_paid_on.is_a?(Date)
55 raise ArgumentError.new('membership_fee_paid_on is not a date')
61 last_year = Time.new(now.year - 1, now.month, now.day).to_date
62 membership_fee_paid_on && last_year < membership_fee_paid_on