ruby-trello 2.0.1 → 3.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.
Files changed (305) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +61 -10
  3. data/lib/trello.rb +57 -36
  4. data/lib/trello/action.rb +31 -23
  5. data/lib/trello/association_builder/has_many.rb +17 -0
  6. data/lib/trello/association_builder/has_one.rb +16 -0
  7. data/lib/trello/association_fetcher/has_many.rb +26 -0
  8. data/lib/trello/association_fetcher/has_many/fetch.rb +47 -0
  9. data/lib/trello/association_fetcher/has_many/params.rb +56 -0
  10. data/lib/trello/association_fetcher/has_one.rb +25 -0
  11. data/lib/trello/association_fetcher/has_one/fetch.rb +49 -0
  12. data/lib/trello/association_fetcher/has_one/params.rb +36 -0
  13. data/lib/trello/association_infer_tool.rb +13 -0
  14. data/lib/trello/association_proxy.rb +1 -1
  15. data/lib/trello/attachment.rb +40 -27
  16. data/lib/trello/basic_data.rb +112 -50
  17. data/lib/trello/board.rb +91 -101
  18. data/lib/trello/card.rb +53 -200
  19. data/lib/trello/checklist.rb +17 -71
  20. data/lib/trello/comment.rb +32 -22
  21. data/lib/trello/cover_image.rb +20 -0
  22. data/lib/trello/custom_field.rb +78 -0
  23. data/lib/trello/custom_field_item.rb +76 -0
  24. data/lib/trello/custom_field_option.rb +49 -0
  25. data/lib/trello/item.rb +27 -16
  26. data/lib/trello/item_state.rb +7 -15
  27. data/lib/trello/json_utils.rb +1 -1
  28. data/lib/trello/label.rb +15 -84
  29. data/lib/trello/label_name.rb +22 -25
  30. data/lib/trello/list.rb +31 -44
  31. data/lib/trello/member.rb +77 -31
  32. data/lib/trello/notification.rb +27 -20
  33. data/lib/trello/organization.rb +53 -25
  34. data/lib/trello/plugin_datum.rb +11 -16
  35. data/lib/trello/schema.rb +31 -0
  36. data/lib/trello/schema/attribute/base.rb +79 -0
  37. data/lib/trello/schema/attribute/board_pref.rb +45 -0
  38. data/lib/trello/schema/attribute/custom_field_display.rb +45 -0
  39. data/lib/trello/schema/attribute/default.rb +45 -0
  40. data/lib/trello/schema/attribute_builder.rb +42 -0
  41. data/lib/trello/schema/attribute_registration.rb +47 -0
  42. data/lib/trello/schema/serializer/default.rb +17 -0
  43. data/lib/trello/schema/serializer/labels.rb +23 -0
  44. data/lib/trello/schema/serializer/time.rb +25 -0
  45. data/lib/trello/schema/serializer/webhooks.rb +25 -0
  46. data/lib/trello/token.rb +15 -12
  47. data/lib/trello/webhook.rb +18 -71
  48. data/spec/action_spec.rb +2 -3
  49. data/spec/basic_data_spec.rb +58 -0
  50. data/spec/board_spec.rb +53 -100
  51. data/spec/card_spec.rb +177 -66
  52. data/spec/cassettes/action_find_with_id_and_get_all_fields.yml +104 -0
  53. data/spec/cassettes/board_find_with_id_and_get_all_fields.yml +96 -0
  54. data/spec/cassettes/board_find_with_id_and_get_specific_fields.yml +96 -0
  55. data/spec/cassettes/can_add_a_file_from_url_on_a_card.yml +189 -0
  56. data/spec/cassettes/can_add_a_file_on_a_card.yml +200 -0
  57. data/spec/cassettes/can_add_a_member_to_a_board.yml +191 -0
  58. data/spec/cassettes/can_add_a_member_to_a_card.yml +190 -0
  59. data/spec/cassettes/can_add_label_on_a_card.yml +281 -0
  60. data/spec/cassettes/can_arvhice_all_cards_of_list.yml +397 -0
  61. data/spec/cassettes/can_close_bong_a_card.yml +189 -0
  62. data/spec/cassettes/can_get_actions.yml +196 -0
  63. data/spec/cassettes/can_get_actions_of_board.yml +188 -0
  64. data/spec/cassettes/can_get_actions_of_list.yml +202 -0
  65. data/spec/cassettes/can_get_actions_of_members.yml +199 -0
  66. data/spec/cassettes/can_get_actions_of_organization.yml +201 -0
  67. data/spec/cassettes/can_get_attachments.yml +187 -0
  68. data/spec/cassettes/can_get_boards_of_custom_field.yml +198 -0
  69. data/spec/cassettes/can_get_boards_of_label.yml +197 -0
  70. data/spec/cassettes/can_get_boards_of_organization.yml +207 -0
  71. data/spec/cassettes/can_get_cards_of_board.yml +193 -0
  72. data/spec/cassettes/can_get_cards_of_list.yml +201 -0
  73. data/spec/cassettes/can_get_cards_of_member.yml +204 -0
  74. data/spec/cassettes/can_get_checklists_of_board.yml +187 -0
  75. data/spec/cassettes/can_get_comments.yml +193 -0
  76. data/spec/cassettes/can_get_custom_field_options_of_custom_field.yml +197 -0
  77. data/spec/cassettes/can_get_custom_fields_of_board.yml +187 -0
  78. data/spec/cassettes/can_get_label_names_of_board.yml +187 -0
  79. data/spec/cassettes/can_get_labels_of_board.yml +187 -0
  80. data/spec/cassettes/can_get_lists_of_board.yml +187 -0
  81. data/spec/cassettes/can_get_members_of_board.yml +188 -0
  82. data/spec/cassettes/can_get_members_of_organization.yml +200 -0
  83. data/spec/cassettes/can_get_notifications_of_member.yml +199 -0
  84. data/spec/cassettes/can_get_organization_of_board.yml +189 -0
  85. data/spec/cassettes/can_get_organizations_of_member.yml +203 -0
  86. data/spec/cassettes/can_get_plugin_data_of_board.yml +187 -0
  87. data/spec/cassettes/can_move_a_card_to_another_board_with_specific_list.yml +373 -0
  88. data/spec/cassettes/can_move_a_card_to_another_board_without_specific_list.yml +281 -0
  89. data/spec/cassettes/can_move_a_card_to_another_list.yml +281 -0
  90. data/spec/cassettes/can_move_all_cards_to_another_list.yml +886 -0
  91. data/spec/cassettes/can_remove_a_member_from_a_card.yml +185 -0
  92. data/spec/cassettes/can_remove_an_attachment_on_a_card.yml +277 -0
  93. data/spec/cassettes/can_remove_an_upvote_on_a_card.yml +465 -0
  94. data/spec/cassettes/can_remove_label_on_a_card.yml +279 -0
  95. data/spec/cassettes/can_success_add_comment_to_a_card.yml +196 -0
  96. data/spec/cassettes/can_success_copy_checklist_to_a_card.yml +281 -0
  97. data/spec/cassettes/can_success_copy_checklist_to_a_card_without_name_pos.yml +281 -0
  98. data/spec/cassettes/can_success_create_a_board.yml +98 -0
  99. data/spec/cassettes/can_success_create_a_board_with_full_parameters.yml +97 -0
  100. data/spec/cassettes/can_success_create_a_board_without_clone_from_other.yml +98 -0
  101. data/spec/cassettes/can_success_create_a_card.yml +99 -0
  102. data/spec/cassettes/can_success_create_a_card_when_due_is_datetime.yml +98 -0
  103. data/spec/cassettes/can_success_create_a_card_when_due_is_time.yml +98 -0
  104. data/spec/cassettes/can_success_create_a_checklist.yml +102 -0
  105. data/spec/cassettes/can_success_create_a_custom_field.yml +102 -0
  106. data/spec/cassettes/can_success_create_a_custom_field_option.yml +102 -0
  107. data/spec/cassettes/can_success_create_a_label.yml +102 -0
  108. data/spec/cassettes/can_success_create_a_list.yml +102 -0
  109. data/spec/cassettes/can_success_create_a_list_with_full_parameters.yml +102 -0
  110. data/spec/cassettes/can_success_create_a_organization.yml +104 -0
  111. data/spec/cassettes/can_success_create_a_webhook.yml +102 -0
  112. data/spec/cassettes/can_success_create_new_checklist_to_a_card.yml +189 -0
  113. data/spec/cassettes/can_success_delete_a_custom_field_option.yml +389 -0
  114. data/spec/cassettes/can_success_delete_card.yml +185 -0
  115. data/spec/cassettes/can_success_delete_checklist.yml +284 -0
  116. data/spec/cassettes/can_success_get_card_of_board_by_card_id.yml +188 -0
  117. data/spec/cassettes/can_success_remove_member_from_board.yml +186 -0
  118. data/spec/cassettes/can_success_return_all_boards_of_current_user.yml +195 -0
  119. data/spec/cassettes/can_success_upate_a_board.yml +191 -0
  120. data/spec/cassettes/can_success_upate_a_card.yml +189 -0
  121. data/spec/cassettes/can_success_upate_a_list.yml +296 -0
  122. data/spec/cassettes/can_success_update_bong_a_board.yml +283 -0
  123. data/spec/cassettes/can_success_update_bong_a_board_with_specific_fields.yml +284 -0
  124. data/spec/cassettes/can_success_update_bong_a_card.yml +191 -0
  125. data/spec/cassettes/can_success_update_bong_a_checklist_with_specific_fields.yml +296 -0
  126. data/spec/cassettes/can_success_update_bong_a_custom_field.yml +200 -0
  127. data/spec/cassettes/can_success_update_bong_a_label.yml +200 -0
  128. data/spec/cassettes/can_success_update_bong_a_list.yml +199 -0
  129. data/spec/cassettes/can_success_update_bong_a_list_with_specific_fields.yml +296 -0
  130. data/spec/cassettes/can_success_update_bong_a_organization.yml +203 -0
  131. data/spec/cassettes/can_success_update_bong_a_webhook.yml +296 -0
  132. data/spec/cassettes/can_upvote_on_a_card.yml +469 -0
  133. data/spec/cassettes/card_find_with_id_and_get_all_fields.yml +95 -0
  134. data/spec/cassettes/card_find_with_id_and_get_specific_fields.yml +96 -0
  135. data/spec/cassettes/checklist_can_add_an_item.yml +296 -0
  136. data/spec/cassettes/checklist_can_update_the_item_state.yml +296 -0
  137. data/spec/cassettes/checklist_find_with_id_and_get_all_fields.yml +100 -0
  138. data/spec/cassettes/custom_field_find_with_id_and_get_all_fields.yml +100 -0
  139. data/spec/cassettes/custom_field_find_with_id_and_get_specific_fields.yml +100 -0
  140. data/spec/cassettes/custom_field_item_save_1.yml +97 -0
  141. data/spec/cassettes/custom_field_item_save_2.yml +281 -0
  142. data/spec/cassettes/custom_field_option_find_with_id.yml +100 -0
  143. data/spec/cassettes/get_board_of_card.yml +187 -0
  144. data/spec/cassettes/get_board_of_list.yml +197 -0
  145. data/spec/cassettes/get_boards_of_member.yml +207 -0
  146. data/spec/cassettes/get_check_item_states_of_card.yml +188 -0
  147. data/spec/cassettes/get_checklists_of_card.yml +187 -0
  148. data/spec/cassettes/get_cover_image_of_card.yml +187 -0
  149. data/spec/cassettes/get_custom_field_items_of_card.yml +187 -0
  150. data/spec/cassettes/get_list_of_card.yml +188 -0
  151. data/spec/cassettes/get_lists.yml +187 -0
  152. data/spec/cassettes/get_members_of_card.yml +189 -0
  153. data/spec/cassettes/get_plugin_data_of_card.yml +187 -0
  154. data/spec/cassettes/get_voters_of_card.yml +188 -0
  155. data/spec/cassettes/label_delete.yml +285 -0
  156. data/spec/cassettes/label_find_with_id.yml +100 -0
  157. data/spec/cassettes/list_find_with_id_and_get_all_fields.yml +100 -0
  158. data/spec/cassettes/list_find_with_id_and_get_specific_fields.yml +100 -0
  159. data/spec/cassettes/member_find_with_id_and_get_all_fields.yml +101 -0
  160. data/spec/cassettes/member_find_with_id_and_get_specific_fields.yml +100 -0
  161. data/spec/cassettes/notification_find_with_id.yml +103 -0
  162. data/spec/cassettes/organization_find_with_id_and_get_all_fields.yml +102 -0
  163. data/spec/cassettes/organization_find_with_id_and_get_specific_fields.yml +100 -0
  164. data/spec/cassettes/remove_upvote_on_a_card_when_have_not_voted.yml +366 -0
  165. data/spec/cassettes/revote_on_a_card.yml +464 -0
  166. data/spec/cassettes/token_find_with_token_string.yml +100 -0
  167. data/spec/cassettes/webhook_delete.yml +286 -0
  168. data/spec/cassettes/webhook_find_with_id.yml +100 -0
  169. data/spec/checklist_spec.rb +27 -43
  170. data/spec/custom_field_item_spec.rb +192 -0
  171. data/spec/custom_field_option_spec.rb +49 -0
  172. data/spec/custom_field_spec.rb +273 -0
  173. data/spec/integration/action/find_spec.rb +23 -0
  174. data/spec/integration/basic_data/many_spec.rb +127 -0
  175. data/spec/integration/basic_data/one_spec.rb +84 -0
  176. data/spec/integration/basic_data/schema_spec.rb +156 -0
  177. data/spec/integration/board/add_member_spec.rb +21 -0
  178. data/spec/integration/board/all_spec.rb +20 -0
  179. data/spec/integration/board/associations/actions_spec.rb +18 -0
  180. data/spec/integration/board/associations/cards_spec.rb +18 -0
  181. data/spec/integration/board/associations/checklists_spec.rb +18 -0
  182. data/spec/integration/board/associations/custom_fields_spec.rb +18 -0
  183. data/spec/integration/board/associations/label_names_spec.rb +17 -0
  184. data/spec/integration/board/associations/labels_spec.rb +18 -0
  185. data/spec/integration/board/associations/lists_spec.rb +18 -0
  186. data/spec/integration/board/associations/members_spec.rb +18 -0
  187. data/spec/integration/board/associations/organization_spec.rb +19 -0
  188. data/spec/integration/board/associations/plugin_data_spec.rb +18 -0
  189. data/spec/integration/board/create_spec.rb +95 -0
  190. data/spec/integration/board/find_card_spec.rb +18 -0
  191. data/spec/integration/board/find_spec.rb +42 -0
  192. data/spec/integration/board/remove_member_spec.rb +21 -0
  193. data/spec/integration/board/save_spec.rb +37 -0
  194. data/spec/integration/board/update!_spec.rb +62 -0
  195. data/spec/integration/board_lists_spec.rb +21 -0
  196. data/spec/integration/card/add_and_remove_attachment_spec.rb +45 -0
  197. data/spec/integration/card/add_and_remove_label_spec.rb +35 -0
  198. data/spec/integration/card/add_checklist_spec.rb +32 -0
  199. data/spec/integration/card/add_comment_spec.rb +19 -0
  200. data/spec/integration/card/add_memeber_spec.rb +19 -0
  201. data/spec/integration/card/associations/actions_spec.rb +17 -0
  202. data/spec/integration/card/associations/attachments_spec.rb +18 -0
  203. data/spec/integration/card/associations/board_spec.rb +17 -0
  204. data/spec/integration/card/associations/check_item_states_spec.rb +17 -0
  205. data/spec/integration/card/associations/checklists_spec.rb +18 -0
  206. data/spec/integration/card/associations/comments_spec.rb +19 -0
  207. data/spec/integration/card/associations/cover_image_spec.rb +18 -0
  208. data/spec/integration/card/associations/custom_field_items_spec.rb +18 -0
  209. data/spec/integration/card/associations/list_spec.rb +16 -0
  210. data/spec/integration/card/associations/members_spec.rb +18 -0
  211. data/spec/integration/card/associations/plugin_data_spec.rb +18 -0
  212. data/spec/integration/card/associations/voters_spec.rb +17 -0
  213. data/spec/integration/card/close!_spec.rb +16 -0
  214. data/spec/integration/card/create_new_check_list_spec.rb +19 -0
  215. data/spec/integration/card/create_spec.rb +84 -0
  216. data/spec/integration/card/delete_spec.rb +16 -0
  217. data/spec/integration/card/find_spec.rb +67 -0
  218. data/spec/integration/card/move_to_board_spec.rb +36 -0
  219. data/spec/integration/card/move_to_list_spec.rb +20 -0
  220. data/spec/integration/card/remove_member_spec.rb +19 -0
  221. data/spec/integration/card/save_spec.rb +61 -0
  222. data/spec/integration/card/update!_spec.rb +53 -0
  223. data/spec/integration/card/vote_spec.rb +50 -0
  224. data/spec/integration/checklist/add_item_spec.rb +20 -0
  225. data/spec/integration/checklist/create_spec.rb +23 -0
  226. data/spec/integration/checklist/delete_spec.rb +17 -0
  227. data/spec/integration/checklist/find_spec.rb +22 -0
  228. data/spec/integration/checklist/update!_spec.rb +21 -0
  229. data/spec/integration/checklist/update_item_state_spec.rb +20 -0
  230. data/spec/integration/custom_field/association/board_spec.rb +18 -0
  231. data/spec/integration/custom_field/association/custom_field_options_spec.rb +18 -0
  232. data/spec/integration/custom_field/create_spec.rb +29 -0
  233. data/spec/integration/custom_field/find_spec.rb +41 -0
  234. data/spec/integration/custom_field/update!_spec.rb +25 -0
  235. data/spec/integration/custom_field_item_spec.rb +47 -0
  236. data/spec/integration/custom_field_option/create_spec.rb +23 -0
  237. data/spec/integration/custom_field_option/delete_spec.rb +19 -0
  238. data/spec/integration/custom_field_option/find_spec.rb +21 -0
  239. data/spec/integration/label/association/board_spec.rb +18 -0
  240. data/spec/integration/label/create_spec.rb +23 -0
  241. data/spec/integration/label/delete_spec.rb +21 -0
  242. data/spec/integration/label/find_spec.rb +20 -0
  243. data/spec/integration/label/update!_spec.rb +25 -0
  244. data/spec/integration/list/archive_all_cards_spec.rb +20 -0
  245. data/spec/integration/list/associations/actions_spec.rb +18 -0
  246. data/spec/integration/list/associations/board_spec.rb +18 -0
  247. data/spec/integration/list/associations/cards_spec.rb +18 -0
  248. data/spec/integration/list/create_spec.rb +44 -0
  249. data/spec/integration/list/find_spec.rb +37 -0
  250. data/spec/integration/list/move_all_cards_spec.rb +31 -0
  251. data/spec/integration/list/save_spec.rb +40 -0
  252. data/spec/integration/list/update!_spec.rb +43 -0
  253. data/spec/integration/member/associations/actions_spec.rb +17 -0
  254. data/spec/integration/member/associations/boards_spec.rb +18 -0
  255. data/spec/integration/member/associations/cards_spec.rb +18 -0
  256. data/spec/integration/member/associations/notifications_spec.rb +18 -0
  257. data/spec/integration/member/associations/organizations_spec.rb +18 -0
  258. data/spec/integration/member/find_spec.rb +39 -0
  259. data/spec/integration/member/update!_spec.rb +18 -0
  260. data/spec/integration/notification/find_spec.rb +27 -0
  261. data/spec/integration/organization/associations/actions_spec.rb +18 -0
  262. data/spec/integration/organization/associations/boards_spec.rb +18 -0
  263. data/spec/integration/organization/associations/members_spec.rb +18 -0
  264. data/spec/integration/organization/create_spec.rb +23 -0
  265. data/spec/integration/organization/find_spec.rb +37 -0
  266. data/spec/integration/organization/update!_spec.rb +28 -0
  267. data/spec/integration/token/find_spec.rb +24 -0
  268. data/spec/integration/webhook/create_spec.rb +27 -0
  269. data/spec/integration/webhook/delete_spec.rb +21 -0
  270. data/spec/integration/webhook/find_spec.rb +22 -0
  271. data/spec/integration/webhook/update!_spec.rb +24 -0
  272. data/spec/item_spec.rb +2 -2
  273. data/spec/label_spec.rb +105 -28
  274. data/spec/list_spec.rb +32 -14
  275. data/spec/notification_spec.rb +3 -3
  276. data/spec/organization_spec.rb +6 -5
  277. data/spec/spec_helper.rb +118 -37
  278. data/spec/token_spec.rb +10 -11
  279. data/spec/unit/trello/association_builder/has_many_spec.rb +36 -0
  280. data/spec/unit/trello/association_builder/has_one_spec.rb +36 -0
  281. data/spec/unit/trello/association_fetcher/has_many/fetch_spec.rb +38 -0
  282. data/spec/unit/trello/association_fetcher/has_many/params_spec.rb +107 -0
  283. data/spec/unit/trello/association_fetcher/has_many_spec.rb +50 -0
  284. data/spec/unit/trello/association_fetcher/has_one/fetch_spec.rb +51 -0
  285. data/spec/unit/trello/association_fetcher/has_one/params_spec.rb +81 -0
  286. data/spec/unit/trello/association_fetcher/has_one_spec.rb +49 -0
  287. data/spec/unit/trello/association_infer_tool_spec.rb +41 -0
  288. data/spec/unit/trello/basic_data_spec.rb +113 -0
  289. data/spec/unit/trello/board/new_spec.rb +370 -0
  290. data/spec/unit/trello/board/save_spec.rb +49 -0
  291. data/spec/unit/trello/board/update_fields_spec.rb +129 -0
  292. data/spec/unit/trello/board/update_spec.rb +197 -0
  293. data/spec/unit/trello/card_spec.rb +103 -0
  294. data/spec/unit/trello/member/new_spec.rb +62 -0
  295. data/spec/unit/trello/member/update_fields_spec.rb +80 -0
  296. data/spec/unit/trello/schema/attribute/base_spec.rb +349 -0
  297. data/spec/unit/trello/schema/attribute/board_pref_spec.rb +208 -0
  298. data/spec/unit/trello/schema/attribute/default_spec.rb +236 -0
  299. data/spec/unit/trello/schema/attribute_builder_spec.rb +55 -0
  300. data/spec/unit/trello/schema/attribute_registration_spec.rb +59 -0
  301. data/spec/unit/trello/schema/serializer/default_spec.rb +19 -0
  302. data/spec/unit/trello/schema/serializer/time_spec.rb +39 -0
  303. data/spec/unit/trello/schema_spec.rb +25 -0
  304. data/spec/webhook_spec.rb +23 -7
  305. metadata +542 -29
