xeroizer 0.2.2 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (115) hide show
  1. data/VERSION +1 -1
  2. data/lib/xeroizer/exceptions.rb +13 -0
  3. data/lib/xeroizer/generic_application.rb +1 -0
  4. data/lib/xeroizer/models/credit_note.rb +1 -0
  5. data/lib/xeroizer/models/employee.rb +28 -0
  6. data/lib/xeroizer/models/external_link.rb +16 -0
  7. data/lib/xeroizer/models/invoice.rb +2 -0
  8. data/lib/xeroizer/models/organisation.rb +13 -7
  9. data/lib/xeroizer/models/payment.rb +1 -1
  10. data/lib/xeroizer/models/tracking_category_child.rb +4 -1
  11. data/lib/xeroizer/record/base.rb +2 -2
  12. data/lib/xeroizer/record/base_model.rb +21 -3
  13. data/lib/xeroizer/record/model_definition_helper.rb +6 -2
  14. data/lib/xeroizer/record/record_association_helper.rb +42 -4
  15. data/lib/xeroizer/record/xml_helper.rb +3 -2
  16. data/lib/xeroizer/report/factory.rb +3 -2
  17. data/lib/xeroizer/response.rb +1 -1
  18. data/lib/xeroizer.rb +1 -0
  19. data/test/stub_responses/contacts.xml +0 -3349
  20. data/test/stub_responses/credit_note.xml +37 -31
  21. data/test/stub_responses/credit_notes.xml +54 -34
  22. data/test/stub_responses/employees.xml +29 -0
  23. data/test/stub_responses/invoice.xml +44 -51
  24. data/test/stub_responses/invoices.xml +1180 -1055
  25. data/test/stub_responses/organisation.xml +10 -1
  26. data/test/stub_responses/organisations.xml +13 -4
  27. data/test/stub_responses/payments.xml +1121 -0
  28. data/test/stub_responses/records/credit_note-371cd138-1e5c-4ec1-a8c6-a1c10e8bdab1.xml +13 -9
  29. data/test/stub_responses/records/credit_note-3bffc09b-79f2-490d-b91b-c59b700b43a4.xml +13 -9
  30. data/test/stub_responses/records/credit_note-43c678ee-f357-48e2-b192-b6e3634762f9.xml +13 -9
  31. data/test/stub_responses/records/credit_note-482c018b-d329-4e05-9b4f-7a4cfc695aa0.xml +13 -9
  32. data/test/stub_responses/records/credit_note-4f67130a-749a-4ee6-98b2-743adbc11245.xml +11 -9
  33. data/test/stub_responses/records/credit_note-50e98404-2fba-4031-af67-8ba4bb227c44.xml +12 -9
  34. data/test/stub_responses/records/credit_note-7df8949c-b71f-40c0-bbcf-39f2f450f286.xml +11 -9
  35. data/test/stub_responses/records/credit_note-b356e488-2678-4be4-ad4b-d294df2d48d6.xml +9 -7
  36. data/test/stub_responses/records/invoice-0032f627-3156-4d30-9b1c-4d3b994dc921.xml +13 -11
  37. data/test/stub_responses/records/invoice-00c9511b-24b9-4190-a90a-8abf2fe9f4a0.xml +13 -11
  38. data/test/stub_responses/records/invoice-024d7994-a26c-4c20-9894-13934840fc31.xml +12 -11
  39. data/test/stub_responses/records/invoice-0e64a623-c2a1-446a-93ed-eb897f118cbc.xml +9 -8
  40. data/test/stub_responses/records/invoice-15e88e57-2554-4496-a18e-eb3f5c622345.xml +13 -11
  41. data/test/stub_responses/records/invoice-166f0588-d0ba-458c-b28a-8edd4c8fc463.xml +13 -11
  42. data/test/stub_responses/records/invoice-1d1ba340-afa2-4f4c-8ff7-a147bda9a47b.xml +13 -11
  43. data/test/stub_responses/records/invoice-290ef4c4-baec-492b-b4dd-c102826470ae.xml +13 -11
  44. data/test/stub_responses/records/invoice-30a87092-31b5-4a2c-831e-327486533dd2.xml +10 -8
  45. data/test/stub_responses/records/invoice-30dbd181-72a8-43df-b392-4241bf43d5fc.xml +22 -11
  46. data/test/stub_responses/records/invoice-33e4123e-7cdd-4f05-9a0a-eb8adeb2b868.xml +13 -11
  47. data/test/stub_responses/records/invoice-387db692-26ac-47e6-b6cc-015343809bda.xml +13 -11
  48. data/test/stub_responses/records/invoice-3b28bf11-ed2f-4cf4-8e9e-fcae730cc292.xml +13 -11
  49. data/test/stub_responses/records/invoice-3fcb9847-b350-412e-ab90-7d9d774ad881.xml +13 -11
  50. data/test/stub_responses/records/invoice-440613e4-4785-4eff-9ba1-c432816cf8c7.xml +78 -0
  51. data/test/stub_responses/records/invoice-4602eda6-abe9-448e-b65f-ae6bea21f0eb.xml +10 -8
  52. data/test/stub_responses/records/invoice-46441f63-873f-4cdc-a278-b8fe516f3abb.xml +11 -8
  53. data/test/stub_responses/records/invoice-4ad1ec01-f4a3-41d7-bbb4-d2ab2fec8e65.xml +12 -11
  54. data/test/stub_responses/records/invoice-4b9afceb-f7c7-4e64-8aac-7b009971fd52.xml +13 -11
  55. data/test/stub_responses/records/invoice-4edbf6d5-4e92-43af-bedd-7effc0b86833.xml +10 -8
  56. data/test/stub_responses/records/invoice-4fad1af2-b871-4ac5-a15a-3c5e32d2e2c4.xml +19 -9
  57. data/test/stub_responses/records/invoice-52ee4d67-cae4-462c-adb2-182c39017f3d.xml +13 -11
  58. data/test/stub_responses/records/invoice-54585f46-c1a0-4432-bd4f-c1fae2fba59b.xml +9 -8
  59. data/test/stub_responses/records/invoice-5613938b-9e27-472e-92ae-3b038b669d10.xml +13 -11
  60. data/test/stub_responses/records/invoice-5aa9451d-95d1-4f95-a966-bbab2573f71c.xml +10 -8
  61. data/test/stub_responses/records/invoice-5aadcd34-01a9-4b8d-a2bb-d7cc1de9fa45.xml +13 -11
  62. data/test/stub_responses/records/invoice-5f6deadf-36a2-495a-9980-ceb11e8af9a9.xml +10 -8
  63. data/test/stub_responses/records/invoice-625ffe1b-f5d8-438e-a376-981de5f5a733.xml +13 -11
  64. data/test/stub_responses/records/invoice-64cd559e-8e03-46af-b461-8555285cee71.xml +10 -8
  65. data/test/stub_responses/records/invoice-66fbe37f-49b1-43fd-97ed-85114022cd2f.xml +10 -8
  66. data/test/stub_responses/records/invoice-673dd7cc-beb7-4697-83d4-0c47cb400cc2.xml +21 -11
  67. data/test/stub_responses/records/invoice-69fc971e-9b37-41c5-9c87-174330f22343.xml +9 -8
  68. data/test/stub_responses/records/invoice-70e6db69-e5a4-42c7-a397-aa3212c2945f.xml +10 -8
  69. data/test/stub_responses/records/invoice-766d1289-b440-4675-a656-1a0612ecac77.xml +13 -11
  70. data/test/stub_responses/records/invoice-76bcb361-f93b-4513-b312-5a4af306d276.xml +9 -8
  71. data/test/stub_responses/records/invoice-76e3f056-479f-417c-a72b-f3d767899b87.xml +13 -11
  72. data/test/stub_responses/records/invoice-77b338ef-ecc0-4b95-a0d7-2617b0054611.xml +21 -10
  73. data/test/stub_responses/records/invoice-7be9956d-5316-4f6b-a66a-d355b3f159b2.xml +13 -11
  74. data/test/stub_responses/records/invoice-7dae876a-b424-436b-a4e6-17b3fdeec80c.xml +20 -11
  75. data/test/stub_responses/records/invoice-7e862d93-8dab-4856-8b0c-d844e09d750f.xml +10 -8
  76. data/test/stub_responses/records/invoice-803f70b0-56d9-4157-9787-41df271777a0.xml +13 -11
  77. data/test/stub_responses/records/invoice-86102312-aa3f-438c-9938-6840f4d8dda6.xml +12 -11
  78. data/test/stub_responses/records/invoice-8694c9c5-7097-4449-a708-b8c1982921a4.xml +9 -8
  79. data/test/stub_responses/records/invoice-86d6e00f-ef56-49f7-9a54-796ccd5ca057.xml +10 -8
  80. data/test/stub_responses/records/invoice-88e77f0f-54a5-4efc-a979-7e22223cc4d7.xml +9 -8
  81. data/test/stub_responses/records/invoice-8b0ccb6a-d9b7-4da5-8360-ef7fb157b5aa.xml +9 -8
  82. data/test/stub_responses/records/invoice-935fc854-8037-4111-8d91-993010c331cc.xml +12 -11
  83. data/test/stub_responses/records/invoice-962ef33f-c9d2-4602-9b9f-93a02bea23b3.xml +13 -10
  84. data/test/stub_responses/records/invoice-9868b472-1983-48e9-8edf-7e81ddf2c03a.xml +10 -8
  85. data/test/stub_responses/records/invoice-a3bc62ef-f11b-4a9c-a4f9-a342bda371b5.xml +9 -8
  86. data/test/stub_responses/records/invoice-a6894ca0-60ee-4d45-9dd4-b44fcba46ec5.xml +13 -11
  87. data/test/stub_responses/records/invoice-a77268ce-74b2-483d-a2b3-70dbdc9e49d2.xml +78 -0
  88. data/test/stub_responses/records/invoice-a9f765e6-b9bc-4505-a47b-fb3ecb327e7b.xml +14 -11
  89. data/test/stub_responses/records/invoice-aa0173af-8707-4e7f-8dde-4c7a357bd312.xml +30 -13
  90. data/test/stub_responses/records/invoice-ab63738a-370a-43a5-bfa3-620d684e66d0.xml +10 -8
  91. data/test/stub_responses/records/invoice-b0344791-5a8a-40dd-a208-d99a461a6c10.xml +13 -11
  92. data/test/stub_responses/records/invoice-b1e53910-473c-46a3-b3cb-38ece571220e.xml +21 -11
  93. data/test/stub_responses/records/invoice-b2c02d0b-41a8-4d4d-97d7-014c78b3547d.xml +13 -11
  94. data/test/stub_responses/records/invoice-b75b3928-ab72-4424-8b93-9cdbbde4cd72.xml +19 -9
  95. data/test/stub_responses/records/invoice-bcd8a71f-aa31-4d0f-8a01-13ea26363ddf.xml +13 -11
  96. data/test/stub_responses/records/invoice-bfbb7c45-de02-45e7-b065-d9863ecfb0d8.xml +9 -8
  97. data/test/stub_responses/records/invoice-c12aff7e-12bf-4185-8702-460929f19674.xml +9 -8
  98. data/test/stub_responses/records/invoice-c3380b96-976d-4b3e-8b26-8d01eb6a3742.xml +13 -11
  99. data/test/stub_responses/records/invoice-c963f2b0-cbe1-4abd-9ccc-7e512c942068.xml +9 -8
  100. data/test/stub_responses/records/invoice-cba46b29-3788-4158-b668-ab10160ccbfe.xml +78 -0
  101. data/test/stub_responses/records/invoice-dba2f021-f149-4191-a126-5351d587ab0e.xml +12 -11
  102. data/test/stub_responses/records/invoice-de5d9c29-21b3-4342-958b-ed72c4bd7ab0.xml +13 -11
  103. data/test/stub_responses/records/invoice-e3d96555-2876-4364-a46a-7551a4f52611.xml +15 -11
  104. data/test/stub_responses/records/invoice-e4a0afbd-aea0-450b-ae23-0ce921e84a77.xml +11 -8
  105. data/test/stub_responses/records/invoice-e9cb9ecb-58ef-43a8-bd20-69a85338142d.xml +13 -11
  106. data/test/stub_responses/records/invoice-ec9a6f67-7128-4a63-8ba3-5e516f455f9b.xml +13 -11
  107. data/test/stub_responses/records/invoice-ed0f2587-84fc-4aef-bc4b-b1a262e24484.xml +14 -11
  108. data/test/stub_responses/records/invoice-f362ca53-8ade-4047-865a-bb64bee5863d.xml +12 -11
  109. data/test/stub_responses/records/invoice-f571c38b-5be1-41e1-ad5a-ff6184284beb.xml +21 -11
  110. data/test/stub_responses/records/invoice-f5832195-5cd3-4660-ad3f-b73d9c64f263.xml +10 -8
  111. data/test/stub_responses/records/invoice-f9c857eb-64cd-4235-a078-d04b52c77ea7.xml +13 -11
  112. data/test/stub_responses/refresh_responses.rb +1 -1
  113. data/test/unit/record/record_association_test.rb +33 -0
  114. data/xeroizer.gemspec +9 -2
  115. metadata +11 -4
