axiom 0.1.1 → 0.2.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 (311) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +2 -1
  3. data/.rubocop.yml +7 -0
  4. data/.travis.yml +10 -7
  5. data/Gemfile +4 -0
  6. data/Gemfile.devtools +27 -13
  7. data/Guardfile +2 -2
  8. data/README.md +36 -30
  9. data/TODO +22 -24
  10. data/axiom.gemspec +9 -9
  11. data/benchmarks/memory.rb +1 -2
  12. data/benchmarks/speed.rb +7 -8
  13. data/config/flay.yml +1 -1
  14. data/config/reek.yml +19 -7
  15. data/config/rubocop.yml +6 -9
  16. data/lib/axiom.rb +28 -13
  17. data/lib/axiom/aggregate/mean.rb +4 -3
  18. data/lib/axiom/aggregate/sum.rb +1 -1
  19. data/lib/axiom/algebra/extension.rb +1 -1
  20. data/lib/axiom/algebra/join.rb +4 -27
  21. data/lib/axiom/algebra/product.rb +3 -3
  22. data/lib/axiom/algebra/projection.rb +2 -2
  23. data/lib/axiom/algebra/rename.rb +2 -2
  24. data/lib/axiom/algebra/rename/aliases.rb +3 -3
  25. data/lib/axiom/algebra/summarization.rb +3 -3
  26. data/lib/axiom/attribute.rb +5 -4
  27. data/lib/axiom/attribute/comparable.rb +15 -11
  28. data/lib/axiom/attribute/date.rb +1 -1
  29. data/lib/axiom/attribute/date_time.rb +1 -1
  30. data/lib/axiom/attribute/length_comparable.rb +39 -0
  31. data/lib/axiom/attribute/numeric.rb +1 -26
  32. data/lib/axiom/attribute/relation.rb +64 -0
  33. data/lib/axiom/attribute/string.rb +1 -28
  34. data/lib/axiom/attribute/time.rb +1 -1
  35. data/lib/axiom/attribute/tuple.rb +50 -0
  36. data/lib/axiom/attribute/value_comparable.rb +42 -0
  37. data/lib/axiom/function.rb +1 -1
  38. data/lib/axiom/function/binary.rb +4 -16
  39. data/lib/axiom/function/comparable.rb +1 -1
  40. data/lib/axiom/function/connective/conjunction.rb +1 -1
  41. data/lib/axiom/function/connective/disjunction.rb +1 -1
  42. data/lib/axiom/function/connective/negation.rb +1 -1
  43. data/lib/axiom/function/numeric/exponentiation.rb +1 -1
  44. data/lib/axiom/function/numeric/square_root.rb +1 -1
  45. data/lib/axiom/function/predicate/enumerable.rb +0 -14
  46. data/lib/axiom/function/predicate/exclusion.rb +1 -1
  47. data/lib/axiom/function/predicate/inclusion.rb +1 -1
  48. data/lib/axiom/function/proposition.rb +12 -25
  49. data/lib/axiom/function/unary.rb +92 -106
  50. data/lib/axiom/relation.rb +3 -3
  51. data/lib/axiom/relation/base.rb +15 -0
  52. data/lib/axiom/relation/header.rb +25 -22
  53. data/lib/axiom/relation/index.rb +91 -0
  54. data/lib/axiom/relation/keys.rb +3 -3
  55. data/lib/axiom/relation/materialized.rb +48 -4
  56. data/lib/axiom/relation/operation/binary.rb +5 -5
  57. data/lib/axiom/relation/operation/group.rb +95 -0
  58. data/lib/axiom/relation/operation/limit.rb +15 -15
  59. data/lib/axiom/relation/operation/offset.rb +12 -12
  60. data/lib/axiom/relation/operation/reverse.rb +9 -9
  61. data/lib/axiom/relation/operation/set.rb +1 -1
  62. data/lib/axiom/relation/operation/{order.rb → sorted.rb} +29 -28
  63. data/lib/axiom/relation/operation/{order → sorted}/direction.rb +4 -4
  64. data/lib/axiom/relation/operation/{order → sorted}/direction_set.rb +3 -3
  65. data/lib/axiom/relation/operation/ungroup.rb +82 -0
  66. data/lib/axiom/relation/operation/unwrap.rb +80 -0
  67. data/lib/axiom/relation/operation/wrap.rb +85 -0
  68. data/lib/axiom/relation/proxy.rb +5 -6
  69. data/lib/axiom/relation/variable.rb +1 -2
  70. data/lib/axiom/support/aliasable.rb +3 -5
  71. data/lib/axiom/support/equalizer.rb +10 -12
  72. data/lib/axiom/support/operation/binary.rb +3 -2
  73. data/lib/axiom/support/operation/unary.rb +1 -1
  74. data/lib/axiom/tuple.rb +76 -26
  75. data/lib/axiom/types/relation.rb +13 -0
  76. data/lib/axiom/types/tuple.rb +13 -0
  77. data/lib/axiom/version.rb +1 -1
  78. data/spec/integration/axiom/relation/efficient_enumerable_spec.rb +9 -9
  79. data/spec/integration/axiom/relation/writable_relations_spec.rb +12 -12
  80. data/spec/shared/invertible_method_behaviour.rb +1 -1
  81. data/spec/spec_helper.rb +8 -6
  82. data/spec/unit/axiom/aggregate/call_spec.rb +7 -12
  83. data/spec/unit/axiom/aggregate/class_methods/default_spec.rb +7 -2
  84. data/spec/unit/axiom/aggregate/default_spec.rb +1 -1
  85. data/spec/unit/axiom/aggregate/finalize_spec.rb +1 -1
  86. data/spec/unit/axiom/aggregate/maximum/type_spec.rb +2 -6
  87. data/spec/unit/axiom/aggregate/mean/class_methods/call_spec.rb +2 -2
  88. data/spec/unit/axiom/aggregate/mean/class_methods/finalize_spec.rb +10 -3
  89. data/spec/unit/axiom/aggregate/minimum/type_spec.rb +2 -6
  90. data/spec/unit/axiom/aggregate/sum/default_spec.rb +32 -6
  91. data/spec/unit/axiom/aggregate/sum/type_spec.rb +2 -6
  92. data/spec/unit/axiom/aggregate/variance/class_methods/call_spec.rb +6 -6
  93. data/spec/unit/axiom/algebra/difference/each_spec.rb +3 -3
  94. data/spec/unit/axiom/algebra/extension/class_methods/new_spec.rb +1 -1
  95. data/spec/unit/axiom/algebra/extension/each_spec.rb +2 -2
  96. data/spec/unit/axiom/algebra/intersection/each_spec.rb +3 -3
  97. data/spec/unit/axiom/algebra/join/each_spec.rb +6 -6
  98. data/spec/unit/axiom/algebra/product/each_spec.rb +2 -2
  99. data/spec/unit/axiom/algebra/projection/each_spec.rb +2 -2
  100. data/spec/unit/axiom/algebra/rename/directions_spec.rb +3 -3
  101. data/spec/unit/axiom/algebra/rename/each_spec.rb +2 -2
  102. data/spec/unit/axiom/algebra/restriction/delete_spec.rb +3 -3
  103. data/spec/unit/axiom/algebra/restriction/each_spec.rb +12 -11
  104. data/spec/unit/axiom/algebra/restriction/insert_spec.rb +3 -3
  105. data/spec/unit/axiom/algebra/restriction/methods/restrict_spec.rb +4 -4
  106. data/spec/unit/axiom/algebra/summarization/each_spec.rb +2 -2
  107. data/spec/unit/axiom/algebra/summarization/eql_spec.rb +1 -1
  108. data/spec/unit/axiom/algebra/summarization/summaries/summarize_by_spec.rb +4 -4
  109. data/spec/unit/axiom/algebra/summarization/summaries/to_hash_spec.rb +2 -2
  110. data/spec/unit/axiom/algebra/summarization/summary/summarize_by_spec.rb +1 -1
  111. data/spec/unit/axiom/algebra/union/each_spec.rb +4 -4
  112. data/spec/unit/axiom/aliasable/fixtures/classes.rb +3 -1
  113. data/spec/unit/axiom/aliasable/inheritable_alias_spec.rb +18 -27
  114. data/spec/unit/axiom/attribute/call_spec.rb +1 -1
  115. data/spec/unit/axiom/attribute/class_methods/coerce_spec.rb +57 -51
  116. data/spec/unit/axiom/attribute/class_methods/new_spec.rb +1 -1
  117. data/spec/unit/axiom/attribute/comparable/asc_spec.rb +4 -2
  118. data/spec/unit/axiom/attribute/comparable/desc_spec.rb +4 -2
  119. data/spec/unit/axiom/attribute/comparable/range_spec.rb +20 -0
  120. data/spec/unit/axiom/attribute/eql_spec.rb +1 -1
  121. data/spec/unit/axiom/attribute/equality_operator_spec.rb +1 -1
  122. data/spec/unit/axiom/attribute/include_predicate_spec.rb +1 -1
  123. data/spec/unit/axiom/attribute/name_spec.rb +1 -1
  124. data/spec/unit/axiom/attribute/optional_predicate_spec.rb +1 -1
  125. data/spec/unit/axiom/attribute/relation/class_methods/new_spec.rb +56 -0
  126. data/spec/unit/axiom/attribute/relation/class_methods/type_spec.rb +13 -0
  127. data/spec/unit/axiom/attribute/relation/header_spec.rb +13 -0
  128. data/spec/unit/axiom/attribute/relation/new_relation_spec.rb +15 -0
  129. data/spec/unit/axiom/attribute/rename_spec.rb +1 -1
  130. data/spec/unit/axiom/attribute/required_predicate_spec.rb +1 -1
  131. data/spec/unit/axiom/attribute/tuple/class_methods/new_spec.rb +56 -0
  132. data/spec/unit/axiom/attribute/tuple/class_methods/type_spec.rb +13 -0
  133. data/spec/unit/axiom/attribute/tuple/header_spec.rb +13 -0
  134. data/spec/unit/axiom/equalizer/class_method/new_spec.rb +24 -54
  135. data/spec/unit/axiom/evaluator/context/add_spec.rb +7 -7
  136. data/spec/unit/axiom/evaluator/context/element_reader_spec.rb +4 -4
  137. data/spec/unit/axiom/evaluator/context/functions_spec.rb +1 -1
  138. data/spec/unit/axiom/evaluator/context/method_missing_spec.rb +3 -3
  139. data/spec/unit/axiom/evaluator/context/respond_to_predicate_spec.rb +3 -3
  140. data/spec/unit/axiom/evaluator/context/send_spec.rb +8 -8
  141. data/spec/unit/axiom/function/binary/call_spec.rb +1 -1
  142. data/spec/unit/axiom/function/binary/type_spec.rb +12 -10
  143. data/spec/unit/axiom/function/comparable/class_methods/included_spec.rb +2 -2
  144. data/spec/unit/axiom/function/connective/negation/inverse_spec.rb +1 -1
  145. data/spec/unit/axiom/function/predicate/call_spec.rb +5 -4
  146. data/spec/unit/axiom/function/predicate/enumerable/call_spec.rb +12 -2
  147. data/spec/unit/axiom/function/predicate/eql_spec.rb +4 -3
  148. data/spec/unit/axiom/function/predicate/equality/methods/eq_spec.rb +5 -1
  149. data/spec/unit/axiom/function/predicate/exclusion/class_methods/call_spec.rb +37 -8
  150. data/spec/unit/axiom/function/predicate/exclusion/methods/exclude_spec.rb +6 -2
  151. data/spec/unit/axiom/function/predicate/greater_than/methods/gt_spec.rb +5 -1
  152. data/spec/unit/axiom/function/predicate/greater_than_or_equal_to/methods/gte_spec.rb +5 -1
  153. data/spec/unit/axiom/function/predicate/inclusion/class_methods/call_spec.rb +37 -8
  154. data/spec/unit/axiom/function/predicate/inclusion/methods/include_spec.rb +6 -2
  155. data/spec/unit/axiom/function/predicate/inequality/methods/ne_spec.rb +5 -1
  156. data/spec/unit/axiom/function/predicate/less_than/methods/lt_spec.rb +5 -1
  157. data/spec/unit/axiom/function/predicate/less_than_or_equal_to/methods/lte_spec.rb +5 -1
  158. data/spec/unit/axiom/function/predicate/match/methods/match_spec.rb +7 -3
  159. data/spec/unit/axiom/function/predicate/no_match/methods/no_match_spec.rb +6 -2
  160. data/spec/unit/axiom/function/proposition/call_spec.rb +6 -4
  161. data/spec/unit/axiom/function/proposition/class_methods/{new_spec.rb → coerce_spec.rb} +17 -17
  162. data/spec/unit/axiom/function/proposition/eql_spec.rb +4 -4
  163. data/spec/unit/axiom/function/proposition/equality_operator_spec.rb +3 -3
  164. data/spec/unit/axiom/function/proposition/inverse_spec.rb +4 -4
  165. data/spec/unit/axiom/function/proposition/rename_spec.rb +1 -1
  166. data/spec/unit/axiom/function/type_spec.rb +1 -1
  167. data/spec/unit/axiom/function/unary/call_spec.rb +1 -1
  168. data/spec/unit/axiom/function/unary/callable/call_spec.rb +3 -13
  169. data/spec/unit/axiom/function/unary/callable/included_spec.rb +2 -2
  170. data/spec/unit/axiom/function/unary/type_spec.rb +11 -1
  171. data/spec/unit/axiom/relation/base/eql_spec.rb +1 -1
  172. data/spec/unit/axiom/relation/base/equality_operator_spec.rb +138 -0
  173. data/spec/unit/axiom/relation/class_methods/new_spec.rb +7 -7
  174. data/spec/unit/axiom/relation/directions_spec.rb +2 -2
  175. data/spec/unit/axiom/relation/each_spec.rb +5 -5
  176. data/spec/unit/axiom/relation/element_reader_spec.rb +1 -1
  177. data/spec/unit/axiom/relation/empty/each_spec.rb +1 -1
  178. data/spec/unit/axiom/relation/empty_predicate_spec.rb +1 -1
  179. data/spec/unit/axiom/relation/eql_spec.rb +1 -1
  180. data/spec/unit/axiom/relation/equality_operator_spec.rb +1 -1
  181. data/spec/unit/axiom/relation/header/class_methods/coerce_spec.rb +2 -2
  182. data/spec/unit/axiom/relation/header/class_methods/new_spec.rb +3 -3
  183. data/spec/unit/axiom/relation/header/context_spec.rb +2 -2
  184. data/spec/unit/axiom/relation/header/each_spec.rb +2 -2
  185. data/spec/unit/axiom/relation/header/extend_spec.rb +1 -1
  186. data/spec/unit/axiom/relation/header/{call_spec.rb → fetch_spec.rb} +1 -1
  187. data/spec/unit/axiom/relation/header/project_spec.rb +1 -1
  188. data/spec/unit/axiom/relation/header/rename_spec.rb +19 -5
  189. data/spec/unit/axiom/relation/header/size_spec.rb +14 -0
  190. data/spec/unit/axiom/relation/header_spec.rb +1 -1
  191. data/spec/unit/axiom/relation/index/each_spec.rb +33 -0
  192. data/spec/unit/axiom/relation/index/element_reader_spec.rb +17 -0
  193. data/spec/unit/axiom/relation/index/left_shift_operator_spec.rb +23 -0
  194. data/spec/unit/axiom/relation/index/merge_spec.rb +19 -0
  195. data/spec/unit/axiom/relation/keys/class_methods/coerce_spec.rb +19 -2
  196. data/spec/unit/axiom/relation/keys/class_methods/new_spec.rb +1 -1
  197. data/spec/unit/axiom/relation/keys/each_spec.rb +2 -2
  198. data/spec/unit/axiom/relation/materialize_spec.rb +1 -1
  199. data/spec/unit/axiom/relation/materialized/class_methods/new_spec.rb +30 -4
  200. data/spec/unit/axiom/relation/materialized/directions_spec.rb +1 -1
  201. data/spec/unit/axiom/relation/materialized/materialized_predicate_spec.rb +1 -1
  202. data/spec/unit/axiom/relation/materialized_predicate_spec.rb +1 -1
  203. data/spec/unit/axiom/relation/operation/binary/class_methods/included_spec.rb +2 -2
  204. data/spec/unit/axiom/relation/operation/binary/class_methods/new_spec.rb +6 -6
  205. data/spec/unit/axiom/relation/operation/combination/class_methods/combine_tuples_spec.rb +4 -4
  206. data/spec/unit/axiom/relation/operation/group/each_spec.rb +33 -0
  207. data/spec/unit/axiom/relation/operation/group/header_spec.rb +22 -0
  208. data/spec/unit/axiom/relation/operation/group/methods/group_spec.rb +25 -0
  209. data/spec/unit/axiom/relation/operation/limit/class_methods/new_spec.rb +4 -4
  210. data/spec/unit/axiom/relation/operation/limit/directions_spec.rb +3 -3
  211. data/spec/unit/axiom/relation/operation/limit/each_spec.rb +4 -4
  212. data/spec/unit/axiom/relation/operation/limit/limit_spec.rb +2 -2
  213. data/spec/unit/axiom/relation/operation/offset/class_methods/new_spec.rb +4 -4
  214. data/spec/unit/axiom/relation/operation/offset/directions_spec.rb +3 -3
  215. data/spec/unit/axiom/relation/operation/offset/each_spec.rb +4 -4
  216. data/spec/unit/axiom/relation/operation/offset/offset_spec.rb +2 -2
  217. data/spec/unit/axiom/relation/operation/reverse/class_methods/new_spec.rb +6 -6
  218. data/spec/unit/axiom/relation/operation/reverse/directions_spec.rb +3 -3
  219. data/spec/unit/axiom/relation/operation/reverse/each_spec.rb +4 -4
  220. data/spec/unit/axiom/relation/operation/set/class_methods/included_spec.rb +2 -2
  221. data/spec/unit/axiom/relation/operation/{order → sorted}/ascending/class_methods/call_spec.rb +22 -1
  222. data/spec/unit/axiom/relation/operation/sorted/ascending/class_methods/reverse_spec.rb +11 -0
  223. data/spec/unit/axiom/relation/operation/{order/descending → sorted/ascending}/reverse_spec.rb +2 -2
  224. data/spec/unit/axiom/relation/operation/{order → sorted}/class_methods/new_spec.rb +4 -4
  225. data/spec/unit/axiom/relation/operation/{order → sorted}/delete_spec.rb +12 -6
  226. data/spec/unit/axiom/relation/operation/{order → sorted}/descending/class_methods/call_spec.rb +22 -1
  227. data/spec/unit/axiom/relation/operation/sorted/descending/class_methods/reverse_spec.rb +11 -0
  228. data/spec/unit/axiom/relation/operation/{order/ascending → sorted/descending}/reverse_spec.rb +2 -2
  229. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/attribute_spec.rb +4 -4
  230. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/call_spec.rb +7 -7
  231. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/class_methods/coerce_spec.rb +2 -2
  232. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/eql_predicate_spec.rb +4 -4
  233. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/name_spec.rb +4 -4
  234. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/rename_spec.rb +5 -5
  235. data/spec/unit/axiom/relation/operation/{order → sorted}/direction/reverse_spec.rb +9 -9
  236. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/attributes_spec.rb +1 -1
  237. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/class_methods/coerce_spec.rb +3 -3
  238. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/class_methods/new_spec.rb +1 -1
  239. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/eql_spec.rb +1 -1
  240. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/equality_operator_spec.rb +1 -1
  241. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/project_spec.rb +1 -1
  242. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/rename_spec.rb +1 -1
  243. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/reverse_spec.rb +2 -2
  244. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/sort_tuples_spec.rb +1 -1
  245. data/spec/unit/axiom/relation/operation/{order → sorted}/direction_set/to_ary_spec.rb +1 -1
  246. data/spec/unit/axiom/relation/operation/{order → sorted}/directions_spec.rb +1 -1
  247. data/spec/unit/axiom/relation/operation/{order → sorted}/each_spec.rb +3 -3
  248. data/spec/unit/axiom/relation/operation/{order → sorted}/eql_spec.rb +1 -1
  249. data/spec/unit/axiom/relation/operation/{order → sorted}/header_spec.rb +1 -1
  250. data/spec/unit/axiom/relation/operation/{order → sorted}/insert_spec.rb +12 -6
  251. data/spec/unit/axiom/relation/operation/{order → sorted}/methods/sort_by_spec.rb +24 -24
  252. data/spec/unit/axiom/relation/operation/sorted/methods/sort_spec.rb +19 -0
  253. data/spec/unit/axiom/relation/operation/ungroup/each_spec.rb +33 -0
  254. data/spec/unit/axiom/relation/operation/ungroup/header_spec.rb +19 -0
  255. data/spec/unit/axiom/relation/operation/ungroup/methods/ungroup_spec.rb +21 -0
  256. data/spec/unit/axiom/relation/operation/unwrap/each_spec.rb +33 -0
  257. data/spec/unit/axiom/relation/operation/unwrap/header_spec.rb +19 -0
  258. data/spec/unit/axiom/relation/operation/unwrap/methods/unwrap_spec.rb +21 -0
  259. data/spec/unit/axiom/relation/operation/wrap/each_spec.rb +33 -0
  260. data/spec/unit/axiom/relation/operation/wrap/header_spec.rb +22 -0
  261. data/spec/unit/axiom/relation/operation/wrap/methods/wrap_spec.rb +25 -0
  262. data/spec/unit/axiom/relation/proxy/each_spec.rb +2 -2
  263. data/spec/unit/axiom/relation/proxy/respond_to_predicate_spec.rb +48 -12
  264. data/spec/unit/axiom/relation/replace_spec.rb +8 -8
  265. data/spec/unit/axiom/tuple/class_methods/coerce_spec.rb +7 -1
  266. data/spec/unit/axiom/tuple/{call_spec.rb → fetch_spec.rb} +1 -1
  267. data/spec/unit/axiom/tuple/inspect_spec.rb +14 -0
  268. data/spec/unit/axiom/tuple/rename_spec.rb +17 -0
  269. data/spec/unit/axiom/tuple/size_spec.rb +14 -0
  270. data/spec/unit/axiom/tuple/to_ary_spec.rb +22 -5
  271. data/spec/unit/axiom/tuple/to_hash_spec.rb +14 -0
  272. data/spec/unit/axiom/types/relation/class_methods/primitive_spec.rb +13 -0
  273. data/spec/unit/axiom/types/tuple/class_methods/primitive_spec.rb +13 -0
  274. data/spec/unit/axiom/visitable/accept_spec.rb +1 -1
  275. data/spec/unit/date/pred_spec.rb +1 -1
  276. data/spec/unit/time/pred_spec.rb +1 -1
  277. metadata +631 -107
  278. data/spec/unit/axiom/aggregate/hash_spec.rb +0 -15
  279. data/spec/unit/axiom/algebra/extension/hash_spec.rb +0 -15
  280. data/spec/unit/axiom/algebra/projection/hash_spec.rb +0 -16
  281. data/spec/unit/axiom/algebra/rename/aliases/hash_spec.rb +0 -15
  282. data/spec/unit/axiom/algebra/rename/hash_spec.rb +0 -15
  283. data/spec/unit/axiom/algebra/restriction/hash_spec.rb +0 -15
  284. data/spec/unit/axiom/algebra/summarization/hash_spec.rb +0 -16
  285. data/spec/unit/axiom/attribute/hash_spec.rb +0 -21
  286. data/spec/unit/axiom/attribute/numeric/hash_spec.rb +0 -17
  287. data/spec/unit/axiom/attribute/string/hash_spec.rb +0 -25
  288. data/spec/unit/axiom/equalizer/methods/eql_spec.rb +0 -49
  289. data/spec/unit/axiom/equalizer/methods/equality_operator_spec.rb +0 -85
  290. data/spec/unit/axiom/function/binary/invertible/class_methods/included_spec.rb +0 -29
  291. data/spec/unit/axiom/function/predicate/hash_spec.rb +0 -16
  292. data/spec/unit/axiom/function/predicate/inverse_spec.rb +0 -17
  293. data/spec/unit/axiom/function/proposition/hash_spec.rb +0 -14
  294. data/spec/unit/axiom/function/unary/hash_spec.rb +0 -18
  295. data/spec/unit/axiom/function/unary/invertible/class_methods/included_spec.rb +0 -29
  296. data/spec/unit/axiom/operation/binary/hash_spec.rb +0 -16
  297. data/spec/unit/axiom/operation/unary/hash_spec.rb +0 -15
  298. data/spec/unit/axiom/relation/base/hash_spec.rb +0 -16
  299. data/spec/unit/axiom/relation/hash_spec.rb +0 -19
  300. data/spec/unit/axiom/relation/header/hash_spec.rb +0 -15
  301. data/spec/unit/axiom/relation/operation/limit/hash_spec.rb +0 -16
  302. data/spec/unit/axiom/relation/operation/offset/hash_spec.rb +0 -16
  303. data/spec/unit/axiom/relation/operation/order/ascending/class_methods/reverse_spec.rb +0 -11
  304. data/spec/unit/axiom/relation/operation/order/descending/class_methods/reverse_spec.rb +0 -11
  305. data/spec/unit/axiom/relation/operation/order/direction/hash_spec.rb +0 -15
  306. data/spec/unit/axiom/relation/operation/order/direction_set/hash_spec.rb +0 -15
  307. data/spec/unit/axiom/relation/operation/order/hash_spec.rb +0 -15
  308. data/spec/unit/axiom/relation/operation/order/methods/sort_spec.rb +0 -19
  309. data/spec/unit/axiom/relation/proxy/hash_spec.rb +0 -26
  310. data/spec/unit/axiom/relation/proxy/method_missing_spec.rb +0 -24
  311. data/spec/unit/axiom/tuple/hash_spec.rb +0 -15