@@ -0,0 +1,25 @@
1
+ module Trello
2
+ module AssociationFetcher
3
+ class HasOne
4
+ autoload :Params, 'trello/association_fetcher/has_one/params'
5
+ autoload :Fetch, 'trello/association_fetcher/has_one/fetch'
6
+
7
+ attr_reader :model, :name, :options
8
+
9
+ def initialize(model, name, options)
10
+ @model = model
11
+ @name = name
12
+ @options = options
13
+ end
14
+
15
+ def fetch
16
+ params = Params.new(
17
+ association_owner: model,
18
+ association_name: name,
19
+ association_options: options
20
+ )
21
+ Fetch.execute(params)
22
+ end
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,49 @@
1
+ module Trello
2
+ module AssociationFetcher
3
+ class HasOne
4
+ class Fetch
5
+ class << self
6
+ def execute(params)
7
+ new(params).execute
8
+ end
9
+ end
10
+
11
+ def initialize(params)
12
+ @params = params
13
+ end
14
+
15
+ def execute
16
+ if association_restful_name
17
+ client.find(association_restful_name, association_restful_id)
18
+ else
19
+ association_class.find(association_restful_id)
20
+ end
21
+ end
22
+
23
+ private
24
+
25
+ attr_reader :params
26
+
27
+ def client
28
+ association_owner.client
29
+ end
30
+
31
+ def association_owner
32
+ params.association_owner
33
+ end
34
+
35
+ def association_restful_name
36
+ params.association_restful_name
37
+ end
38
+
39
+ def association_restful_id
40
+ params.association_restful_id
41
+ end
42
+
43
+ def association_class
44
+ params.association_class
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,36 @@
1
+ module Trello
2
+ module AssociationFetcher
3
+ class HasOne
4
+ class Params
5
+ attr_reader :association_owner
6
+
7
+ def initialize(association_owner:, association_name:, association_options:)
8
+ @association_owner = association_owner
9
+ @association_name = association_name
10
+ @association_options = association_options || {}
11
+ end
12
+
13
+ def association_class
14
+ association_options[:via] || infer_class_on(association_name)
15
+ end
16
+
17
+ def association_restful_name
18
+ association_options[:path]
19
+ end
20
+
21
+ def association_restful_id
22
+ id_field = association_options[:using] || :id
23
+ association_owner.send(id_field)
24
+ end
25
+
26
+ private
27
+
28
+ attr_reader :association_name, :association_options
29
+
30
+ def infer_class_on(name)
31
+ AssociationInferTool.infer_class_on_name(name)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,13 @@
1
+ module Trello
2
+ class AssociationInferTool
3
+ class << self
4
+ def infer_restful_resource_on_class(klass)
5
+ klass.to_s.split('::').last.downcase.pluralize
6
+ end
7
+
8
+ def infer_class_on_name(name)
9
+ Trello.const_get(name.to_s.singularize.camelize)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -31,7 +31,7 @@ module Trello
31
31
  end
