recras 0.1.0 → 0.1.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -2
- data/lib/recras.rb +21 -10
- data/lib/recras/client.rb +5 -4
- data/lib/recras/combination.rb +48 -30
- data/lib/recras/combination_item.rb +14 -1
- data/lib/recras/contact_form.rb +1 -0
- data/lib/recras/contact_form_field.rb +1 -0
- data/lib/recras/itinerary.rb +70 -0
- data/lib/recras/person.rb +1 -0
- data/lib/recras/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7064f4a5e12db70ed3a1ae6a97743b1109b8a7e9
|
4
|
+
data.tar.gz: e13b4e94d5b80eb0c7e46f59e9cc06d815b09ffa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1bff5adb284a437064267f56e84b4cc44a0f4db43e5bf6ac28b670530561c98e10049505dc345752d00308450e89d9ddcd3f059d5d36da1234655a21454016e8
|
7
|
+
data.tar.gz: da3020ed4620cd4dbe5aead2c112ae7bc1d8c854a995faee1874c5e8cec0f1ac0f756acc8545bb5bc20920aa7790371ae2160abec69adc59a69601ae15c70b29
|
data/README.md
CHANGED
@@ -48,6 +48,7 @@ A combination has a number of fields. __Not all the fields present in the native
|
|
48
48
|
- allowed_to_pay_later
|
49
49
|
- combination_items
|
50
50
|
- contact_form_id
|
51
|
+
- itineraries (returns a list of `<Recras::Itinerary>` objects)
|
51
52
|
- client (returns the client object that made the request)
|
52
53
|
|
53
54
|
|
@@ -56,7 +57,15 @@ A combination has a number of fields. __Not all the fields present in the native
|
|
56
57
|
@recras_client.combinations # => returns an array of <Recras::Combination> objects
|
57
58
|
|
58
59
|
# Find a single combination:
|
59
|
-
@recras_client.combination(4) => <Recras::Combination:0x007fc617cd1948 @id=4 ...>
|
60
|
+
@combination = @recras_client.combination(4) => <Recras::Combination:0x007fc617cd1948 @id=4 ...>
|
61
|
+
|
62
|
+
# Show the itineraries
|
63
|
+
for itinerary in @combination.itineraries
|
64
|
+
puts itenerary
|
65
|
+
end
|
66
|
+
# outputs:
|
67
|
+
# Ontvangst met koffie - 10 personen (00:30:00)
|
68
|
+
# Leer boogschieten - 10 personen (02:15:00)
|
60
69
|
```
|
61
70
|
|
62
71
|
### CombinationItem
|
@@ -109,6 +118,19 @@ __Important:__ If you don't supply the `items` argument, you have to enter a `nu
|
|
109
118
|
### ContactForm
|
110
119
|
If you see the checkout page of any of Recras' clients, you'll notice that the consumer has to fill in a couple of fields in the last step before the booking. These fields are specific to the selected Combination (arrangement). To know which fields to show, how to label them and with which identifier to submit them, you use the `@combination.contact_form`. In it are `<Recras::ContactFormField>` objects.
|
111
120
|
|
121
|
+
A ContactFormField has the following attributes:
|
122
|
+
- id
|
123
|
+
- name
|
124
|
+
- contact_form_id
|
125
|
+
- input_type
|
126
|
+
- required
|
127
|
+
- options
|
128
|
+
- special_for_booking (if true, it will be displayed as information on the ticket/booking confirmation)
|
129
|
+
- field_identifier
|
130
|
+
- contact_form (parent object)
|
131
|
+
|
132
|
+
|
133
|
+
|
112
134
|
|
113
135
|
### Make a booking
|
114
136
|
Making a booking is not much different from checking times: you need to know when the consumer wants to book and wich items+quantity. It looks like this:
|
@@ -126,7 +148,8 @@ contact_form_details: {
|
|
126
148
|
"veel_tekst_0"=>""
|
127
149
|
}
|
128
150
|
|
129
|
-
@combination.book(number_of_people: 2, date: "2017-04-14T13:00:00+02:00", contact_form_details: contact_form_details)
|
151
|
+
@combination.book(number_of_people: 2, date: "2017-04-14T13:00:00+02:00", contact_form_details: contact_form_details)
|
152
|
+
# => #<Recras::Booking:0x007f99bab94c30 @id=8994, @status="reservering", @message="Boeking gemaakt", @customer_id=8986>
|
130
153
|
```
|
131
154
|
|
132
155
|
|
data/lib/recras.rb
CHANGED
@@ -14,6 +14,7 @@ require "recras/combination_item"
|
|
14
14
|
require "recras/contact_form"
|
15
15
|
require "recras/contact_form_field"
|
16
16
|
require "recras/booking"
|
17
|
+
require "recras/itinerary"
|
17
18
|
|
18
19
|
module Recras
|
19
20
|
|
@@ -22,9 +23,9 @@ module Recras
|
|
22
23
|
# returns the version number
|
23
24
|
def self.version
|
24
25
|
VERSION
|
25
|
-
end
|
26
|
+
end
|
26
27
|
|
27
|
-
# this method maps the recras API objects to
|
28
|
+
# this method maps the recras API objects to
|
28
29
|
# the names used by this gem
|
29
30
|
def self.object_mappings
|
30
31
|
[["personeel", Person], ["arrangement", Combination], ["contactformulier", ContactForm], ["velden", ContactFormField], ["booking", Booking]]
|
@@ -35,27 +36,35 @@ module Recras
|
|
35
36
|
end
|
36
37
|
|
37
38
|
# initialize a new Person from given JSON.
|
38
|
-
def new_from_json(json)
|
39
|
+
def new_from_json(json)
|
39
40
|
params = {}
|
40
41
|
|
41
42
|
# set each attribute based on the mapping
|
42
|
-
self.attribute_mapping.each do |o,n|
|
43
|
+
self.attribute_mapping.each do |o,n|
|
43
44
|
# if o is a string, parse it
|
44
45
|
if n.is_a?(String)
|
45
46
|
# check if data type is specified (using @@ symbol)
|
46
47
|
if n.include?("@@")
|
47
48
|
if n.split("@@").last.downcase == 'time'
|
48
49
|
data = Time.new(n.split("@@").first)
|
49
|
-
|
50
|
-
|
50
|
+
elsif n.split("@@").last.downcase == 'float'
|
51
|
+
data = n.split("@@").first.to_f
|
51
52
|
else
|
52
53
|
data = n.split("@@").first
|
53
54
|
end
|
54
55
|
params[n.split("@@").first] = data
|
55
56
|
else
|
57
|
+
# puts "parsing value: #{n} => #{json[o]}"
|
56
58
|
params[n] = json[o.to_s]
|
59
|
+
# puts "parsed value (#{params[n]})"
|
57
60
|
end
|
58
|
-
|
61
|
+
|
62
|
+
|
63
|
+
# assign boolean value
|
64
|
+
elsif [FalseClass, TrueClass].include?(n.class)
|
65
|
+
# puts "Parsing boolean value: #{n} = #{json[o]}"
|
66
|
+
params[n] = json[o]
|
67
|
+
# puts "#{n} => #{o}"
|
59
68
|
# else, o is a class. Call the 'parse_children' method on it
|
60
69
|
else
|
61
70
|
# puts "n is a #{n.class.name}"
|
@@ -68,7 +77,9 @@ module Recras
|
|
68
77
|
params[n.plural_name] = children
|
69
78
|
end
|
70
79
|
end
|
80
|
+
|
71
81
|
end
|
82
|
+
params['json'] = json
|
72
83
|
self.new(params)
|
73
84
|
end
|
74
85
|
|
@@ -99,7 +110,7 @@ module Recras
|
|
99
110
|
# - an error
|
100
111
|
# - a json object
|
101
112
|
def self.make_request(endpoint, body: {}, http_method: :get, client: nil)
|
102
|
-
url = "#{
|
113
|
+
url = "#{client.host}/api#{Recras::API_VERSION}/#{endpoint}"
|
103
114
|
|
104
115
|
auth = client ? {username: client.username, password: client.password} : nil
|
105
116
|
|
@@ -108,9 +119,9 @@ module Recras
|
|
108
119
|
else
|
109
120
|
response = HTTParty.get(url, basic_auth: auth, body: body)
|
110
121
|
end
|
111
|
-
|
122
|
+
|
112
123
|
json = response.parsed_response
|
113
124
|
return json
|
114
125
|
end
|
115
126
|
|
116
|
-
end
|
127
|
+
end
|
data/lib/recras/client.rb
CHANGED
@@ -3,8 +3,9 @@ module Recras
|
|
3
3
|
class Client
|
4
4
|
# @note The is a required parameter.
|
5
5
|
attr_accessor :username
|
6
|
-
# @return [String] Your
|
6
|
+
# @return [String] Your Recras password
|
7
7
|
attr_accessor :password
|
8
|
+
attr_accessor :host
|
8
9
|
|
9
10
|
|
10
11
|
#
|
@@ -12,10 +13,10 @@ module Recras
|
|
12
13
|
#
|
13
14
|
# @param [Hash] args
|
14
15
|
def initialize(args=nil)
|
15
|
-
required_args = [:username, :password]
|
16
|
+
required_args = [] # [:username, :password]
|
16
17
|
for arg in required_args
|
17
18
|
if args.nil? || args[arg].nil?
|
18
|
-
raise RecrasError.new(self), "Insufficient login credentials. Please provide @username, @password"
|
19
|
+
raise RecrasError.new(self), "Insufficient login credentials. Please provide @username, @password and @host"
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
@@ -66,6 +67,6 @@ module Recras
|
|
66
67
|
end
|
67
68
|
return a
|
68
69
|
end
|
69
|
-
|
70
|
+
|
70
71
|
end
|
71
72
|
end
|
data/lib/recras/combination.rb
CHANGED
@@ -8,14 +8,22 @@ module Recras
|
|
8
8
|
|
9
9
|
attr_accessor :id
|
10
10
|
attr_accessor :name
|
11
|
+
attr_accessor :welcome_location
|
11
12
|
attr_accessor :visible_online
|
13
|
+
attr_accessor :max_number_of_people
|
12
14
|
attr_accessor :number_of_people
|
13
15
|
attr_accessor :allowed_to_pay_later
|
14
16
|
attr_accessor :combination_items
|
17
|
+
attr_accessor :itineraries
|
18
|
+
attr_accessor :description
|
19
|
+
attr_accessor :price_per_person_incl_vat
|
20
|
+
attr_accessor :price_total_incl_vat
|
21
|
+
attr_accessor :seperate_planning
|
15
22
|
attr_accessor :contact_form_id
|
16
23
|
attr_accessor :client
|
17
|
-
|
18
|
-
|
24
|
+
attr_accessor :json
|
25
|
+
|
26
|
+
# Initializer to transform a +Hash+ into an Combination object
|
19
27
|
# @param [Hash] args
|
20
28
|
def initialize(args=nil)
|
21
29
|
required_args = []
|
@@ -31,53 +39,62 @@ module Recras
|
|
31
39
|
end
|
32
40
|
end
|
33
41
|
|
34
|
-
|
35
|
-
def self.find(id)
|
36
|
-
json = Recras.make_request("arrangementen/#{id}")
|
37
|
-
# puts json
|
38
|
-
return Recras.parse_json(json: json, endpoint: "arrangement")
|
39
|
-
end
|
42
|
+
|
40
43
|
|
41
44
|
# returns a Recras::ContactForm
|
42
45
|
def contact_form
|
43
46
|
json = client.make_request("contactformulieren/#{contact_form_id}")
|
44
47
|
cf = Recras.parse_json(json: json, endpoint: "contactformulier", client: client)
|
48
|
+
return cf
|
45
49
|
end
|
46
50
|
|
47
51
|
|
48
52
|
|
49
53
|
# returns a list of available days (in string format) for a given campaign
|
50
|
-
#
|
51
|
-
# If no combination_items are given, assume that you want each item to be booked. In that scenario,
|
54
|
+
# example: combination.available_days(combination_items: [{combination_item_id: 1, number_of_people: 2}])
|
55
|
+
# If no combination_items are given, assume that you want each item to be booked. In that scenario,
|
52
56
|
# also use the 'number_of_people' argument. E.g.: @combination.available_days(number_of_people: 2).
|
53
57
|
def available_days(items: [], number_of_people: nil, from_time: Date.today, until_time: (Time.now + 3600*24*7))
|
54
|
-
|
55
|
-
|
56
|
-
|
58
|
+
if items && items.any?
|
59
|
+
begin
|
60
|
+
puts "starting product_items (#{items})"
|
61
|
+
product_items = convert_items(items, number_of_people)
|
62
|
+
rescue
|
63
|
+
# no items
|
64
|
+
end
|
65
|
+
end
|
66
|
+
if product_items && product_items.any?
|
57
67
|
body_data = {
|
58
68
|
arrangement_id: id,
|
59
69
|
producten: product_items,
|
60
70
|
begin: from_time.strftime("%Y-%m-%d"),
|
61
71
|
eind: until_time.strftime("%Y-%m-%d")
|
62
72
|
}
|
73
|
+
elsif number_of_people
|
74
|
+
body_data = {
|
75
|
+
arrangement_id: id,
|
76
|
+
begin: from_time.strftime("%Y-%m-%d"),
|
77
|
+
eind: until_time.strftime("%Y-%m-%d")
|
78
|
+
}
|
79
|
+
else
|
80
|
+
raise RecrasError.new(self), "Insufficient details provided. Either combination_items or number_of_people are required."
|
81
|
+
end
|
82
|
+
# make request
|
83
|
+
json = client.make_request("onlineboeking/beschikbaredagen", body: body_data.to_json, http_method: :post)
|
63
84
|
|
64
|
-
# make request
|
65
|
-
json = client.make_request("onlineboeking/beschikbaredagen", body: body_data.to_json, http_method: :post)
|
66
85
|
|
67
|
-
|
68
|
-
|
69
|
-
else
|
70
|
-
return json
|
71
|
-
end
|
86
|
+
if json.is_a?(Hash) && json["error"]
|
87
|
+
raise RecrasError.new(self), json["message"]
|
72
88
|
else
|
73
|
-
|
89
|
+
return json
|
74
90
|
end
|
91
|
+
|
75
92
|
end
|
76
93
|
|
77
94
|
|
78
95
|
# returns a list of available days (in string format) for a given campaign
|
79
96
|
# exampel: combination.available_days(combination_items: [{combination_item_id: 1, number_of_people: 2}])
|
80
|
-
# If no combination_items are given, assume that you want each item to be booked. In that scenario,
|
97
|
+
# If no combination_items are given, assume that you want each item to be booked. In that scenario,
|
81
98
|
# also use the 'number_of_people' argument. E.g.: @combination.available_days(number_of_people: 2).
|
82
99
|
def available_times(items: [], number_of_people: nil, date: nil)
|
83
100
|
product_items = convert_items(items, number_of_people)
|
@@ -101,16 +118,17 @@ module Recras
|
|
101
118
|
|
102
119
|
|
103
120
|
# make a reservation for this combination
|
104
|
-
def book(items: [], number_of_people: nil, date: nil, payment_method: "factuur", contact_form_details: {})
|
121
|
+
def book(items: [], number_of_people: nil, date: nil, payment_method: "factuur", status: "reservering", contact_form_details: {})
|
105
122
|
|
106
123
|
product_items = convert_items(items, number_of_people)
|
107
124
|
date = convert_date(date)
|
108
125
|
|
109
126
|
if product_items.any?
|
110
|
-
body_data = {
|
111
|
-
arrangement_id: id,
|
112
|
-
producten: product_items,
|
127
|
+
body_data = {
|
128
|
+
arrangement_id: id,
|
129
|
+
producten: product_items,
|
113
130
|
begin: date,
|
131
|
+
status: status,
|
114
132
|
betaalmethode: payment_method,
|
115
133
|
contactformulier: contact_form_details
|
116
134
|
}
|
@@ -119,7 +137,7 @@ module Recras
|
|
119
137
|
if json.is_a?(Hash) && json["error"]
|
120
138
|
raise RecrasError.new(self), json["error"]["message"]
|
121
139
|
else
|
122
|
-
booking = Recras.parse_json(json: json, endpoint: "booking")
|
140
|
+
booking = Recras.parse_json(json: json, endpoint: "booking")
|
123
141
|
return booking
|
124
142
|
end
|
125
143
|
else
|
@@ -142,7 +160,7 @@ module Recras
|
|
142
160
|
# translates the mapping between the Recras API
|
143
161
|
# and the terms used in this gem
|
144
162
|
def self.attribute_mapping
|
145
|
-
[["id", "id"],["weergavenaam", "name"],["mag_online", "visible_online"],["aantal_personen", "number_of_people"], ["mag_online_geboekt_worden_achteraf_betalen", "allowed_to_pay_later"], ["regels", Recras::CombinationItem], ["onlineboeking_contactformulier_id", "contact_form_id"]]
|
163
|
+
[["id", "id"],["weergavenaam", "name"],["mag_online", "visible_online"],["aantal_personen", "number_of_people"], ["mag_online_geboekt_worden_achteraf_betalen", "allowed_to_pay_later"], ["regels", Recras::CombinationItem], ["programma", Recras::Itinerary], ["onlineboeking_contactformulier_id", "contact_form_id"], ["prijs_pp_inc","price_per_person_incl_vat"], ["prijs_totaal_inc","price_total_incl_vat"],["los_op_planning", "seperate_planning"],["uitgebreide_omschrijving","description"], ["maximum_aantal_personen_online","max_number_of_people"], ["ontvangstlocatie", "welcome_location"]]
|
146
164
|
end
|
147
165
|
|
148
166
|
private
|
@@ -158,7 +176,7 @@ module Recras
|
|
158
176
|
end
|
159
177
|
|
160
178
|
def convert_items(items, number_of_people)
|
161
|
-
if items.any?
|
179
|
+
if items && items.any?
|
162
180
|
# TODO
|
163
181
|
elsif number_of_people && number_of_people > 0
|
164
182
|
# assume that all the items will be chose the same amount
|
@@ -176,7 +194,7 @@ module Recras
|
|
176
194
|
end
|
177
195
|
return product_items
|
178
196
|
end
|
179
|
-
|
197
|
+
|
180
198
|
return items
|
181
199
|
end
|
182
200
|
|
@@ -10,9 +10,13 @@ module Recras
|
|
10
10
|
attr_accessor :location_id
|
11
11
|
attr_accessor :begins_at
|
12
12
|
attr_accessor :ends_at
|
13
|
+
attr_accessor :name
|
13
14
|
attr_accessor :description
|
14
15
|
attr_accessor :number_of_people
|
15
16
|
attr_accessor :product_id
|
17
|
+
attr_accessor :price
|
18
|
+
attr_accessor :minimum
|
19
|
+
attr_accessor :json
|
16
20
|
|
17
21
|
# Initializer to transform a +Hash+ into an Client object
|
18
22
|
# @param [Hash] args
|
@@ -22,6 +26,7 @@ module Recras
|
|
22
26
|
args.each do |k,v|
|
23
27
|
instance_variable_set("@#{k}", v) unless v.nil?
|
24
28
|
end
|
29
|
+
set_values_from_json
|
25
30
|
end
|
26
31
|
|
27
32
|
def self.plural_name
|
@@ -31,7 +36,15 @@ module Recras
|
|
31
36
|
# translates the mapping between the Recras API
|
32
37
|
# and the terms used in this gem
|
33
38
|
def self.attribute_mapping
|
34
|
-
[["id", "id"],["locatie_id", "location_id"],["begin", "begins_at@@time"],["eind", "ends_at@@time"], ["beschrijving", "description"], ["aantal_personen", "number_of_people"], ["product_id", "product_id"]]
|
39
|
+
[["id", "id"],["locatie_id", "location_id"],["begin", "begins_at@@time"],["eind", "ends_at@@time"], ["beschrijving", "description"], ["verkoop", "price@@float"], ["aantal_personen", "number_of_people"], ["product_id", "product_id"]]
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def set_values_from_json
|
45
|
+
self.price = json["product"]["verkoop"].to_f
|
46
|
+
self.name = json["product"]["naam"]
|
47
|
+
self.minimum = json["product"]["minimum_aantal"].to_i
|
35
48
|
end
|
36
49
|
|
37
50
|
end
|
data/lib/recras/contact_form.rb
CHANGED
@@ -0,0 +1,70 @@
|
|
1
|
+
module Recras
|
2
|
+
|
3
|
+
# links to 'programma' in the API
|
4
|
+
# http://recras.github.io/docs/endpoints/arrangementen.html
|
5
|
+
class Itinerary
|
6
|
+
extend Recras
|
7
|
+
# @note The is a required parameter.
|
8
|
+
|
9
|
+
attr_accessor :description
|
10
|
+
attr_accessor :quantity
|
11
|
+
attr_accessor :quantity_type
|
12
|
+
attr_accessor :start_time
|
13
|
+
attr_accessor :end_time
|
14
|
+
attr_accessor :duration
|
15
|
+
attr_accessor :json
|
16
|
+
|
17
|
+
# Initializer to transform a +Hash+ into an Client object
|
18
|
+
# @param [Hash] args
|
19
|
+
def initialize(args=nil)
|
20
|
+
required_args = []
|
21
|
+
return if args.nil?
|
22
|
+
args.each do |k,v|
|
23
|
+
instance_variable_set("@#{k}", v) unless v.nil?
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# outputs a nice readable itinerary
|
28
|
+
def to_s
|
29
|
+
"#{description} - #{quantity} #{quantity_type} (#{duration_string})"
|
30
|
+
end
|
31
|
+
|
32
|
+
def duration_string
|
33
|
+
"#{duration_hours.to_s.rjust(2, '0')}:#{duration_minutes.to_s.rjust(2, '0')}:#{duration_seconds.to_s.rjust(2, '0')}"
|
34
|
+
end
|
35
|
+
|
36
|
+
def duration_hours
|
37
|
+
begin
|
38
|
+
duration.split("PT").last.split("H").first.to_i
|
39
|
+
rescue
|
40
|
+
nil
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def duration_minutes
|
45
|
+
begin
|
46
|
+
duration.split("H").last.split("M").first.to_i
|
47
|
+
rescue
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def duration_seconds
|
53
|
+
begin
|
54
|
+
duration.split("M").last.split("S").first.to_i
|
55
|
+
rescue
|
56
|
+
nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
def self.plural_name
|
60
|
+
"itineraries"
|
61
|
+
end
|
62
|
+
|
63
|
+
# translates the mapping between the Recras API
|
64
|
+
# and the terms used in this gem
|
65
|
+
def self.attribute_mapping
|
66
|
+
[["omschrijving", "description"], ["aantal", "quantity"], ["wat", "quantity_type"], ["begin", "start_time"], ["duur", "duration"], ["eind", "end_time"]]
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
data/lib/recras/person.rb
CHANGED
data/lib/recras/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: recras
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.5
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henk Meijer
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-05-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -119,6 +119,7 @@ files:
|
|
119
119
|
- lib/recras/config.rb
|
120
120
|
- lib/recras/contact_form.rb
|
121
121
|
- lib/recras/contact_form_field.rb
|
122
|
+
- lib/recras/itinerary.rb
|
122
123
|
- lib/recras/person.rb
|
123
124
|
- lib/recras/recras_error.rb
|
124
125
|
- lib/recras/version.rb
|