@@ -7,10 +7,10 @@ module Axiom
7
7
  module Proxy
8
8
  include Equalizer.new(:relation)
9
9
 
10
- # Relation methods to proxy
11
- ENUMERABLE_METHODS = Enumerable.public_instance_methods.map(&:to_s).freeze
12
10
  PROXY_METHODS = %w[header each empty? materialized?].freeze
13
- RELATION_METHODS = %w[take drop sort_by].freeze
11
+ ENUMERABLE_METHODS = Enumerable.public_instance_methods.map(&:to_s).freeze
12
+ RELATION_METHODS = Relation.public_instance_methods.map(&:to_s).freeze
13
+ REMOVE_METHODS = PROXY_METHODS | (ENUMERABLE_METHODS - RELATION_METHODS)
14
14
 
15
15
  # Hook called when module is included
16
16
  #
@@ -21,9 +21,8 @@ module Axiom
21
21
  #
22
22
  # @api private
23
23
  def self.included(descendant)
24
- descendant.class_eval do
25
- undef_method(*PROXY_METHODS | ENUMERABLE_METHODS - RELATION_METHODS)
26
- end
24
+ super
25
+ descendant.class_eval { undef_method(*REMOVE_METHODS) }
27
26
  end
28
27
 
29
28
  private_class_method :included