32
32
 
33
33
  def to_ary
34
- proxy_assocation.dup
34
+ proxy_assocation.target.dup
35
35
  end
36
36
  alias_method :to_a, :to_ary
37
37
 
@@ -1,40 +1,53 @@
1
1
  module Trello
2
2
  # A file or url that is linked to a Trello card
3
3
  #
4
- # @!attribute id
4
+ # @!attribute [r] id
5
5
  # @return [String]
6
- # @!attribute name
7
- # @return [String]
8
- # @!attribute url
9
- # @return [String]
10
- # @!attribute pos
6
+ # @!attribute [r] position
11
7
  # @return [Float]
12
- # @!attribute bytes
8
+ # @!attribute [r] bytes
13
9
  # @return [Fixnum]
14
- # @!attribute date
10
+ # @!attribute [r] member_id
11
+ # @return [String]
12
+ # @!attribute [r] date
15
13
  # @return [Datetime]
16
- # @!attribute is_upload
14
+ # @!attribute [r] is_upload
17
15
  # @return [Boolean]
18
- # @!attribute mime_type
16
+ # @!attribute [r] previews
17
+ # @return [Array]
18
+ # @!attribute [r] file_name
19
+ # @return [String]
20
+ # @!attribute [r] edge_color
21
+ # @return [String]
22
+ # @!attribute [rw] name
19
23
  # @return [String]
