tessitura_rest 1.5.1 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +1 -0
- data/README.md +61 -33
- data/lib/tessitura_rest/crm/addresses.rb +0 -3
- data/lib/tessitura_rest/crm/constituencies.rb +1 -1
- data/lib/tessitura_rest/crm/constituents.rb +49 -0
- data/lib/tessitura_rest/finance/appeals.rb +1 -1
- data/lib/tessitura_rest/txn/package.rb +1 -0
- data/lib/tessitura_rest/txn/performance_extension.rb +2 -7
- data/lib/tessitura_rest/version.rb +1 -1
- data/lib/tessitura_rest/web/cart.rb +1 -1
- data/lib/tessitura_rest/web/login.rb +3 -5
- data/lib/tessitura_rest/web/payment_plan_extension.rb +1 -0
- data/lib/tessitura_rest/web/registration.rb +38 -0
- data/lib/tessitura_rest/web/session.rb +25 -0
- data/lib/tessitura_rest.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 7f7d53c0e30ab24ecb1292529c3e77f9e0ca53d1247d9434ab73e396b9ef8291
|
4
|
+
data.tar.gz: 76f6b654bd47108357ee2edd2cfd4bdf40247763fa1f688dbdc05b2b5b3cd27c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3faf1d15c3bf233d61dc94a5a990f840df4978b5912cd7e928c08524b98783669bf3c2a27162ae13e748d877f3816be13f3a715d25e584309c02a693291ab7ff
|
7
|
+
data.tar.gz: afdca0d765b27d307271574880baef930e1e0b49f7fa95df9923ada1f2edf2802232218ffc05c047db98c83ca87c4b279303e324f7b7ff9ad21c4fa140c98935
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -1,3 +1,6 @@
|
|
1
|
+
[![Test Coverage](https://api.codeclimate.com/v1/badges/7e9be54ce754061ff52a/test_coverage)](https://codeclimate.com/repos/5a8308622f7e3e028700068f/test_coverage)
|
2
|
+
[![Maintainability](https://api.codeclimate.com/v1/badges/7e9be54ce754061ff52a/maintainability)](https://codeclimate.com/repos/5a8308622f7e3e028700068f/maintainability)
|
3
|
+
|
1
4
|
# TessituraRest
|
2
5
|
|
3
6
|
A Ruby gem wrapper for the [TessituraRest Network's Rest API](https://www.tessituranetwork.com/) (version 14 and up).
|
@@ -11,77 +14,102 @@ gem 'tessitura_rest'
|
|
11
14
|
```
|
12
15
|
|
13
16
|
And then execute:
|
17
|
+
|
14
18
|
```
|
15
19
|
$ bundle
|
16
20
|
```
|
21
|
+
|
17
22
|
Or install it yourself as:
|
23
|
+
|
18
24
|
```
|
19
25
|
$ gem install tessitura_rest
|
20
26
|
```
|
27
|
+
|
21
28
|
## Usage
|
22
29
|
|
23
30
|
Create a .env file in the root of your directory. The following fields are required:
|
24
31
|
|
25
|
-
*
|
26
|
-
* TESSITURA_USERNAME
|
27
|
-
* TESSITURA_PASSWORD
|
32
|
+
* TESSITURA_v16_URL # the url to your Production TessituraRest REST instance
|
33
|
+
* TESSITURA_USERNAME # the username to authenticate to your TessituraRest REST instance
|
34
|
+
* TESSITURA_PASSWORD # the password to authenticate to your TessituraRest REST instance
|
28
35
|
|
29
36
|
To run the gem locally, use:
|
37
|
+
|
30
38
|
```
|
31
39
|
$ rake console
|
32
40
|
```
|
41
|
+
|
33
42
|
To connect to the TessituraRest Rest API, use:
|
43
|
+
|
34
44
|
```
|
35
45
|
TessituraRest.new
|
36
46
|
```
|
37
|
-
|
47
|
+
|
48
|
+
followed by the method and arguments you would like to use.
|
38
49
|
|
39
50
|
## Running the Test Suite
|
40
51
|
|
41
52
|
1. You will need to add valid environment variables to the gem to run the test suite.
|
42
|
-
2. Delete all of the pre-recorded cassettes tapes from spec/vcr_cassettes so they can be re-recorded with your
|
53
|
+
2. Delete all of the pre-recorded cassettes tapes from spec/vcr_cassettes so they can be re-recorded with your
|
54
|
+
instance's settings.
|
43
55
|
3. Create a .env file and set these values:
|
44
56
|
|
45
|
-
* TESSITURA_URL
|
46
|
-
* USERNAME
|
47
|
-
* PASSWORD
|
48
|
-
* WEB_CART_TEXT
|
49
|
-
* SESSION_KEY
|
50
|
-
* EMAIL
|
51
|
-
* CONSTITUENT_ID
|
52
|
-
* ATTRIBUTE_ID
|
53
|
-
* SCALPER_ID
|
54
|
-
* CSI_ID
|
55
|
-
* PATRON_ID
|
56
|
-
* ACTION_ID
|
57
|
-
* ACTION_TYPE
|
58
|
-
* PROMO_CODE
|
59
|
-
* PROMO_CODE_STRING
|
60
|
-
* FUND
|
61
|
-
* FUND2
|
62
|
-
* MEMBER
|
63
|
-
* PAYMENT_ID
|
64
|
-
* GIFT_CARD_NO
|
65
|
-
* APPLIED_GC
|
66
|
-
* RETURN_TICKET_KEY
|
67
|
-
* TEMPLATE_ID
|
68
|
-
* PROFILE_ID
|
57
|
+
* TESSITURA_URL # the url to your Test/Staging TessituraRest REST instance
|
58
|
+
* USERNAME # the username to authenticate to your TessituraRest REST instance
|
59
|
+
* PASSWORD # the password to authenticate to your TessituraRest REST instance
|
60
|
+
* WEB_CART_TEXT # the ID to the pricing rule you have setup for Cart
|
61
|
+
* SESSION_KEY # an existing session key in your TessituraRest instance
|
62
|
+
* EMAIL # an email tied to an existing web login in your TessituraRest instance
|
63
|
+
* CONSTITUENT_ID # an active constituent in your TessituraRest instance
|
64
|
+
* ATTRIBUTE_ID # an active Attribute in your TessituraRest instance
|
65
|
+
* SCALPER_ID # any active constituent in your TessituraRest instance
|
66
|
+
* CSI_ID # the id of an open customer service inquiry in your TessituraRest instance
|
67
|
+
* PATRON_ID # the patron ID of a user whom submits CSIs
|
68
|
+
* ACTION_ID # the id of an action made against a customer service inquiry in your TessituraRest instance
|
69
|
+
* ACTION_TYPE # a valid action type that can be attributed to an action on a customer service inquiry
|
70
|
+
* PROMO_CODE # a valid integer tied to an active promotion code
|
71
|
+
* PROMO_CODE_STRING # a valid string tied to an active promotion code
|
72
|
+
* FUND # an active fund to apply money to
|
73
|
+
* FUND2 # another active fund to apply money to
|
74
|
+
* MEMBER # an active membership level
|
75
|
+
* PAYMENT_ID # active payment auth ID
|
76
|
+
* GIFT_CARD_NO # a valid gift certificate number that has been purchased
|
77
|
+
* APPLIED_GC # a valid gift certificate number that can be used to purchase products
|
78
|
+
* RETURN_TICKET_KEY # a logged in session that contains a exchangeable ticket
|
79
|
+
* TEMPLATE_ID # a valid email template ID to send Forgot Password emails
|
80
|
+
* PROFILE_ID # a valid email template profile ID
|
69
81
|
|
70
82
|
To run the tests:
|
83
|
+
|
71
84
|
```
|
72
85
|
$ rake spec
|
73
86
|
```
|
74
|
-
|
87
|
+
|
88
|
+
WARNING: I advise you NOT to run the test suite against your Production TessituraRest API since it will make database
|
89
|
+
alterations.
|
90
|
+
|
91
|
+
## Updating CircleCI's Environment Variables
|
92
|
+
|
93
|
+
1. Go to the CircleCI dashboard for the tessitura gem.
|
94
|
+
2. Click on the gear icon in the upper right corner.
|
95
|
+
3. Click on the tessitura gem project.
|
96
|
+
4. Click on Environment Variables.
|
97
|
+
5. Encode your .env with ```base64 -i .env -o .env_enc``` and add the encoded string to the ENV_ENC variable.
|
75
98
|
|
76
99
|
## Development
|
77
100
|
|
78
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can
|
101
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can
|
102
|
+
also run `bin/console` for an interactive prompt that will allow you to experiment.
|
79
103
|
|
80
|
-
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
|
104
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the
|
105
|
+
version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version,
|
106
|
+
push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
81
107
|
|
82
108
|
## Contributing
|
83
109
|
|
84
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/pgharts/tessitura. This project is intended to
|
110
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/pgharts/tessitura. This project is intended to
|
111
|
+
be a safe, welcoming space for collaboration, and contributors are expected to adhere to
|
112
|
+
the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
|
85
113
|
|
86
114
|
## License
|
87
115
|
|
@@ -22,7 +22,6 @@ module Addresses
|
|
22
22
|
'Id': constituent,
|
23
23
|
},
|
24
24
|
'Inactive': false,
|
25
|
-
'Label': true,
|
26
25
|
'Months': 'YYYYYYYYYYYY',
|
27
26
|
'PostalCode': postal_code,
|
28
27
|
'PrimaryIndicator': primary,
|
@@ -58,7 +57,6 @@ module Addresses
|
|
58
57
|
'Id': current['Constituent']['Id'],
|
59
58
|
},
|
60
59
|
'Inactive': false,
|
61
|
-
'Label': true,
|
62
60
|
'Months': 'YYYYYYYYYYYY',
|
63
61
|
'PostalCode': postal_code,
|
64
62
|
'PrimaryIndicator': primary,
|
@@ -94,7 +92,6 @@ module Addresses
|
|
94
92
|
'Id': current['Constituent']['Id'],
|
95
93
|
},
|
96
94
|
'Inactive': true,
|
97
|
-
'Label': true,
|
98
95
|
'Months': 'YYYYYYYYYYYY',
|
99
96
|
'PostalCode': current['PostalCode'],
|
100
97
|
'State': {
|
@@ -17,6 +17,6 @@ module Constituencies
|
|
17
17
|
}
|
18
18
|
options.merge!(basic_auth: @auth, headers: @headers)
|
19
19
|
options.merge!(:body => parameters.to_json)
|
20
|
-
|
20
|
+
self.class.post(base_api_endpoint('CRM/Constituencies'), options)
|
21
21
|
end
|
22
22
|
end
|
@@ -60,6 +60,55 @@ module Constituents
|
|
60
60
|
self.class.post(base_api_endpoint('CRM/Constituents/Snapshot'), options)
|
61
61
|
end
|
62
62
|
|
63
|
+
def create_constituent_by_snapshot_v16(first_name, last_name, email, phone, constituent_type, source, street1, street2, city, state, zip, country, options = {})
|
64
|
+
parameters =
|
65
|
+
{
|
66
|
+
'ConstituentType': {
|
67
|
+
'Id': constituent_type,
|
68
|
+
},
|
69
|
+
'FirstName': first_name,
|
70
|
+
'LastName': last_name,
|
71
|
+
'OriginalSource': {
|
72
|
+
'Id': source,
|
73
|
+
},
|
74
|
+
'PrimaryAddress': {
|
75
|
+
'AddressType': {
|
76
|
+
'Id': 3,
|
77
|
+
},
|
78
|
+
'City': city,
|
79
|
+
'PostalCode': zip,
|
80
|
+
'State': {
|
81
|
+
'Id': state,
|
82
|
+
},
|
83
|
+
'Street1': street1,
|
84
|
+
'Street2': street2,
|
85
|
+
'Country': {
|
86
|
+
'Id': country,
|
87
|
+
},
|
88
|
+
},
|
89
|
+
'PrimaryElectronicAddress': {
|
90
|
+
'Address': email,
|
91
|
+
'ElectronicAddressType': {
|
92
|
+
'Id': 1,
|
93
|
+
},
|
94
|
+
'AllowHtmlFormat': true,
|
95
|
+
'Inactive': false,
|
96
|
+
'AllowMarketing': false,
|
97
|
+
'Months': 'YYYYYYYYYYYY',
|
98
|
+
'PrimaryIndicator': true,
|
99
|
+
'PrimaryPhone': {
|
100
|
+
'PhoneNumber': phone,
|
101
|
+
'PhoneType': {
|
102
|
+
'Id': 5,
|
103
|
+
},
|
104
|
+
},
|
105
|
+
},
|
106
|
+
}
|
107
|
+
options.merge!(basic_auth: @auth, headers: @headers)
|
108
|
+
options.merge!(:body => parameters.to_json)
|
109
|
+
self.class.post(base_api_endpoint('CRM/Constituents/Snapshot'), options)
|
110
|
+
end
|
111
|
+
|
63
112
|
def update_constituent(constituent_id, params, options = {})
|
64
113
|
current = get_constituent_snapshot(constituent_id)
|
65
114
|
if is_household?(current)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Appeals
|
2
2
|
def get_appeal_info(appeal_id, options = {})
|
3
3
|
options.merge!(basic_auth: @auth, headers: @headers)
|
4
|
-
|
4
|
+
self.class.get(base_api_endpoint("Finance/Appeals/#{appeal_id}"), options)
|
5
5
|
end
|
6
6
|
end
|
@@ -14,6 +14,7 @@ module Package
|
|
14
14
|
options.merge!(basic_auth: @auth, headers: @headers)
|
15
15
|
options.merge!(:body => parameters.to_json)
|
16
16
|
response = self.class.post(base_api_endpoint('TXN/Packages/Search'), options)
|
17
|
+
JSON.parse(response.body)
|
17
18
|
end
|
18
19
|
|
19
20
|
def get_package_detail(id, mode_of_sale, options = {})
|
@@ -13,8 +13,7 @@ module PerformanceExtension
|
|
13
13
|
|
14
14
|
def get_performance_summaries(production_season_id, performance_ids = nil, season_ids = nil, options = {})
|
15
15
|
options.merge!(basic_auth: @auth, headers: @headers)
|
16
|
-
response = self.class.get(base_api_endpoint("
|
17
|
-
options)
|
16
|
+
response = self.class.get(base_api_endpoint("TXN/Performances/Summary?performanceIds=#{performance_ids}&seasonIds=#{season_ids}&productionSeasonId=#{production_season_id}"), options)
|
18
17
|
JSON.parse(response.body)
|
19
18
|
end
|
20
19
|
|
@@ -44,22 +43,18 @@ module PerformanceExtension
|
|
44
43
|
|
45
44
|
def get_performance_seat_summaries(id, mode_of_sale, constituent_id, price_type_ids, options = {})
|
46
45
|
options.merge!(basic_auth: @auth, headers: @headers)
|
47
|
-
response = self.class.get(
|
48
|
-
base_api_endpoint("TXN/Performances/#{id}/Seats/Summary?modeOfSaleId=#{mode_of_sale}&constituentId=#{constituent_id}&checkPriceTypeIds=#{price_type_ids}"), options
|
49
|
-
)
|
46
|
+
response = self.class.get(base_api_endpoint("TXN/Performances/#{id}/Seats/Summary?modeOfSaleId=#{mode_of_sale}&constituentId=#{constituent_id}&checkPriceTypeIds=#{price_type_ids}"), options)
|
50
47
|
JSON.parse(response.body)
|
51
48
|
end
|
52
49
|
|
53
50
|
def get_performance_prices(id, mos, source, options = {})
|
54
51
|
options.merge!(basic_auth: @auth, headers: @headers)
|
55
|
-
options.merge!(:headers => { 'Content-Type' => 'application/json' })
|
56
52
|
response = self.class.get(base_api_endpoint("TXN/Performances/Prices?performanceIds=#{id}&modeOfSaleId=#{mos}&sourceId=#{source}"), options)
|
57
53
|
JSON.parse(response.body)
|
58
54
|
end
|
59
55
|
|
60
56
|
def get_seat_holds(id, hold_code_ids, options = {})
|
61
57
|
options.merge!(basic_auth: @auth, headers: @headers)
|
62
|
-
options.merge!(:headers => { 'Content-Type' => 'application/json' })
|
63
58
|
response = self.class.get(base_api_endpoint("TXN/Performances/#{id}/Seats/Holds?holdCodeIds=#{hold_code_ids}"), options)
|
64
59
|
JSON.parse(response.body)
|
65
60
|
end
|
@@ -58,7 +58,7 @@ module Cart
|
|
58
58
|
self.class.delete(base_api_endpoint("Web/Cart/#{session_key}/Payments/GiftCertificate/#{gift_certificate_number}"), options)
|
59
59
|
end
|
60
60
|
|
61
|
-
def add_contribution(session_key, amount, fund, membership_level, renew =
|
61
|
+
def add_contribution(session_key, amount, fund, membership_level, renew = false, upgrade = false, options = {})
|
62
62
|
parameters =
|
63
63
|
{
|
64
64
|
'Amount': amount,
|
@@ -12,7 +12,6 @@ module Login
|
|
12
12
|
'Password': password,
|
13
13
|
'LoginTypeId': login_type_id,
|
14
14
|
'PromotionCode': promotion,
|
15
|
-
'PersistSessionOnFailure': true,
|
16
15
|
}
|
17
16
|
options.merge!(basic_auth: @auth, headers: @headers)
|
18
17
|
options.merge!(:body => parameters.to_json)
|
@@ -47,7 +46,7 @@ module Login
|
|
47
46
|
post.success?
|
48
47
|
end
|
49
48
|
|
50
|
-
def login_as_guest(email,
|
49
|
+
def login_as_guest(email, session_key, options = {})
|
51
50
|
# promotion will be added as a parameter in v 16.0
|
52
51
|
parameters =
|
53
52
|
{
|
@@ -57,13 +56,12 @@ module Login
|
|
57
56
|
}
|
58
57
|
options.merge!(basic_auth: @auth, headers: @headers)
|
59
58
|
options.merge!(body: parameters.to_json)
|
60
|
-
response = self.class.post(base_api_endpoint("Web/Session/#{
|
59
|
+
response = self.class.post(base_api_endpoint("Web/Session/#{session_key}/LoginAsGuest"), options)
|
61
60
|
JSON.parse(response.body)
|
62
61
|
end
|
63
62
|
|
64
63
|
def logout(session_key, options = {})
|
65
64
|
options.merge!(basic_auth: @auth, headers: @headers)
|
66
|
-
|
67
|
-
self.class.post(base_api_endpoint("/Web/Session/#{session_key}/Logout"), options)
|
65
|
+
self.class.post(base_api_endpoint("Web/Session/#{session_key}/Logout"), options)
|
68
66
|
end
|
69
67
|
end
|
@@ -37,4 +37,42 @@ module Registration
|
|
37
37
|
options.merge!(:body => parameters.to_json)
|
38
38
|
self.class.post(base_api_endpoint("Web/Registration/#{session_key}/Register"), options)
|
39
39
|
end
|
40
|
+
|
41
|
+
def register_user_v16(session_key, address, first_name, last_name, email, password, promotion, special_offer, phone, options = {})
|
42
|
+
parameters =
|
43
|
+
{
|
44
|
+
'FirstName': first_name,
|
45
|
+
'LastName': last_name,
|
46
|
+
'PrimaryElectronicAddress': {
|
47
|
+
'Address': email,
|
48
|
+
'AllowMarketing': special_offer || 0,
|
49
|
+
},
|
50
|
+
'WebLogin': {
|
51
|
+
'Login': email,
|
52
|
+
'LoginTypeId': 1,
|
53
|
+
'Password': password,
|
54
|
+
},
|
55
|
+
'PrimaryAddress': {
|
56
|
+
'AddressTypeId': 3,
|
57
|
+
'City': address.city,
|
58
|
+
'PostalCode': address.postal_code,
|
59
|
+
'StateId': address.state,
|
60
|
+
'Street1': address.street1,
|
61
|
+
'Street2': address.street2,
|
62
|
+
'CountryId': address.country,
|
63
|
+
},
|
64
|
+
'ConstituentTypeId': 1,
|
65
|
+
'OriginalSourceId': 3,
|
66
|
+
'SourceId': promotion,
|
67
|
+
'PrimaryPhone':
|
68
|
+
{
|
69
|
+
'PhoneNumber': phone,
|
70
|
+
'PhoneTypeId': 5,
|
71
|
+
},
|
72
|
+
}
|
73
|
+
options.merge!(basic_auth: @auth, headers: @headers)
|
74
|
+
options.merge!(:body => parameters.to_json)
|
75
|
+
self.class.post(base_api_endpoint("Web/Registration/#{session_key}/Register"), options)
|
76
|
+
end
|
77
|
+
|
40
78
|
end
|
@@ -51,6 +51,18 @@ module Session
|
|
51
51
|
JSON.parse(response.body)
|
52
52
|
end
|
53
53
|
|
54
|
+
def set_expiration_v16(key, expiration, timeoffset = 0, options = {})
|
55
|
+
parameters =
|
56
|
+
{
|
57
|
+
'Expiration': expiration,
|
58
|
+
'TimeOffset': timeoffset,
|
59
|
+
}
|
60
|
+
options.merge!(basic_auth: @auth, headers: @headers)
|
61
|
+
options.merge!(:body => parameters.to_json)
|
62
|
+
response = self.class.put(base_api_endpoint("Web/Session/#{key}/Expiration"), options)
|
63
|
+
JSON.parse(response.body)
|
64
|
+
end
|
65
|
+
|
54
66
|
def load_existing_order(key, order_id, options = {})
|
55
67
|
options.merge!(basic_auth: @auth, headers: @headers)
|
56
68
|
self.class.post(base_api_endpoint("Web/Session/#{key}/LoadOrder/#{order_id}"), options)
|
@@ -86,6 +98,19 @@ module Session
|
|
86
98
|
self.class.post(base_api_endpoint("/Web/Session/#{key}/Login/SendCredentials"), options)
|
87
99
|
end
|
88
100
|
|
101
|
+
def send_credentials_v16(key, email, login_type, template_id, options = {})
|
102
|
+
parameters =
|
103
|
+
{
|
104
|
+
'TemplateFormatId': template_id,
|
105
|
+
'LoginTypeId': login_type,
|
106
|
+
'EmailAddress': email,
|
107
|
+
'IsPriority': true,
|
108
|
+
}
|
109
|
+
options.merge!(basic_auth: @auth, headers: @headers)
|
110
|
+
options.merge!(:body => parameters.to_json)
|
111
|
+
self.class.post(base_api_endpoint("/Web/Session/#{key}/Login/SendCredentials"), options)
|
112
|
+
end
|
113
|
+
|
89
114
|
def update_login(key, user_name, old_password, new_password, email, new_email, options = {})
|
90
115
|
parameters =
|
91
116
|
{
|
data/lib/tessitura_rest.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tessitura_rest
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Brittany Martin, Danielle Greaves, Craig Donavin, Patrick FitzGerald
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-
|
11
|
+
date: 2024-06-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|