@@ -31,6 +31,39 @@ class RecordAssociationTest < Test::Unit::TestCase
31
31
  assert_equal(true, invoice.complete_record_downloaded?)
32
32
  end
33
33
 
34
+ should "auto-build belongs_to item when passed hash" do
35
+ invoice = @client.Invoice.build
36
+ assert_nil(invoice.contact)
37
+ invoice.contact = {:name => "Test Contact"}
38
+ assert_kind_of(Xeroizer::Record::Contact, invoice.contact)
39
+ assert_equal("Test Contact", invoice.contact.name)
40
+ end
41
+
42
+ should "auto-build has_many items when passed hash" do
43
+ contact = @client.Contact.build
44
+ assert_equal([], contact.phones)
45
+ contact.phones = {:type => "DEFAULT", :number => "1234"}
46
+ assert_kind_of(Xeroizer::Record::Phone, contact.phones.first)
47
+ assert_equal("1234", contact.phones.first.number)
48
+ end
49
+
50
+ should "auto-build has_many items when passed array" do
51
+ contact = @client.Contact.build
52
+ assert_equal([], contact.phones)
53
+
54
+ data = [
55
+ {:type => "DEFAULT", :number => "1111"},
56
+ {:type => "FAX", :number => "2222"}
57
+ ]
58
+ contact.phones = data.dup
59
+
60
+ assert_equal(2, contact.phones.size)
61
+ contact.phones.each_with_index do | phone, index |
62
+ assert_kind_of(Xeroizer::Record::Phone, phone)
63
+ assert_equal(data[index][:number], phone.number)
64
+ end
65
+ end
66
+
34
67
  end