@@ -99,8 +99,6 @@ module Axiom
99
99
  # A materialized relation variable
100
100
  class Materialized < self
101
101
 
102
- private
103
-
104
102
  # Mutate and materialize the relation variable
105
103
  #
106
104
  # @return [undefined]
@@ -110,6 +108,7 @@ module Axiom
110
108
  super
111
109
  @relation = relation.materialize
112
110
  end
111
+ private :mutate_relation
113
112
 
114
113
  end # class Materialized
115
114
  end # class Variable
@@ -33,11 +33,9 @@ module Axiom
33
33
  #
34
34
  # @api private
35
35
  def define_inheritable_alias_method(new_method, original_method)
36
- class_eval <<-RUBY, __FILE__, __LINE__ + 1
37
- def #{new_method}(*args, &block) # def |(*args, &block)
38
- self.#{original_method}(*args, &block) # self.union(*args, &block)
39
- end # end
40
- RUBY
36
+ define_method(new_method) do |*args, &block|
37
+ public_send(original_method, *args, &block)
38
+ end
41
39
  end
42
40
 
43
41
  end # module Aliasable
@@ -5,25 +5,23 @@ module Axiom
5
5
  # Define equality, equivalence and inspection methods
6
6
  class Equalizer < ::Equalizer
7
7
 
