avatar-o-matic 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (352) hide show
  1. checksums.yaml +7 -0
  2. data/data/images/female/background1.png +0 -0
  3. data/data/images/female/background2.png +0 -0
  4. data/data/images/female/background3.png +0 -0
  5. data/data/images/female/background4.png +0 -0
  6. data/data/images/female/background5.png +0 -0
  7. data/data/images/female/clothes1.png +0 -0
  8. data/data/images/female/clothes10.png +0 -0
  9. data/data/images/female/clothes11.png +0 -0
  10. data/data/images/female/clothes12.png +0 -0
  11. data/data/images/female/clothes13.png +0 -0
  12. data/data/images/female/clothes14.png +0 -0
  13. data/data/images/female/clothes15.png +0 -0
  14. data/data/images/female/clothes16.png +0 -0
  15. data/data/images/female/clothes17.png +0 -0
  16. data/data/images/female/clothes18.png +0 -0
  17. data/data/images/female/clothes19.png +0 -0
  18. data/data/images/female/clothes2.png +0 -0
  19. data/data/images/female/clothes20.png +0 -0
  20. data/data/images/female/clothes21.png +0 -0
  21. data/data/images/female/clothes22.png +0 -0
  22. data/data/images/female/clothes23.png +0 -0
  23. data/data/images/female/clothes24.png +0 -0
  24. data/data/images/female/clothes25.png +0 -0
  25. data/data/images/female/clothes26.png +0 -0
  26. data/data/images/female/clothes27.png +0 -0
  27. data/data/images/female/clothes28.png +0 -0
  28. data/data/images/female/clothes29.png +0 -0
  29. data/data/images/female/clothes3.png +0 -0
  30. data/data/images/female/clothes30.png +0 -0
  31. data/data/images/female/clothes31.png +0 -0
  32. data/data/images/female/clothes32.png +0 -0
  33. data/data/images/female/clothes33.png +0 -0
  34. data/data/images/female/clothes34.png +0 -0
  35. data/data/images/female/clothes35.png +0 -0
  36. data/data/images/female/clothes36.png +0 -0
  37. data/data/images/female/clothes37.png +0 -0
  38. data/data/images/female/clothes38.png +0 -0
  39. data/data/images/female/clothes39.png +0 -0
  40. data/data/images/female/clothes4.png +0 -0
  41. data/data/images/female/clothes40.png +0 -0
  42. data/data/images/female/clothes41.png +0 -0
  43. data/data/images/female/clothes42.png +0 -0
  44. data/data/images/female/clothes43.png +0 -0
  45. data/data/images/female/clothes44.png +0 -0
  46. data/data/images/female/clothes45.png +0 -0
  47. data/data/images/female/clothes46.png +0 -0
  48. data/data/images/female/clothes47.png +0 -0
  49. data/data/images/female/clothes48.png +0 -0
  50. data/data/images/female/clothes49.png +0 -0
  51. data/data/images/female/clothes5.png +0 -0
  52. data/data/images/female/clothes50.png +0 -0
  53. data/data/images/female/clothes51.png +0 -0
  54. data/data/images/female/clothes52.png +0 -0
  55. data/data/images/female/clothes53.png +0 -0
  56. data/data/images/female/clothes54.png +0 -0
  57. data/data/images/female/clothes55.png +0 -0
  58. data/data/images/female/clothes56.png +0 -0
  59. data/data/images/female/clothes57.png +0 -0
  60. data/data/images/female/clothes58.png +0 -0
  61. data/data/images/female/clothes59.png +0 -0
  62. data/data/images/female/clothes6.png +0 -0
  63. data/data/images/female/clothes7.png +0 -0
  64. data/data/images/female/clothes8.png +0 -0
  65. data/data/images/female/clothes9.png +0 -0
  66. data/data/images/female/eye1.png +0 -0
  67. data/data/images/female/eye10.png +0 -0
  68. data/data/images/female/eye11.png +0 -0
  69. data/data/images/female/eye12.png +0 -0
  70. data/data/images/female/eye13.png +0 -0
  71. data/data/images/female/eye14.png +0 -0
  72. data/data/images/female/eye15.png +0 -0
  73. data/data/images/female/eye16.png +0 -0
  74. data/data/images/female/eye17.png +0 -0
  75. data/data/images/female/eye18.png +0 -0
  76. data/data/images/female/eye19.png +0 -0
  77. data/data/images/female/eye2.png +0 -0
  78. data/data/images/female/eye20.png +0 -0
  79. data/data/images/female/eye21.png +0 -0
  80. data/data/images/female/eye22.png +0 -0
  81. data/data/images/female/eye23.png +0 -0
  82. data/data/images/female/eye24.png +0 -0
  83. data/data/images/female/eye25.png +0 -0
  84. data/data/images/female/eye26.png +0 -0
  85. data/data/images/female/eye27.png +0 -0
  86. data/data/images/female/eye28.png +0 -0
  87. data/data/images/female/eye29.png +0 -0
  88. data/data/images/female/eye3.png +0 -0
  89. data/data/images/female/eye30.png +0 -0
  90. data/data/images/female/eye31.png +0 -0
  91. data/data/images/female/eye32.png +0 -0
  92. data/data/images/female/eye33.png +0 -0
  93. data/data/images/female/eye34.png +0 -0
  94. data/data/images/female/eye35.png +0 -0
  95. data/data/images/female/eye36.png +0 -0
  96. data/data/images/female/eye37.png +0 -0
  97. data/data/images/female/eye38.png +0 -0
  98. data/data/images/female/eye39.png +0 -0
  99. data/data/images/female/eye4.png +0 -0
  100. data/data/images/female/eye40.png +0 -0
  101. data/data/images/female/eye41.png +0 -0
  102. data/data/images/female/eye42.png +0 -0
  103. data/data/images/female/eye43.png +0 -0
  104. data/data/images/female/eye44.png +0 -0
  105. data/data/images/female/eye45.png +0 -0
  106. data/data/images/female/eye46.png +0 -0
  107. data/data/images/female/eye47.png +0 -0
  108. data/data/images/female/eye48.png +0 -0
  109. data/data/images/female/eye49.png +0 -0
  110. data/data/images/female/eye5.png +0 -0
  111. data/data/images/female/eye50.png +0 -0
  112. data/data/images/female/eye51.png +0 -0
  113. data/data/images/female/eye52.png +0 -0
  114. data/data/images/female/eye53.png +0 -0
  115. data/data/images/female/eye6.png +0 -0
  116. data/data/images/female/eye7.png +0 -0
  117. data/data/images/female/eye8.png +0 -0
  118. data/data/images/female/eye9.png +0 -0
  119. data/data/images/female/face1.png +0 -0
  120. data/data/images/female/face2.png +0 -0
  121. data/data/images/female/face3.png +0 -0
  122. data/data/images/female/face4.png +0 -0
  123. data/data/images/female/head1.png +0 -0
  124. data/data/images/female/head10.png +0 -0
  125. data/data/images/female/head11.png +0 -0
  126. data/data/images/female/head12.png +0 -0
  127. data/data/images/female/head13.png +0 -0
  128. data/data/images/female/head14.png +0 -0
  129. data/data/images/female/head15.png +0 -0
  130. data/data/images/female/head16.png +0 -0
  131. data/data/images/female/head17.png +0 -0
  132. data/data/images/female/head18.png +0 -0
  133. data/data/images/female/head19.png +0 -0
  134. data/data/images/female/head2.png +0 -0
  135. data/data/images/female/head20.png +0 -0
  136. data/data/images/female/head21.png +0 -0
  137. data/data/images/female/head22.png +0 -0
  138. data/data/images/female/head23.png +0 -0
  139. data/data/images/female/head24.png +0 -0
  140. data/data/images/female/head25.png +0 -0
  141. data/data/images/female/head26.png +0 -0
  142. data/data/images/female/head27.png +0 -0
  143. data/data/images/female/head28.png +0 -0
  144. data/data/images/female/head29.png +0 -0
  145. data/data/images/female/head3.png +0 -0
  146. data/data/images/female/head30.png +0 -0
  147. data/data/images/female/head31.png +0 -0
  148. data/data/images/female/head32.png +0 -0
  149. data/data/images/female/head33.png +0 -0
  150. data/data/images/female/head34.png +0 -0
  151. data/data/images/female/head4.png +0 -0
  152. data/data/images/female/head5.png +0 -0
  153. data/data/images/female/head6.png +0 -0
  154. data/data/images/female/head7.png +0 -0
  155. data/data/images/female/head8.png +0 -0
  156. data/data/images/female/head9.png +0 -0
  157. data/data/images/female/mouth1.png +0 -0
  158. data/data/images/female/mouth10.png +0 -0
  159. data/data/images/female/mouth11.png +0 -0
  160. data/data/images/female/mouth12.png +0 -0
  161. data/data/images/female/mouth13.png +0 -0
  162. data/data/images/female/mouth14.png +0 -0
  163. data/data/images/female/mouth15.png +0 -0
  164. data/data/images/female/mouth16.png +0 -0
  165. data/data/images/female/mouth17.png +0 -0
  166. data/data/images/female/mouth2.png +0 -0
  167. data/data/images/female/mouth3.png +0 -0
  168. data/data/images/female/mouth4.png +0 -0
  169. data/data/images/female/mouth5.png +0 -0
  170. data/data/images/female/mouth6.png +0 -0
  171. data/data/images/female/mouth7.png +0 -0
  172. data/data/images/female/mouth8.png +0 -0
  173. data/data/images/female/mouth9.png +0 -0
  174. data/data/images/male/background1.png +0 -0
  175. data/data/images/male/background2.png +0 -0
  176. data/data/images/male/background3.png +0 -0
  177. data/data/images/male/background4.png +0 -0
  178. data/data/images/male/background5.png +0 -0
  179. data/data/images/male/clothes1.png +0 -0
  180. data/data/images/male/clothes10.png +0 -0
  181. data/data/images/male/clothes11.png +0 -0
  182. data/data/images/male/clothes12.png +0 -0
  183. data/data/images/male/clothes13.png +0 -0
  184. data/data/images/male/clothes14.png +0 -0
  185. data/data/images/male/clothes15.png +0 -0
  186. data/data/images/male/clothes16.png +0 -0
  187. data/data/images/male/clothes17.png +0 -0
  188. data/data/images/male/clothes18.png +0 -0
  189. data/data/images/male/clothes19.png +0 -0
  190. data/data/images/male/clothes2.png +0 -0
  191. data/data/images/male/clothes20.png +0 -0
  192. data/data/images/male/clothes21.png +0 -0
  193. data/data/images/male/clothes22.png +0 -0
  194. data/data/images/male/clothes23.png +0 -0
  195. data/data/images/male/clothes24.png +0 -0
  196. data/data/images/male/clothes25.png +0 -0
  197. data/data/images/male/clothes26.png +0 -0
  198. data/data/images/male/clothes27.png +0 -0
  199. data/data/images/male/clothes28.png +0 -0
  200. data/data/images/male/clothes29.png +0 -0
  201. data/data/images/male/clothes3.png +0 -0
  202. data/data/images/male/clothes30.png +0 -0
  203. data/data/images/male/clothes31.png +0 -0
  204. data/data/images/male/clothes32.png +0 -0
  205. data/data/images/male/clothes33.png +0 -0
  206. data/data/images/male/clothes34.png +0 -0
  207. data/data/images/male/clothes35.png +0 -0
  208. data/data/images/male/clothes36.png +0 -0
  209. data/data/images/male/clothes37.png +0 -0
  210. data/data/images/male/clothes38.png +0 -0
  211. data/data/images/male/clothes39.png +0 -0
  212. data/data/images/male/clothes4.png +0 -0
  213. data/data/images/male/clothes40.png +0 -0
  214. data/data/images/male/clothes41.png +0 -0
  215. data/data/images/male/clothes42.png +0 -0
  216. data/data/images/male/clothes43.png +0 -0
  217. data/data/images/male/clothes44.png +0 -0
  218. data/data/images/male/clothes45.png +0 -0
  219. data/data/images/male/clothes46.png +0 -0
  220. data/data/images/male/clothes47.png +0 -0
  221. data/data/images/male/clothes48.png +0 -0
  222. data/data/images/male/clothes49.png +0 -0
  223. data/data/images/male/clothes5.png +0 -0
  224. data/data/images/male/clothes50.png +0 -0
  225. data/data/images/male/clothes51.png +0 -0
  226. data/data/images/male/clothes52.png +0 -0
  227. data/data/images/male/clothes53.png +0 -0
  228. data/data/images/male/clothes54.png +0 -0
  229. data/data/images/male/clothes55.png +0 -0
  230. data/data/images/male/clothes56.png +0 -0
  231. data/data/images/male/clothes57.png +0 -0
  232. data/data/images/male/clothes58.png +0 -0
  233. data/data/images/male/clothes59.png +0 -0
  234. data/data/images/male/clothes6.png +0 -0
  235. data/data/images/male/clothes60.png +0 -0
  236. data/data/images/male/clothes61.png +0 -0
  237. data/data/images/male/clothes62.png +0 -0
  238. data/data/images/male/clothes63.png +0 -0
  239. data/data/images/male/clothes64.png +0 -0
  240. data/data/images/male/clothes65.png +0 -0
  241. data/data/images/male/clothes66.png +0 -0
  242. data/data/images/male/clothes7.png +0 -0
  243. data/data/images/male/clothes8.png +0 -0
  244. data/data/images/male/clothes9.png +0 -0
  245. data/data/images/male/eye1.png +0 -0
  246. data/data/images/male/eye10.png +0 -0
  247. data/data/images/male/eye11.png +0 -0
  248. data/data/images/male/eye12.png +0 -0
  249. data/data/images/male/eye13.png +0 -0
  250. data/data/images/male/eye14.png +0 -0
  251. data/data/images/male/eye15.png +0 -0
  252. data/data/images/male/eye16.png +0 -0
  253. data/data/images/male/eye17.png +0 -0
  254. data/data/images/male/eye18.png +0 -0
  255. data/data/images/male/eye19.png +0 -0
  256. data/data/images/male/eye2.png +0 -0
  257. data/data/images/male/eye20.png +0 -0
  258. data/data/images/male/eye21.png +0 -0
  259. data/data/images/male/eye22.png +0 -0
  260. data/data/images/male/eye23.png +0 -0
  261. data/data/images/male/eye24.png +0 -0
  262. data/data/images/male/eye25.png +0 -0
  263. data/data/images/male/eye26.png +0 -0
  264. data/data/images/male/eye27.png +0 -0
  265. data/data/images/male/eye28.png +0 -0
  266. data/data/images/male/eye29.png +0 -0
  267. data/data/images/male/eye3.png +0 -0
  268. data/data/images/male/eye30.png +0 -0
  269. data/data/images/male/eye31.png +0 -0
  270. data/data/images/male/eye32.png +0 -0
  271. data/data/images/male/eye33.png +0 -0
  272. data/data/images/male/eye4.png +0 -0
  273. data/data/images/male/eye5.png +0 -0
  274. data/data/images/male/eye6.png +0 -0
  275. data/data/images/male/eye7.png +0 -0
  276. data/data/images/male/eye8.png +0 -0
  277. data/data/images/male/eye9.png +0 -0
  278. data/data/images/male/face1.png +0 -0
  279. data/data/images/male/face2.png +0 -0
  280. data/data/images/male/face3.png +0 -0
  281. data/data/images/male/face4.png +0 -0
  282. data/data/images/male/head1.png +0 -0
  283. data/data/images/male/head10.png +0 -0
  284. data/data/images/male/head11.png +0 -0
  285. data/data/images/male/head12.png +0 -0
  286. data/data/images/male/head13.png +0 -0
  287. data/data/images/male/head14.png +0 -0
  288. data/data/images/male/head15.png +0 -0
  289. data/data/images/male/head16.png +0 -0
  290. data/data/images/male/head17.png +0 -0
  291. data/data/images/male/head18.png +0 -0
  292. data/data/images/male/head19.png +0 -0
  293. data/data/images/male/head2.png +0 -0
  294. data/data/images/male/head20.png +0 -0
  295. data/data/images/male/head21.png +0 -0
  296. data/data/images/male/head22.png +0 -0
  297. data/data/images/male/head23.png +0 -0
  298. data/data/images/male/head24.png +0 -0
  299. data/data/images/male/head25.png +0 -0
  300. data/data/images/male/head26.png +0 -0
  301. data/data/images/male/head27.png +0 -0
  302. data/data/images/male/head28.png +0 -0
  303. data/data/images/male/head29.png +0 -0
  304. data/data/images/male/head3.png +0 -0
  305. data/data/images/male/head30.png +0 -0
  306. data/data/images/male/head31.png +0 -0
  307. data/data/images/male/head32.png +0 -0
  308. data/data/images/male/head33.png +0 -0
  309. data/data/images/male/head34.png +0 -0
  310. data/data/images/male/head35.png +0 -0
  311. data/data/images/male/head36.png +0 -0
  312. data/data/images/male/head37.png +0 -0
  313. data/data/images/male/head4.png +0 -0
  314. data/data/images/male/head5.png +0 -0
  315. data/data/images/male/head6.png +0 -0
  316. data/data/images/male/head7.png +0 -0
  317. data/data/images/male/head8.png +0 -0
  318. data/data/images/male/head9.png +0 -0
  319. data/data/images/male/mouth1.png +0 -0
  320. data/data/images/male/mouth10.png +0 -0
  321. data/data/images/male/mouth11.png +0 -0
  322. data/data/images/male/mouth12.png +0 -0
  323. data/data/images/male/mouth13.png +0 -0
  324. data/data/images/male/mouth14.png +0 -0
  325. data/data/images/male/mouth15.png +0 -0
  326. data/data/images/male/mouth16.png +0 -0
  327. data/data/images/male/mouth17.png +0 -0
  328. data/data/images/male/mouth18.png +0 -0
  329. data/data/images/male/mouth19.png +0 -0
  330. data/data/images/male/mouth2.png +0 -0
  331. data/data/images/male/mouth20.png +0 -0
  332. data/data/images/male/mouth21.png +0 -0
  333. data/data/images/male/mouth22.png +0 -0
  334. data/data/images/male/mouth23.png +0 -0
  335. data/data/images/male/mouth24.png +0 -0
  336. data/data/images/male/mouth25.png +0 -0
  337. data/data/images/male/mouth26.png +0 -0
  338. data/data/images/male/mouth3.png +0 -0
  339. data/data/images/male/mouth4.png +0 -0
  340. data/data/images/male/mouth5.png +0 -0
  341. data/data/images/male/mouth6.png +0 -0
  342. data/data/images/male/mouth7.png +0 -0
  343. data/data/images/male/mouth8.png +0 -0
  344. data/data/images/male/mouth9.png +0 -0
  345. data/lib/avatar_o_matic.rb +5 -0
  346. data/lib/avatar_o_matic/config.rb +53 -0
  347. data/lib/avatar_o_matic/generator.rb +98 -0
  348. data/spec/avatar_o_matic/config_spec.rb +64 -0
  349. data/spec/avatar_o_matic/generator_spec.rb +119 -0
  350. data/spec/data/test.png +0 -0
  351. data/spec/spec_helper.rb +3 -0
  352. metadata +408 -0
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
Binary file
@@ -0,0 +1,5 @@
1
+ require_relative 'avatar_o_matic/config'
2
+ require_relative 'avatar_o_matic/generator'
3
+
4
+ module AvatarOMatic
5
+ end
@@ -0,0 +1,53 @@
1
+ require 'find'
2
+
3
+ module AvatarOMatic
4
+ class Config
5
+ class << self
6
+
7
+ attr_accessor :image_lib
8
+
9
+ def image_lib
10
+ @image_lib ||= File.expand_path( File.join( '..', '..', '..', 'data', 'images'), __FILE__ )
11
+ end
12
+
13
+ def properties
14
+ [:background, :face, :clothes, :head, :eye, :mouth]
15
+ end
16
+
17
+ def types
18
+ [:male, :female]
19
+ end
20
+
21
+ def options_for(type, prop)
22
+ image_data[type.to_sym][prop.to_sym]
23
+ end
24
+
25
+ def image_data
26
+ return @_data if @_data
27
+
28
+ @_data = {}
29
+ re_file = /
30
+ \/
31
+ (#{self.types.join('|')})
32
+ \/
33
+ (#{self.properties.join('|')})
34
+ \d+
35
+ \.png
36
+ \Z/xo
37
+
38
+ Find.find(image_lib) do |path|
39
+ m = re_file.match(path) or next
40
+
41
+ type = m[1].to_sym
42
+ prop = m[2].to_sym
43
+
44
+ @_data[type] ||= {}
45
+ @_data[type][prop] ||= []
46
+ @_data[type][prop] << path
47
+ end
48
+
49
+ @_data
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,98 @@
1
+ require 'mini_magick'
2
+
3
+ #
4
+ # generator = AvatarOMatic::Generator.new(...)
5
+ # generator.generate! Does the magick, returns itself
6
+ # generator.save(path) Saves the image to path
7
+ # generator.image Returns the underlying minimagick object
8
+ #
9
+ # AvatarOMatic::Generator.new.generate!.save(path)
10
+ #
11
+
12
+
13
+ module AvatarOMatic
14
+ class Generator
15
+
16
+ attr_accessor :size
17
+ attr_reader :image
18
+
19
+ def initialize(opts={})
20
+ super()
21
+
22
+ opts.keys.select {|k| (Config.properties + [:size]).include? k }.each do |opt|
23
+ self.send :"#{opt}=", opts[opt]
24
+ end
25
+
26
+ @size ||= 400
27
+ end
28
+
29
+ def type=(type)
30
+ unless Config.types.include? type.to_sym
31
+ raise InvalidPropertyError.new("#{type} is not a recognised type")
32
+ end
33
+ @type = type
34
+ end
35
+
36
+ def type
37
+ @type ||= Config.types.sample
38
+ end
39
+
40
+
41
+ Config.properties.each do |prop|
42
+ define_method :"#{prop}=" do |value|
43
+ allowed_size = Config.options_for(type, prop).size
44
+
45
+ if value > allowed_size
46
+ raise InvalidPropertyError.new "There are only #{allowed_size} options for #{prop} (#{type}), you wanted #{value}"
47
+ end
48
+
49
+ instance_variable_set :"@#{prop}", value
50
+ end
51
+
52
+ define_method :"#{prop}" do
53
+ value = instance_variable_get :"@#{prop}"
54
+
55
+ unless value
56
+ value = Random.new.rand Config.options_for(type, prop).size
57
+ instance_variable_set :"@#{prop}", value
58
+ end
59
+
60
+ value
61
+ end
62
+ end
63
+
64
+ def generate!
65
+ @image = MiniMagick::Image.open path_for :background
66
+
67
+ Config.properties.select {|p| p != :background }.each do |prop|
68
+ overlay = MiniMagick::Image.open path_for prop
69
+ @image = @image.composite(overlay) do |c|
70
+ c.compose 'Over'
71
+ end
72
+ end
73
+
74
+ @image.resize size if image.width != size
75
+
76
+ self
77
+ end
78
+
79
+ def save(path)
80
+ raise NoImageYetError.new if @image.nil?
81
+ @image.write path
82
+ path
83
+ end
84
+
85
+ private
86
+
87
+ def option(prop)
88
+ self.send prop.to_sym
89
+ end
90
+
91
+ def path_for(prop)
92
+ Config.options_for(type, prop)[option prop]
93
+ end
94
+ end
95
+
96
+ class InvalidPropertyError < StandardError; end
97
+ class NoImageYetError < StandardError; end
98
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ describe(AvatarOMatic::Config) do
4
+
5
+ subject { described_class }
6
+
7
+ describe '.image_lib' do
8
+ it { is_expected.to respond_to :image_lib }
9
+
10
+ # FIXME: test setting image lib, and see it's being used
11
+ end
12
+
13
+ describe '.properties' do
14
+ it 'returns array of image properties' do
15
+ expect(subject.properties).to eq [:background, :face, :clothes, :head, :eye, :mouth]
16
+ end
17
+ end
18
+
19
+ describe '.types' do
20
+ it 'returns array of possible types' do
21
+ expect(subject.types).to eq [:male, :female]
22
+ end
23
+ end
24
+
25
+ describe '.options_for' do
26
+ described_class.properties.each do |p|
27
+ described_class.types.each do |g|
28
+ re_file = /\A
29
+ #{described_class.image_lib} # Library path
30
+ \/
31
+ (?:.+\/)?
32
+ #{p} # Property
33
+ \d+ # Serial
34
+ \.png
35
+ \Z/x
36
+
37
+ it "returns list of images for #{g} #{p}" do
38
+ expect( subject.options_for(g, p) ).to all match re_file
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ context '.image_data' do
45
+ subject { described_class.image_data }
46
+
47
+ before(:each) {
48
+ described_class.instance_variable_set(:'@_data', nil)
49
+ }
50
+
51
+ it 'data is populated on first access' do
52
+ expect {
53
+ subject
54
+ }.to change {
55
+ described_class.instance_variable_get(:'@_data')
56
+ }.from nil
57
+ end
58
+
59
+ described_class.properties.each do |p|
60
+ it { is_expected.to include :male => a_hash_including( { p => kind_of(Array) } ) }
61
+ it { is_expected.to include :female => a_hash_including( { p => kind_of(Array) } ) }
62
+ end
63
+ end
64
+ end