35
68
 
36
69
  end
data/xeroizer.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{xeroizer}
8
- s.version = "0.2.2"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Wayne Robinson"]
12
- s.date = %q{2011-05-23}
12
+ s.date = %q{2011-05-31}
13
13
  s.description = %q{Ruby library for the Xero accounting system API.}
14
14
  s.email = %q{wayne.robinson@gmail.com}
15
15
  s.extra_rdoc_files = [
@@ -42,6 +42,8 @@ Gem::Specification.new do |s|
42
42
  "lib/xeroizer/models/contact_group.rb",
43
43
  "lib/xeroizer/models/credit_note.rb",
44
44
  "lib/xeroizer/models/currency.rb",
45
+ "lib/xeroizer/models/employee.rb",
46
+ "lib/xeroizer/models/external_link.rb",
45
47
  "lib/xeroizer/models/invoice.rb",
46
48
  "lib/xeroizer/models/item.rb",
47
49
  "lib/xeroizer/models/item_purchase_sale_details.rb",
@@ -97,6 +99,7 @@ Gem::Specification.new do |s|
97
99
  "test/stub_responses/credit_note_not_found_error.xml",
98
100
  "test/stub_responses/credit_notes.xml",
99
101
  "test/stub_responses/currencies.xml",
102
+ "test/stub_responses/employees.xml",
100
103
  "test/stub_responses/invalid_api_key_error.xml",
101
104
  "test/stub_responses/invalid_consumer_key",
102
105
  "test/stub_responses/invalid_request_token",
@@ -108,6 +111,7 @@ Gem::Specification.new do |s|
108
111
  "test/stub_responses/manual_journals.xml",
109
112
  "test/stub_responses/organisation.xml",
110
113
  "test/stub_responses/organisations.xml",
114
+ "test/stub_responses/payments.xml",
111
115
  "test/stub_responses/rate_limit_exceeded",
112
116
  "test/stub_responses/records/contact-043892a1-aef1-4c18-88d8-b8ccb6d31466.xml",
113
117
  "test/stub_responses/records/contact-09664078-efe2-4a88-89a5-67eac9b0047b.xml",
@@ -235,6 +239,7 @@ Gem::Specification.new do |s|
235
239
  "test/stub_responses/records/invoice-387db692-26ac-47e6-b6cc-015343809bda.xml",
236
240
  "test/stub_responses/records/invoice-3b28bf11-ed2f-4cf4-8e9e-fcae730cc292.xml",
237
241
  "test/stub_responses/records/invoice-3fcb9847-b350-412e-ab90-7d9d774ad881.xml",
242
+ "test/stub_responses/records/invoice-440613e4-4785-4eff-9ba1-c432816cf8c7.xml",
238
243
  "test/stub_responses/records/invoice-4602eda6-abe9-448e-b65f-ae6bea21f0eb.xml",
239
244
  "test/stub_responses/records/invoice-46441f63-873f-4cdc-a278-b8fe516f3abb.xml",
240
245
  "test/stub_responses/records/invoice-4ad1ec01-f4a3-41d7-bbb4-d2ab2fec8e65.xml",
@@ -275,6 +280,7 @@ Gem::Specification.new do |s|
275
280
  "test/stub_responses/records/invoice-a1d04a14-96a8-4067-a0ff-8136990a354f.xml",
276
281
  "test/stub_responses/records/invoice-a3bc62ef-f11b-4a9c-a4f9-a342bda371b5.xml",
277
282
  "test/stub_responses/records/invoice-a6894ca0-60ee-4d45-9dd4-b44fcba46ec5.xml",
283
+ "test/stub_responses/records/invoice-a77268ce-74b2-483d-a2b3-70dbdc9e49d2.xml",
278
284
  "test/stub_responses/records/invoice-a9f765e6-b9bc-4505-a47b-fb3ecb327e7b.xml",
279
285
  "test/stub_responses/records/invoice-aa0173af-8707-4e7f-8dde-4c7a357bd312.xml",
280
286
  "test/stub_responses/records/invoice-ab63738a-370a-43a5-bfa3-620d684e66d0.xml",
@@ -287,6 +293,7 @@ Gem::Specification.new do |s|
287
293
  "test/stub_responses/records/invoice-c12aff7e-12bf-4185-8702-460929f19674.xml",
288
294
  "test/stub_responses/records/invoice-c3380b96-976d-4b3e-8b26-8d01eb6a3742.xml",
289
295
  "test/stub_responses/records/invoice-c963f2b0-cbe1-4abd-9ccc-7e512c942068.xml",
296
+ "test/stub_responses/records/invoice-cba46b29-3788-4158-b668-ab10160ccbfe.xml",
290
297
  "test/stub_responses/records/invoice-d62646b9-d0a9-4fdb-9561-756a8b7eba45.xml",
291
298
  "test/stub_responses/records/invoice-dba2f021-f149-4191-a126-5351d587ab0e.xml",
292
299
  "test/stub_responses/records/invoice-de5d9c29-21b3-4342-958b-ed72c4bd7ab0.xml",
metadata CHANGED
@@ -5,9 +5,9 @@ version: !ruby/object:Gem::Version
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 2
9
- - 2
10
- version: 0.2.2
8
+ - 3
9
+ - 0
10
+ version: 0.3.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Wayne Robinson
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-05-23 00:00:00 +10:00
18
+ date: 2011-05-31 00:00:00 +10:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -217,6 +217,8 @@ files:
217
217
  - lib/xeroizer/models/contact_group.rb
218
218
  - lib/xeroizer/models/credit_note.rb
219
219
  - lib/xeroizer/models/currency.rb
220
+ - lib/xeroizer/models/employee.rb
221
+ - lib/xeroizer/models/external_link.rb
220
222
  - lib/xeroizer/models/invoice.rb
221
223
  - lib/xeroizer/models/item.rb
222
224
  - lib/xeroizer/models/item_purchase_sale_details.rb
@@ -272,6 +274,7 @@ files:
272
274
  - test/stub_responses/credit_note_not_found_error.xml
273
275
  - test/stub_responses/credit_notes.xml
274
276
  - test/stub_responses/currencies.xml
277
+ - test/stub_responses/employees.xml
275
278
  - test/stub_responses/invalid_api_key_error.xml
276
279
  - test/stub_responses/invalid_consumer_key
277
280
  - test/stub_responses/invalid_request_token
@@ -283,6 +286,7 @@ files:
283
286
  - test/stub_responses/manual_journals.xml
284
287
  - test/stub_responses/organisation.xml
285
288
  - test/stub_responses/organisations.xml
289
+ - test/stub_responses/payments.xml
286
290
  - test/stub_responses/rate_limit_exceeded
287
291
  - test/stub_responses/records/contact-043892a1-aef1-4c18-88d8-b8ccb6d31466.xml
288
292
  - test/stub_responses/records/contact-09664078-efe2-4a88-89a5-67eac9b0047b.xml
@@ -410,6 +414,7 @@ files:
410
414
  - test/stub_responses/records/invoice-387db692-26ac-47e6-b6cc-015343809bda.xml
411
415
  - test/stub_responses/records/invoice-3b28bf11-ed2f-4cf4-8e9e-fcae730cc292.xml
412
416
  - test/stub_responses/records/invoice-3fcb9847-b350-412e-ab90-7d9d774ad881.xml
417
+ - test/stub_responses/records/invoice-440613e4-4785-4eff-9ba1-c432816cf8c7.xml
413
418
  - test/stub_responses/records/invoice-4602eda6-abe9-448e-b65f-ae6bea21f0eb.xml
414
419
  - test/stub_responses/records/invoice-46441f63-873f-4cdc-a278-b8fe516f3abb.xml
415
420
  - test/stub_responses/records/invoice-4ad1ec01-f4a3-41d7-bbb4-d2ab2fec8e65.xml
@@ -450,6 +455,7 @@ files:
450
455
  - test/stub_responses/records/invoice-a1d04a14-96a8-4067-a0ff-8136990a354f.xml
451
456
  - test/stub_responses/records/invoice-a3bc62ef-f11b-4a9c-a4f9-a342bda371b5.xml
452
457
  - test/stub_responses/records/invoice-a6894ca0-60ee-4d45-9dd4-b44fcba46ec5.xml
458
+ - test/stub_responses/records/invoice-a77268ce-74b2-483d-a2b3-70dbdc9e49d2.xml
453
459
  - test/stub_responses/records/invoice-a9f765e6-b9bc-4505-a47b-fb3ecb327e7b.xml
454
460
  - test/stub_responses/records/invoice-aa0173af-8707-4e7f-8dde-4c7a357bd312.xml
455
461
  - test/stub_responses/records/invoice-ab63738a-370a-43a5-bfa3-620d684e66d0.xml
@@ -462,6 +468,7 @@ files:
462
468
  - test/stub_responses/records/invoice-c12aff7e-12bf-4185-8702-460929f19674.xml
463
469
  - test/stub_responses/records/invoice-c3380b96-976d-4b3e-8b26-8d01eb6a3742.xml
464
470
  - test/stub_responses/records/invoice-c963f2b0-cbe1-4abd-9ccc-7e512c942068.xml
471
+ - test/stub_responses/records/invoice-cba46b29-3788-4158-b668-ab10160ccbfe.xml
465
472
  - test/stub_responses/records/invoice-d62646b9-d0a9-4fdb-9561-756a8b7eba45.xml
466
473
  - test/stub_responses/records/invoice-dba2f021-f149-4191-a126-5351d587ab0e.xml
467
474
  - test/stub_responses/records/invoice-de5d9c29-21b3-4342-958b-ed72c4bd7ab0.xml