8
- # Include the #eql? and #== methods
8
+ # Hook called when module is included
9
9
  #
10
- # @return [undefined]
10
+ # @param [Module] descendant
11
+ # the module or class including Equalizer
11
12
  #
12
- # @api private
13
+ # @return [self]
13
14
  #
14
- # TODO: this monkey-patches equalizer and should be removed
15
- def initialize(*keys)
16
- @keys = keys
17
- define_methods
18
- include_comparison_methods
19
-
20
- module_eval do
15
+ # @api private
16
+ def included(descendant)
17
+ super
18
+ descendant.module_eval do
21
19
  include Adamantium
22
20
  memoize :hash
23
21
  end
24
-
25
- freeze
26
22
  end
27
23
 
24
+ private :included
25
+
28
26
  end # class Equalizer
29
27
  end # module Axiom
@@ -36,8 +36,9 @@ module Axiom
36
36
  #
37
37
  # @api private
38
38
  def initialize(left, right)
39
- @left = freeze_object(left)
40
- @right = freeze_object(right)
39
+ freezer = self.class.freezer
40
+ @left = freezer.call(left)
41
+ @right = freezer.call(right)
41
42
  end
42
43
 
43
44
  end # module Binary
@@ -24,7 +24,7 @@ module Axiom
24
24
  #