24
+ # @!attribute [rw] url
25
+ # @return [String]
26
+ # @!attribute [rw] mime_type
27
+ # @return [String]
28
+ # @!attribute [w] file
29
+ # @return [String]
30
+ # @!attribute [w] set_as_cover
31
+ # @return [Boolean]
20
32
  class Attachment < BasicData
21
- register_attributes :name, :id, :pos, :url, :bytes, :member_id, :date, :is_upload, :mime_type, :previews
22
- # Update the fields of an attachment.
23
- #
24
- # Supply a hash of stringkeyed data retrieved from the Trello API representing
25
- # an attachment.
26
- def update_fields(fields)
27
- attributes[:name] = fields['name'] || attributes[:name]
28
- attributes[:id] = fields['id'] || attributes[:id]
29
- attributes[:pos] = fields['pos'] || attributes[:pos]
30
- attributes[:url] = fields['url'] || attributes[:url]
31
- attributes[:bytes] = fields['bytes'].to_i || attributes[:bytes]
32
- attributes[:member_id] = fields['idMember'] || attributes[:member_id]
33
- attributes[:date] = Time.parse(fields['date']).presence || attributes[:date]
34
- attributes[:is_upload] = fields['isUpload'] if fields.has_key?('isUpload')
35
- attributes[:mime_type] = fields['mimeType'] || attributes[:mime_type]
36
- attributes[:previews] = fields['previews'] if fields.has_key?('previews')
37
- self
33
+ schema do
34
+ # Readonly
35
+ attribute :id, readonly: true, primary_key: true
36
+ attribute :position, readonly: true, remote_key: 'pos'
37
+ attribute :bytes, readonly: true
38
+ attribute :member_id, remote_key: 'idMember', readonly: true
39
+ attribute :date, serializer: 'Time', readonly: true
40
+ attribute :is_upload, remote_key: 'isUpload', readonly: true
41
+ attribute :previews, readonly: true
42
+ attribute :file_name, remote_key: 'fileName', readonly: true
43
+ attribute :edge_color, remote_key: 'edgeColor', readonly: true
44
+
45
+ # Writable but create only
46
+ attribute :name, create_only: true
47
+ attribute :url, create_only: true
48
+ attribute :mime_type, remote_key: 'mimeType', create_only: true
49
+ attribute :file, create_only: true
50
+ attribute :set_as_cover, remote_key: 'setCover', create_only: true
38
51
  end