25
25
  # @api private
26
26
  def initialize(operand)
27
- @operand = freeze_object(operand)
27
+ @operand = self.class.freezer.call(operand)
28
28
  end
29
29
 
30
30
  end # module Unary
@@ -7,7 +7,7 @@ module Axiom
7
7
  extend Aliasable
8
8
  include Equalizer.new(:data)
9
9
 
10
- inheritable_alias(:[] => :call)
10
+ inheritable_alias(:[] => :fetch)
11
11
 
12
12
  # The tuple header
13
13
  #
@@ -23,6 +23,16 @@ module Axiom
23
23
  # @api private
24
24
  attr_reader :data
25
25
 
26
+ # Convert the Tuple into an Array
27
+ #
28
+ # @example
29
+ # array = tuple.to_ary
30
+ #
31
+ # @return [Array]
32
+ #
33
+ # @api public
34
+ attr_reader :to_ary
35
+
26
36
  # Initialize a Tuple
27
37
  #
28
38
  # @param [Header] header
@@ -35,7 +45,8 @@ module Axiom
35
45
  # @api private
36
46
  def initialize(header, data)
37
47
  @header = header
38
- @data = Hash[header.zip(data)]
48
+ @to_ary = self.class.freezer.call(data)
49
+ @data = Hash[header.zip(@to_ary)]
39
50
  end
40
51
 
41
52
  # Lookup a value in the tuple given an attribute
@@ -48,8 +59,8 @@ module Axiom
48
59
  # @return [Object]
49
60
  #
50
61
  # @api public
51
- def call(attribute)
52
- data.fetch(header.call(attribute))
62
+ def fetch(attribute)
63
+ data.fetch(header.fetch(attribute))
53
64
  end
54
65
 
55
66
  # Return a tuple with only the specified attributes
@@ -67,41 +78,55 @@ module Axiom
67
78
  self.class.new(header, data.values_at(*header))
68
79
  end
69
80
 
70
- # Append values to the tuple and return a new tuple
81
+ # Extend a tuple with function results
71
82
  #
72
83
  # @example
73
- # new_tuple = tuple.join(header, [1, 2, 3])
84
+ # new_tuple = tuple.extend(header, [func1, func2])
74
85
  #
75
86
  # @param [Header] header
76
87
  # the attributes to include in the tuple
77
- # @param [Array] values
78
- # the values to append
88
+ # @param [Array<Object>] extensions
89
+ # the functions to extend the tuple with
79
90
  #
80
91
  # @return [Tuple]
81
92
  #
82
93
  # @api public
83
- def join(header, values)
84
- self.class.new(header, to_ary + values)
94
+ def extend(header, extensions)
95
+ join(
96
+ header,
97
+ extensions.map { |extension| Function.extract_value(extension, self) }
98
+ )
85
99
  end