39
52
  end
40
53
  end
@@ -42,77 +42,101 @@ module Trello
42
42
  end
43
43
  end
44
44
 
45
- def self.register_attributes(*names)
46
- options = { readonly: [] }
47
- options.merge!(names.pop) if names.last.kind_of? Hash
48
-
49
- # Defines the attribute getter and setters.
50
- class_eval do
51
- define_method :attributes do
52
- @attributes ||= names.reduce({}) { |hash, k| hash.merge(k.to_sym => nil) }
53
- end
45
+ def self.schema(&block)
46
+ @schema ||= Schema.new
47
+ return @schema unless block_given?
54
48
 
55
- names.each do |key|
56
- define_method(:"#{key}") { @attributes[key] }
49
+ @schema.instance_eval(&block)
57
50
 
58
- unless options[:readonly].include?(key.to_sym)
59
- define_method :"#{key}=" do |val|
60
- send(:"#{key}_will_change!") unless val == @attributes[key]
61
- @attributes[key] = val
62
- end
63
- end
64
- end
51
+ register_attrs
52
+
53
+ @schema
54
+ end
65
55
 
66
- define_attribute_methods names
56
+ def self.register_attrs
57
+ schema.attrs.values.each do |attribute|
58
+ attribute.register(self)
67
59
  end