86
100
 
87
- # Extend a tuple with function results
101
+ # Rename a tuple to use a new header
88
102
  #
89
103
  # @example
90
- # new_tuple = tuple.extend(header, [func1, func2])
104
+ # new_tuple = tuple.rename(header)
105
+ #
106
+ # @param [Header] header
107
+ #
108
+ # @return [Tuple]
109
+ #
110
+ # @api public
111
+ def rename(header)
112
+ self.class.new(header, to_ary)
113
+ end
114
+
115
+ # Append values to the tuple and return a new tuple
116
+ #
117
+ # @example
118
+ # new_tuple = tuple.join(header, [1, 2, 3])
91
119
  #
92
120
  # @param [Header] header
93
121
  # the attributes to include in the tuple
94
- # @param [Array<Object>] extensions
95
- # the functions to extend the tuple with
122
+ # @param [Array] values
123
+ # the values to append
96
124
  #
97
125
  # @return [Tuple]
98
126
  #
99
127
  # @api public
100
- def extend(header, extensions)
101
- join(
102
- header,
103
- extensions.map { |extension| Function.extract_value(extension, self) }
104
- )
128
+ def join(header, values)
129
+ self.class.new(header, to_ary + values)
105
130
  end
106
131
 
107
132
  # Return the predicate matching the tuple
@@ -115,16 +140,37 @@ module Axiom
115
140
  end
116
141
  end
117
142
 
118
- # Convert the Tuple into an Array
143
+ # Coerce the tuple into a Hash
119
144
  #
120
145
  # @example
121
- # array = tuple.to_ary
146
+ # tuple.to_hash # => data as a Hash
122
147
  #
123
- # @return [Array]
148
+ # @return [Hash{Symbol => Object}]
149
+ #
150
+ # @api public
151
+ def to_hash
152
+ Hash[data.map { |attribute, value| [attribute.name, value] }]
153
+ end
154
+
155
+ # The number of attributes
156
+ #
157
+ # @return [Integer]
124
158
  #
125
159
  # @api public
126
- def to_ary
127
- data.values_at(*header).freeze
160
+ def size
161
+ header.size
162
+ end
163
+
164
+ # Display the tuple data in a human readable form
165
+ #
166
+ # @example
167
+ # tuple.inspect # => data as a String
168
+ #
169
+ # @return [String]
170
+ #
171
+ # @api public
172
+ def inspect
173
+ to_hash.inspect
128
174
  end
129
175
 
130
176
  private
@@ -152,10 +198,14 @@ module Axiom
152
198
  #
153
199
  # @api private
154
200
  def self.coerce(header, object)
155
- object.kind_of?(Tuple) ? object : new(header, object.to_ary)
201
+ if object.kind_of?(Tuple) || header.size != object.to_ary.size
202
+ object
203
+ else
204
+ new(header, object)
205
+ end
156
206
  end
157
207
 
158
- memoize :predicate, :to_ary
208
+ memoize :predicate, :to_hash, :inspect
159
209
 
160
210
  end # class Tuple
161
211
  end # module Axiom
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module Types
5
+
6
+ # Represents a relation type
7
+ class Relation < Object
8
+
9
+ primitive Axiom::Relation
10
+
11
+ end # class Relation
12
+ end # module Types
13
+ end # module Axiom
@@ -0,0 +1,13 @@
1
+ # encoding: utf-8
2
+
3
+ module Axiom
4
+ module Types
5
+
6
+ # Represents a tuple type
7
+ class Tuple < Object
8
+
9
+ primitive Axiom::Tuple
10
+
11
+ end # class Tuple
12
+ end # module Types
13
+ end # module Axiom
@@ -3,6 +3,6 @@
3
3
  module Axiom
4
4
 
5
5
  # Gem version
6
- VERSION = '0.1.1'.freeze
6
+ VERSION = '0.2.0'.freeze
7
7
 
8
8
  end # module Axiom
@@ -26,17 +26,17 @@ describe Relation do
26
26
 
27
27
  it '#project should be efficient' do
28
28
  projected = relation.project([:id])
29
- sample(projected).should == [[0], [1], [2], [3], [4]]
29
+ expect(sample(projected)).to eq([[0], [1], [2], [3], [4]])
30
30
  end
31
31
 
32
32
  it '#restrict should be efficient' do
33
33
  restricted = relation.restrict { |r| r.id.gt(5) }
34
- sample(restricted).should == [[6], [7], [8], [9], [10]]
34
+ expect(sample(restricted)).to eq([[6], [7], [8], [9], [10]])
35
35
  end
36
36
 
37
37
  it '#rename should be efficient' do
38
38
  renamed = relation.rename(id: :other_id)
39
- sample(renamed).should == [[0], [1], [2], [3], [4]]
39
+ expect(sample(renamed)).to eq([[0], [1], [2], [3], [4]])
40
40
  end
41
41
 
42
42
  describe '#join should be efficient' do
@@ -45,13 +45,13 @@ describe Relation do
45
45
  it 'has an infinite left relation' do
46
46
  pending 'Change #join to handle infinite sets'
47
47
  join = other.join(relation)
48
- sample(join).should == [[1, 'Dan Kubb']]
48
+ expect(sample(join)).to eq([[1, 'Dan Kubb']])
49
49
  end
50
50
 
51
51
  it 'has an infinite right relation' do
52
52
  pending 'Change #join to handle infinite sets'
53
53
  join = relation.join(other)
54
- sample(join).should == [[1, 'Dan Kubb']]
54
+ expect(sample(join)).to eq([[1, 'Dan Kubb']])
55
55
  end