68
60
  end
69
61
 
70
62
  def self.one(name, opts = {})
71
- class_eval do
72
- define_method(:"#{name}") do |*args|
73
- options = opts.dup
74
- klass = options.delete(:via) || Trello.const_get(name.to_s.camelize)
75
- ident = options.delete(:using) || :id
76
- path = options.delete(:path)
77
-
78
- if path
79
- client.find(path, self.send(ident))
80
- else
81
- klass.find(self.send(ident))
82
- end
83
- end
84
- end
63
+ AssociationBuilder::HasOne.build(self, name, opts)
85
64
  end
86
65
 
87
66
  def self.many(name, opts = {})
88
- class_eval do
89
- define_method(:"#{name}") do |*args|
90
- options = opts.dup
91
- resource = options.delete(:in) || self.class.to_s.split("::").last.downcase.pluralize
92
- klass = options.delete(:via) || Trello.const_get(name.to_s.singularize.camelize)
93
- path = options.delete(:path) || name
94
- params = options.merge(args[0] || {})
95
-
96
- resources = client.find_many(klass, "/#{resource}/#{id}/#{path}", params)
97
- MultiAssociation.new(self, resources).proxy
98
- end
99
- end
67
+ AssociationBuilder::HasMany.build(self, name, opts)
100
68
  end
101
69
 
102
70
  def self.client
103
71
  Trello.client
104
72
  end
105
73
 
106
- register_attributes :id, readonly: [ :id ]
107
-
108
74
  attr_writer :client
109
75
 
110
76
  def initialize(fields = {})
111
- update_fields(fields)
77
+ initialize_fields(fields)
78
+ end
79
+
80
+ def save
81
+ return update! if id
82
+
83
+ payload = {}
84
+
85
+ schema.attrs.each do |_, attribute|
86
+ payload = attribute.build_payload_for_create(attributes, payload)
87
+ end
88
+
89
+ post(collection_path, payload)
90
+ end
91
+
92
+ def update!
93
+ fail "Cannot save new instance." unless id
94
+
95
+ @previously_changed = changes
96
+
97
+ payload = {}
98
+ changed_attrs = attributes.select {|name, _| changed.include?(name.to_s)}
99
+
100
+ schema.attrs.each do |_, attribute|
101
+ payload = attribute.build_payload_for_update(changed_attrs, payload)
102
+ end
103
+
104
+ from_response client.put(element_path, payload)
105
+
106
+ @changed_attributes.clear if @changed_attributes.respond_to?(:clear)
107
+ changes_applied if respond_to?(:changes_applied)
108
+
109
+ self
112
110
  end
113
111
 
114
112
  def update_fields(fields)
115
- raise NotImplementedError, "#{self.class} does not implement update_fields."
113
+ attrs = {}
114
+
115
+ schema.attrs.each do |_, attribute|
116
+ attrs = attribute.build_pending_update_attributes(fields, attrs)
117
+ end
118
+
119
+ attrs.each do |name, value|
120
+ send("#{name}=", value)
121
+ end
122
+
123
+ self
124
+ end
125
+
126
+ def collection_path
127
+ "/#{collection_name}"
128
+ end
129
+
130
+ def element_path
131
+ "/#{collection_name}/#{id}"
132
+ end
133
+
134
+ def collection_name
135
+ @collection_path ||= ActiveSupport::Inflector.pluralize(element_name)
136
+ end
137
+
138
+ def element_name
139
+ @element_name ||= model_name.element
116
140
  end