56
56
  end
57
57
 
@@ -60,24 +60,24 @@ describe Relation do
60
60
 
61
61
  it 'has an infinite left relation' do
62
62
  product = relation.product(other)
63
- sample(product).should == [[0, 'Dan Kubb'], [1, 'Dan Kubb'], [2, 'Dan Kubb'], [3, 'Dan Kubb'], [4, 'Dan Kubb']]
63
+ expect(sample(product)).to eq([[0, 'Dan Kubb'], [1, 'Dan Kubb'], [2, 'Dan Kubb'], [3, 'Dan Kubb'], [4, 'Dan Kubb']])
64
64
  end
65
65
 
66
66
  it 'has an infinite right relation' do
67
67
  pending 'Change #product to handle infinite sets'
68
68
  product = other.product(relation)
69
- sample(product).should == [[0, 'Dan Kubb'], [1, 'Dan Kubb'], [2, 'Dan Kubb'], [3, 'Dan Kubb'], [4, 'Dan Kubb']]
69
+ expect(sample(product)).to eq([[0, 'Dan Kubb'], [1, 'Dan Kubb'], [2, 'Dan Kubb'], [3, 'Dan Kubb'], [4, 'Dan Kubb']])
70
70
  end
71
71
  end
72
72
 
73
73
  it '#difference should be efficient' do
74
74
  difference = relation.difference(Relation.new(relation.header, [[1]]))
75
- sample(difference).should == [[0], [2], [3], [4], [5]]
75
+ expect(sample(difference)).to eq([[0], [2], [3], [4], [5]])
76
76
  end
77
77
 
78
78
  it '#union should be efficient' do
79
79
  union = relation.union(Relation.new(relation.header, [[1]]))
80
- sample(union).should == [[0], [1], [2], [3], [4]]
80
+ expect(sample(union)).to eq([[0], [1], [2], [3], [4]])
81
81
  end
82
82
  end
83
83
  end
@@ -14,55 +14,55 @@ describe Relation do
14
14
  it 'Rename#insert and #delete of a disjoint relation are symmetrical' do
15
15
  rename = relation.rename(id: :other_id)
16
16
  other = [[4, 'John Doe']]
17
- rename.insert(other).delete(other).should == rename
17
+ expect(rename.insert(other).delete(other)).to eq(rename)
18
18
  end
19
19
 
20
20
  it 'Projection#insert and #delete of a disjoint relation are symmetrical' do
21
21
  projection = relation.project([:id])
22
22
  other = [[4]]
23
- projection.insert(other).delete(other).should == projection
23
+ expect(projection.insert(other).delete(other)).to eq(projection)
24
24
  end
25
25
 
26
26
  it 'Extension#insert and #delete of a disjoint relation are symmetrical' do
27
27
  extension = relation.extend { |r| r.add(:age, 30) }
28
28
  other = Relation.new(relation.header, [[4, 'John Doe']]).extend(extension.extensions)
29
- extension.insert(other).delete(other).should == extension
29
+ expect(extension.insert(other).delete(other)).to eq(extension)
30
30
  end
31
31
 
32
32
  it 'Restriction#insert and #delete of a disjoint relation are symmetrical' do
33
33
  restriction = relation.restrict { |r| r.id.gte(1) }
34
34
  other = [[4, 'John Doe']]
35
- restriction.insert(other).delete(other).should == restriction
35
+ expect(restriction.insert(other).delete(other)).to eq(restriction)
36
36
  end
37
37
 
38
38
  it 'Join#insert and #delete of a disjoint relation are symmetrical' do
39
39
  join = relation + Relation.new([[:id, Integer]], [[1]])
40
40
  other = [[4, 'John Doe']]
41
- join.insert(other).delete(other).should == join
41
+ expect(join.insert(other).delete(other)).to eq(join)
42
42
  end
43
43
 
44
44
  it 'Difference#insert and #delete of a disjoint relation are symmetrical' do
45
45
  difference = relation - relation
46
46
  other = [[4, 'John Doe']]
47
- difference.insert(other).delete(other).should == difference
47
+ expect(difference.insert(other).delete(other)).to eq(difference)
48
48
  end
49
49
 
50
50
  it 'Union#insert and #delete of a disjoint relation are symmetrical' do
51
51
  union = relation | relation
52
52
  other = [[4, 'John Doe']]
53
- union.insert(other).delete(other).should == union
53
+ expect(union.insert(other).delete(other)).to eq(union)
54
54
  end
55
55
 
56
56
  it 'Intersection#insert and #delete of a disjoint relation are symmetrical' do
57
57
  intersection = relation & relation
58
58
  other = [[4, 'John Doe']]
59
- intersection.insert(other).delete(other).should == intersection
59
+ expect(intersection.insert(other).delete(other)).to eq(intersection)
60
60
  end
61
61
 
62
- it 'Order#insert and #delete of a disjoint relation are symmetrical' do
63
- order = relation.sort_by(relation.header)
64
- other = Relation.new(relation.header, [[4, 'John Doe']]).sort_by(relation.header)
65
- order.insert(other).delete(other).should == order
62
+ it 'Sorted#insert and #delete of a disjoint relation are symmetrical' do
63
+ sorted = relation.sort_by(relation.header)
64
+ other = Relation.new(relation.header, [[4, 'John Doe']]).sort_by(relation.header)
65
+ expect(sorted.insert(other).delete(other)).to eq(sorted)
66
66
  end
67
67
  end
68
68
  end