117
141
 
118
142
  # Refresh the contents of our object.
@@ -122,11 +146,49 @@ module Trello
122
146
 
123
147
  # Two objects are equal if their _id_ methods are equal.
124
148
  def ==(other)
125
- id == other.id
149
+ self.class == other.class && id == other.id
150
+ end
151
+
152
+ # Alias hash equality to equality
153
+ alias eql? ==
154
+
155
+ # Delegate hash key computation to class and id pair
156
+ def hash
157
+ [self.class, id].hash
126
158
  end
127
159
 
128
160
  def client
129
161
  @client ||= self.class.client
130
162
  end
163
+
164
+ def schema
165
+ self.class.schema
166
+ end
167
+
168
+ def attributes
169
+ @__attributes ||= ActiveSupport::HashWithIndifferentAccess.new
170
+ end
171
+
172
+ private
173
+
174
+ def attributes=(attrs)
175
+ @__attributes = attrs
176
+ end
177
+
178
+ def initialize_fields(fields)
179
+ schema.attrs.each do |_, attribute|
180
+ self.attributes = attribute.build_attributes(fields, attributes)
181
+ end
182
+
183
+ self
184
+ end
185
+
186
+ def post(path, body)
187
+ from_response client.post(path, body)
188
+ end
189
+
190
+ def put(path, body)
191
+ from_response client.put(path, body)
192
+ end
131
193
  end
132
194
  end
@@ -4,21 +4,100 @@ module Trello
4
4
  #
5
5
  # @!attribute [r] id
6
6
  # @return [String]
7
- # @!attribute [r] name
7
+ # @!attribute [r] starred
8
+ # @return [Boolean]
9
+ # @!attribute [r] pinned
10
+ # @return [Boolean]
11
+ # @!attribute [r] url
12
+ # @return [String]
13
+ # @!attribute [r] short_url
14
+ # @return [String]
15
+ # @!attribute [r] prefs
16
+ # @return [Hash]
17
+ # @!attribute [r] last_activity_date
18
+ # @return [Datetime]
19
+ # @!attribute [r] description_data
20
+ # @return [Datetime]
21
+ # @!attribute [r] enterprise_id
22
+ # @return [String]
23
+ # @!attribute [rw] name
8
24
  # @return [String]
9
25
  # @!attribute [rw] description
10
26
  # @return [String]
11
- # @!attribute [rw] closed
27
+ # @!attribute [rw] organization_id
28
+ # @return [String]
29
+ # @!attribute [rw] visibility_level
30
+ # @return [String]
31
+ # @!attribute [rw] voting_permission_level
32
+ # @return [String]
33
+ # @!attribute [rw] comment_permission_level
34
+ # @return [String]
35
+ # @!attribute [rw] invitation_permission_level
36
+ # @return [String]
37
+ # @!attribute [rw] enable_self_join
12
38
  # @return [Boolean]
13
- # @!attribute [r] url
39
+ # @!attribute [rw] enable_card_covers
40
+ # @return [Boolean]
41
+ # @!attribute [rw] background_color
14
42
  # @return [String]
15
- # @!attribute [rw] organization_id
16
- # @return [String] A 24-character hex string
17
- # @!attribute [r] prefs
18
- # @return [Hash] A 24-character hex string
43
+ # @!attribute [rw] background_image
44
+ # @return [String]
45
+ # @!attribute [rw] card_aging_type
46
+ # @return [String]
47
+ # @!attribute [w] use_default_labels
48
+ # @return [Boolean]
49
+ # @!attribute [w] use_default_lists
50
+ # @return [Boolean]
51
+ # @!attribute [w] source_board_id
52
+ # @return [String]
53
+ # @!attribute [w] keep_cards_from_source
54
+ # @return [String]
55
+ # @!attribute [w] power_ups
56
+ # @return [String]
57
+ # @!attribute [rw] closed
58
+ # @return [Boolean]
59
+ # @!attribute [w] subscribed
60
+ # @return [Boolean]
19
61
  class Board < BasicData
20
- register_attributes :id, :name, :description, :closed, :starred, :url, :organization_id, :prefs, :last_activity_date,
21
- readonly: [ :id, :url, :last_activity_date ]
62
+ schema do
63
+ attribute :id, readonly: true, primary_key: true
64
+
65
+ # Readonly
66
+ attribute :starred, readonly: true
67
+ attribute :pinned, readonly: true
68
+ attribute :url, readonly: true
69
+ attribute :short_url, readonly: true, remote_key: 'shortUrl'
70
+ attribute :prefs, readonly: true, default: {}
71
+ attribute :last_activity_date, readonly: true, remote_key: 'dateLastActivity', serializer: 'Time'
72
+ attribute :description_data, readonly: true, remote_key: 'descData'
73
+ attribute :enterprise_id, readonly: true, remote_key: 'idEnterprise'
74
+
75
+ # Writable
76
+ attribute :name
77
+ attribute :description, remote_key: 'desc'
78
+ attribute :organization_id, remote_key: 'idOrganization'
79
+ attribute :visibility_level, remote_key: 'permissionLevel', class_name: 'BoardPref'
80
+ attribute :voting_permission_level, remote_key: 'voting', class_name: 'BoardPref'
81
+ attribute :comment_permission_level, remote_key: 'comments', class_name: 'BoardPref'
82
+ attribute :invitation_permission_level, remote_key: 'invitations', class_name: 'BoardPref'
83
+ attribute :enable_self_join, remote_key: 'selfJoin', class_name: 'BoardPref'
84
+ attribute :enable_card_covers, remote_key: 'cardCovers', class_name: 'BoardPref'
85
+ attribute :background_color, remote_key: 'background', class_name: 'BoardPref'
86
+ attribute :background_image, remote_key: 'backgroundImage', class_name: 'BoardPref'
87
+ attribute :card_aging_type, remote_key: 'cardAging', class_name: 'BoardPref'
88
+
89
+ # Writable but for create only
90
+ attribute :use_default_labels, create_only: true, remote_key: 'defaultLabels'
91
+ attribute :use_default_lists, create_only: true, remote_key: 'defaultLists'
92
+ attribute :source_board_id, create_only: true, remote_key: 'idBoardSource'
93
+ attribute :keep_cards_from_source, create_only: true, remote_key: 'keepFromSource'
94
+ attribute :power_ups, create_only: true, remote_key: 'powerUps'
95
+
96
+ # Writable but for update only
97
+ attribute :closed, update_only: true
98
+ attribute :subscribed, update_only: true
99
+ end
100
+
22
101
  validates_presence_of :id, :name
23
102
  validates_length_of :name, in: 1..16384
24
103
  validates_length_of :description, maximum: 16384
@@ -26,81 +105,12 @@ module Trello
26
105
  include HasActions
27
106
 
28
107
  class << self
29
- # Finds a board.
30
- #
31
- # @param [String] id Either the board's short ID (an alphanumeric string,
32
- # found e.g. in the board's URL) or its long ID (a 24-character hex
33
- # string.)
34
- # @param [Hash] params
35
- #
36
- # @raise [Trello::Board] if a board with the given ID could not be found.
37
- #
38
- # @return [Trello::Board]
39
- def find(id, params = {})
40
- client.find(:board, id, params)
41
- end
42
-
43
- def create(fields)
44
- data = {
45
- 'name' => fields[:name],
46
- 'desc' => fields[:description],
47
- 'closed' => fields[:closed] || false,
48
- 'starred' => fields[:starred] || false }
49
- data.merge!('idOrganization' => fields[:organization_id]) if fields[:organization_id]
50
- data.merge!('prefs' => fields[:prefs]) if fields[:prefs]
51
- client.create(:board, data)
52
- end
53
-
54
108
  # @return [Array<Trello::Board>] all boards for the current user
55
109
  def all
56
110
  from_response client.get("/members/#{Member.find(:me).username}/boards")
57
111
  end
58
112
  end
59
113
 
60
- def save
61
- return update! if id
62
-
63
- fields = { name: name }
64
- fields.merge!(desc: description) if description
65
- fields.merge!(idOrganization: organization_id) if organization_id
66
- fields.merge!(flat_prefs)
67
-
68
- from_response(client.post("/boards", fields))
69
- end
70
-
71
- def update!
72
- fail "Cannot save new instance." unless self.id
73
-
74
- @previously_changed = changes
75
- @changed_attributes.clear
76
-
77
- fields = {
78
- name: attributes[:name],
79
- description: attributes[:description],
80
- closed: attributes[:closed],
81
- starred: attributes[:starred],
82
- idOrganization: attributes[:organization_id]
83
- }
84
- fields.merge!(flat_prefs)
85
-
86
- from_response client.put("/boards/#{self.id}/", fields)
87
- end
88
-
89
- def update_fields(fields)
90
- attributes[:id] = fields['id'] || fields[:id] if fields['id'] || fields[:id]
91
- attributes[:name] = fields['name'] || fields[:name] if fields['name'] || fields[:name]
92
- attributes[:description] = fields['desc'] || fields[:desc] if fields['desc'] || fields[:desc]
93
- attributes[:closed] = fields['closed'] if fields.has_key?('closed')
94
- attributes[:closed] = fields[:closed] if fields.has_key?(:closed)
95
- attributes[:starred] = fields['starred'] if fields.has_key?('starred')
96
- attributes[:starred] = fields[:starred] if fields.has_key?(:starred)
97
- attributes[:url] = fields['url'] if fields['url']
98
- attributes[:organization_id] = fields['idOrganization'] || fields[:organization_id] if fields['idOrganization'] || fields[:organization_id]
99
- attributes[:prefs] = fields['prefs'] || fields[:prefs] || {}
100
- attributes[:last_activity_date] = Time.iso8601(fields['dateLastActivity']) rescue nil
101
- self
102
- end
103
-
104
114
  # @return [Boolean]
105
115
  def closed?
106
116
  attributes[:closed]
@@ -167,6 +177,9 @@ module Trello
167
177
  # Returns a list of plugins associated with the board
168
178
  many :plugin_data, path: "pluginData"
169
179
 
180
+ # Returns custom fields activated on this board
181
+ many :custom_fields, path: "customFields"
182
+
170
183
  def labels(params = {})
171
184
  # Set the limit to as high as possible given there is no pagination in this API.
172
185
  params[:limit] = 1000 unless params[:limit]
@@ -184,28 +197,5 @@ module Trello
184
197
  "/boards/#{id}"
185
198
  end
186
199
 
187
- private
188
-
189
- # On creation
190
- # https://trello.com/docs/api/board/#post-1-boards
191
- # - permissionLevel
192
- # - voting
193
- # - comments
194
- # - invitations
195
- # - selfJoin
196
- # - cardCovers
197
- # - background
198
- # - cardAging
199
- #
200
- # On update
201
- # https://trello.com/docs/api/board/#put-1-boards-board-id
202
- # Same as above plus:
203
- # - calendarFeedEnabled
204
- def flat_prefs
205
- separator = id ? "/" : "_"
206
- attributes[:prefs].inject({}) do |hash, (pref, v)|
207
- hash.merge("prefs#{separator}#{pref}" => v)
208
- end
209
- end
210
200
  end
211
201
  end