simple_attachments 0.1.1

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 (326) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README.rdoc +132 -0
  3. data/lib/simple_attachments.rb +15 -0
  4. data/lib/simple_attachments/attachment_model.rb +128 -0
  5. data/lib/simple_attachments/attachments_controller.rb +100 -0
  6. data/lib/simple_attachments/container_model.rb +73 -0
  7. data/lib/simple_attachments/migration_helpers.rb +14 -0
  8. data/lib/simple_attachments/view_helpers.rb +92 -0
  9. data/locales/en.yml +5 -0
  10. data/test/Rakefile +10 -0
  11. data/test/app/assets/javascripts/attachments.js +18 -0
  12. data/test/app/assets/stylesheets/attachments.css +17 -0
  13. data/test/app/controllers/application_controller.rb +3 -0
  14. data/test/app/controllers/avatars_controller.rb +3 -0
  15. data/test/app/controllers/documents_controller.rb +3 -0
  16. data/test/app/controllers/users_controller.rb +18 -0
  17. data/test/app/models/avatar.rb +5 -0
  18. data/test/app/models/document.rb +5 -0
  19. data/test/app/models/user.rb +4 -0
  20. data/test/app/views/layouts/application.html.erb +12 -0
  21. data/test/app/views/users/edit.html.erb +6 -0
  22. data/test/config.ru +4 -0
  23. data/test/config/application.rb +10 -0
  24. data/test/config/boot.rb +3 -0
  25. data/test/config/database.yml +5 -0
  26. data/test/config/environment.rb +5 -0
  27. data/test/config/environments/test.rb +12 -0
  28. data/test/config/initializers/secret_token.rb +7 -0
  29. data/test/config/initializers/session_store.rb +8 -0
  30. data/test/config/initializers/wrap_parameters.rb +14 -0
  31. data/test/config/routes.rb +5 -0
  32. data/test/db/migrate/1_create_users.rb +6 -0
  33. data/test/db/migrate/2_create_avatars.rb +8 -0
  34. data/test/db/migrate/3_create_documents.rb +8 -0
  35. data/test/db/schema.rb +34 -0
  36. data/test/db/test.sqlite3 +0 -0
  37. data/test/log/test.log +11774 -0
  38. data/test/script/rails +6 -0
  39. data/test/spec/multiple_spec.rb +36 -0
  40. data/test/spec/samples/sample.jpg +0 -0
  41. data/test/spec/samples/sample.pdf +0 -0
  42. data/test/spec/samples/sample.png +0 -0
  43. data/test/spec/singleton_spec.rb +54 -0
  44. data/test/spec/spec_helper.rb +22 -0
  45. data/test/tmp/cache/2CB/9B1/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fattachments.js%3F +0 -0
  46. data/test/tmp/cache/337/6A1/http%3A%2F%2Flocalhost%3A3000%2Fassets%2Fattachments.css%3F +0 -0
  47. data/test/tmp/cache/A03/C30/86cd82a38406e2cc75af040321554265d148882e +0 -0
  48. data/test/tmp/cache/BDE/BD0/7d763b3bac537e97ea5f3fb558c2bdbba05b72bc +0 -0
  49. data/test/tmp/cache/assets/C2E/6F0/sprockets%2F99a77a1d4d8767343010e1153d993839 +0 -0
  50. data/test/tmp/cache/assets/C5A/590/sprockets%2F2993f5a3d21b3e477143358534c68f55 +0 -0
  51. data/test/tmp/cache/assets/C5B/6F0/sprockets%2F19824e4169877bb010cd8163319f3f95 +0 -0
  52. data/test/tmp/cache/assets/CEB/450/sprockets%2Fada5663796684365b3e4ab36529bc86b +0 -0
  53. data/test/tmp/cache/assets/CF4/E60/sprockets%2F96b74d34978f2759ec2af602cd969d00 +0 -0
  54. data/test/tmp/cache/assets/D0B/600/sprockets%2F0b1b45e6991800f2911a6bcccf54a679 +0 -0
  55. data/test/tmp/cache/assets/D48/590/sprockets%2F522d019dab47a2617f2c2a99e98a99ed +0 -0
  56. data/test/tmp/cache/assets/D64/BF0/sprockets%2Fbd0d2396f3797000ffd901eba90b4d0e +0 -0
  57. data/test/tmp/cache/assets/D6B/150/sprockets%2F0b6cebd1717e9da4183329be9a2d77c0 +0 -0
  58. data/test/tmp/cache/assets/D70/120/sprockets%2F0f56b864e2eba6c4199d4171bdf391ae +0 -0
  59. data/test/tmp/cache/assets/D91/580/sprockets%2Fb5e4430a5a0af8eee00d262f82b565ed +0 -0
  60. data/test/tmp/cache/assets/D9A/760/sprockets%2F8df77fdd2c3c1f3d04f450c72a635be2 +0 -0
  61. data/test/tmp/cache/assets/DA1/380/sprockets%2F5e06b3974a8f9ca4452d4dfea337dba5 +0 -0
  62. data/test/tmp/cache/assets/DA9/EC0/sprockets%2F73f61f04eb2d87aced83787a0f14cf8e +0 -0
  63. data/test/uploads/1330732189.40513.sample.jpg +0 -0
  64. data/test/uploads/1330732621.7381.sample.jpg +0 -0
  65. data/test/uploads/1330732672.36763.sample.jpg +0 -0
  66. data/test/uploads/1330732847.98348.sample.jpg +0 -0
  67. data/test/uploads/1330732967.05269.sample.jpg +0 -0
  68. data/test/uploads/1330733025.52707.sample.jpg +0 -0
  69. data/test/uploads/1330733381.60733.sample.jpg +0 -0
  70. data/test/uploads/1330733822.51761.sample.jpg +0 -0
  71. data/test/uploads/1330733887.44114.sample.jpg +0 -0
  72. data/test/uploads/1330738615.68437.sample.jpg +0 -0
  73. data/test/uploads/1330738616.82401.sample.jpg +0 -0
  74. data/test/uploads/1330738618.00278.sample.jpg +0 -0
  75. data/test/uploads/1330738771.92631.sample.jpg +0 -0
  76. data/test/uploads/1330738772.94099.sample.jpg +0 -0
  77. data/test/uploads/1330738901.69933.sample.jpg +0 -0
  78. data/test/uploads/1330738904.3815.sample.jpg +0 -0
  79. data/test/uploads/1330739046.59901.sample.jpg +0 -0
  80. data/test/uploads/1330739125.79463.sample.jpg +0 -0
  81. data/test/uploads/1330739131.09163.sample.pdf +0 -0
  82. data/test/uploads/1330739735.52707.sample.jpg +0 -0
  83. data/test/uploads/1330739738.11937.sample.jpg +0 -0
  84. data/test/uploads/1330739742.76692.sample.jpg +0 -0
  85. data/test/uploads/1330739911.78046.sample.jpg +0 -0
  86. data/test/uploads/1330739914.46047.sample.jpg +0 -0
  87. data/test/uploads/1330739918.80359.sample.jpg +0 -0
  88. data/test/uploads/1330739921.39005.sample.jpg +0 -0
  89. data/test/uploads/1330739988.04537.sample.jpg +0 -0
  90. data/test/uploads/1330739990.65212.sample.jpg +0 -0
  91. data/test/uploads/1330739994.98225.sample.jpg +0 -0
  92. data/test/uploads/1330739997.45622.sample.jpg +0 -0
  93. data/test/uploads/1330740765.24516.sample.jpg +0 -0
  94. data/test/uploads/1330740767.71798.sample.jpg +0 -0
  95. data/test/uploads/1330740771.9889.sample.jpg +0 -0
  96. data/test/uploads/1330740774.56759.sample.jpg +0 -0
  97. data/test/uploads/1330741058.17571.sample.jpg +0 -0
  98. data/test/uploads/1330741060.65483.sample.jpg +0 -0
  99. data/test/uploads/1330741067.79574.sample.jpg +0 -0
  100. data/test/uploads/1330741154.42055.sample.jpg +0 -0
  101. data/test/uploads/1330741157.28718.sample.jpg +0 -0
  102. data/test/uploads/1330741164.64669.sample.jpg +0 -0
  103. data/test/uploads/1330741776.05725.sample.jpg +0 -0
  104. data/test/uploads/1330741778.80256.sample.jpg +0 -0
  105. data/test/uploads/1330741785.96345.sample.jpg +0 -0
  106. data/test/uploads/1330742286.07361.sample.jpg +0 -0
  107. data/test/uploads/1330742288.59918.sample.jpg +0 -0
  108. data/test/uploads/1330742295.83963.sample.jpg +0 -0
  109. data/test/uploads/1330742576.6398.sample.jpg +0 -0
  110. data/test/uploads/1330742579.54181.sample.jpg +0 -0
  111. data/test/uploads/1330742586.88996.sample.jpg +0 -0
  112. data/test/uploads/1330743983.91544.shen-logic-part1.pdf +0 -0
  113. data/test/uploads/1330744294.55912.sample.jpg +0 -0
  114. data/test/uploads/1330744296.94811.sample.jpg +0 -0
  115. data/test/uploads/1330744304.25529.sample.jpg +0 -0
  116. data/test/uploads/1330744307.08498.sample.pdf +0 -0
  117. data/test/uploads/1330744309.25872.sample.pdf +0 -0
  118. data/test/uploads/1330744443.49578.sample.jpg +0 -0
  119. data/test/uploads/1330744446.09032.sample.jpg +0 -0
  120. data/test/uploads/1330744453.55965.sample.jpg +0 -0
  121. data/test/uploads/1330744456.32318.sample.pdf +0 -0
  122. data/test/uploads/1330744458.42931.sample.pdf +0 -0
  123. data/test/uploads/1330744533.52631.sample.jpg +0 -0
  124. data/test/uploads/1330744536.13208.sample.jpg +0 -0
  125. data/test/uploads/1330744543.29535.sample.jpg +0 -0
  126. data/test/uploads/1330744546.16477.sample.pdf +0 -0
  127. data/test/uploads/1330744548.27125.sample.pdf +0 -0
  128. data/test/uploads/1330744696.43953.sample.jpg +0 -0
  129. data/test/uploads/1330744698.95043.sample.jpg +0 -0
  130. data/test/uploads/1330744706.28901.sample.jpg +0 -0
  131. data/test/uploads/1330744711.24284.sample.pdf +0 -0
  132. data/test/uploads/1330744713.6281.sample.pdf +0 -0
  133. data/test/uploads/1330744782.91673.sample.jpg +0 -0
  134. data/test/uploads/1330744785.53684.sample.jpg +0 -0
  135. data/test/uploads/1330744792.74599.sample.jpg +0 -0
  136. data/test/uploads/1330744797.90608.sample.pdf +0 -0
  137. data/test/uploads/1330744800.55736.sample.pdf +0 -0
  138. data/test/uploads/1330771358.91882.sample.jpg +0 -0
  139. data/test/uploads/1330771359.23929.sample.jpg +0 -0
  140. data/test/uploads/1330771359.70574.sample.jpg +0 -0
  141. data/test/uploads/1330771360.07645.sample.png +0 -0
  142. data/test/uploads/1330771364.83802.sample.pdf +0 -0
  143. data/test/uploads/1330771367.18498.sample.pdf +0 -0
  144. data/test/uploads/1330771514.28703.sample.jpg +0 -0
  145. data/test/uploads/1330771514.66497.sample.jpg +0 -0
  146. data/test/uploads/1330771515.12563.sample.jpg +0 -0
  147. data/test/uploads/1330771515.72515.sample.png +0 -0
  148. data/test/uploads/1330771519.30014.sample.pdf +0 -0
  149. data/test/uploads/1330771519.55784.sample.pdf +0 -0
  150. data/test/uploads/1330771519.89044.sample.pdf +0 -0
  151. data/test/uploads/1330771522.50763.sample.pdf +0 -0
  152. data/test/uploads/1330771522.75458.sample.pdf +0 -0
  153. data/test/uploads/1330775627.9105.sample.pdf +0 -0
  154. data/test/uploads/1330775628.40671.sample.pdf +0 -0
  155. data/test/uploads/1330775628.68645.sample.pdf +0 -0
  156. data/test/uploads/1330775631.48519.sample.pdf +0 -0
  157. data/test/uploads/1330775631.9586.sample.pdf +0 -0
  158. data/test/uploads/1330775676.5146.sample.pdf +0 -0
  159. data/test/uploads/1330775703.20143.sample.pdf +0 -0
  160. data/test/uploads/1330775704.36145.sample.pdf +0 -0
  161. data/test/uploads/1330775705.27831.sample.pdf +0 -0
  162. data/test/uploads/1330775706.66539.sample.pdf +0 -0
  163. data/test/uploads/1330776988.21579.sample.pdf +0 -0
  164. data/test/uploads/1330776988.69155.sample.pdf +0 -0
  165. data/test/uploads/1330776989.12114.sample.pdf +0 -0
  166. data/test/uploads/1330776992.1201.sample.pdf +0 -0
  167. data/test/uploads/1330776992.57634.sample.pdf +0 -0
  168. data/test/uploads/1330777152.6597.sample.jpg +0 -0
  169. data/test/uploads/1330777153.00459.sample.jpg +0 -0
  170. data/test/uploads/1330777153.45871.sample.jpg +0 -0
  171. data/test/uploads/1330777153.86376.sample.png +0 -0
  172. data/test/uploads/1330777157.91465.sample.pdf +0 -0
  173. data/test/uploads/1330777158.23816.sample.pdf +0 -0
  174. data/test/uploads/1330777158.74465.sample.pdf +0 -0
  175. data/test/uploads/1330777161.59586.sample.pdf +0 -0
  176. data/test/uploads/1330777161.93334.sample.pdf +0 -0
  177. data/test/uploads/1330777833.73591.sample.jpg +0 -0
  178. data/test/uploads/1330777834.05449.sample.jpg +0 -0
  179. data/test/uploads/1330777834.50661.sample.jpg +0 -0
  180. data/test/uploads/1330777834.87967.sample.jpg +0 -0
  181. data/test/uploads/1330777835.22949.sample.jpg +0 -0
  182. data/test/uploads/1330777835.55546.sample.png +0 -0
  183. data/test/uploads/1330777840.54959.sample.jpg +0 -0
  184. data/test/uploads/1330777844.18911.sample.pdf +0 -0
  185. data/test/uploads/1330777844.58364.sample.pdf +0 -0
  186. data/test/uploads/1330777844.96998.sample.pdf +0 -0
  187. data/test/uploads/1330777847.62838.sample.pdf +0 -0
  188. data/test/uploads/1330777848.0192.sample.pdf +0 -0
  189. data/test/uploads/1330778979.41703.sample.jpg +0 -0
  190. data/test/uploads/1330778979.74093.sample.jpg +0 -0
  191. data/test/uploads/1330778980.16769.sample.jpg +0 -0
  192. data/test/uploads/1330778980.54831.sample.jpg +0 -0
  193. data/test/uploads/1330778980.91033.sample.jpg +0 -0
  194. data/test/uploads/1330778981.23582.sample.png +0 -0
  195. data/test/uploads/1330778986.50795.sample.jpg +0 -0
  196. data/test/uploads/1330778989.07307.sample.pdf +0 -0
  197. data/test/uploads/1330778989.59241.sample.pdf +0 -0
  198. data/test/uploads/1330778990.06415.sample.pdf +0 -0
  199. data/test/uploads/1330778990.44233.sample.pdf +0 -0
  200. data/test/uploads/1330779134.25647.sample.jpg +0 -0
  201. data/test/uploads/1330779134.67957.sample.jpg +0 -0
  202. data/test/uploads/1330779135.15349.sample.jpg +0 -0
  203. data/test/uploads/1330779135.6793.sample.jpg +0 -0
  204. data/test/uploads/1330779136.14714.sample.jpg +0 -0
  205. data/test/uploads/1330779136.70598.sample.png +0 -0
  206. data/test/uploads/1330779141.75878.sample.jpg +0 -0
  207. data/test/uploads/1330779145.79811.sample.pdf +0 -0
  208. data/test/uploads/1330779146.40945.sample.pdf +0 -0
  209. data/test/uploads/1330779146.75038.sample.pdf +0 -0
  210. data/test/uploads/1330779149.67101.sample.pdf +0 -0
  211. data/test/uploads/1330779150.033.sample.pdf +0 -0
  212. data/test/uploads/1330779251.92468.sample.jpg +0 -0
  213. data/test/uploads/1330779252.33759.sample.jpg +0 -0
  214. data/test/uploads/1330779252.79211.sample.jpg +0 -0
  215. data/test/uploads/1330779253.16365.sample.jpg +0 -0
  216. data/test/uploads/1330779253.51459.sample.jpg +0 -0
  217. data/test/uploads/1330779253.82932.sample.png +0 -0
  218. data/test/uploads/1330779259.04186.sample.jpg +0 -0
  219. data/test/uploads/1330779262.79998.sample.pdf +0 -0
  220. data/test/uploads/1330779263.19534.sample.pdf +0 -0
  221. data/test/uploads/1330779263.51726.sample.pdf +0 -0
  222. data/test/uploads/1330779266.23965.sample.pdf +0 -0
  223. data/test/uploads/1330779266.65453.sample.pdf +0 -0
  224. data/test/uploads/1330780162.71983.1.gif +0 -0
  225. data/test/uploads/1330780370.60224.sample.jpg +0 -0
  226. data/test/uploads/1330780370.95202.sample.jpg +0 -0
  227. data/test/uploads/1330780371.44543.sample.jpg +0 -0
  228. data/test/uploads/1330780371.88658.sample.jpg +0 -0
  229. data/test/uploads/1330780372.30293.sample.jpg +0 -0
  230. data/test/uploads/1330780372.79723.sample.png +0 -0
  231. data/test/uploads/1330780378.19075.sample.jpg +0 -0
  232. data/test/uploads/1330780382.07736.sample.pdf +0 -0
  233. data/test/uploads/1330780382.61497.sample.pdf +0 -0
  234. data/test/uploads/1330780383.10458.sample.pdf +0 -0
  235. data/test/uploads/1330780385.85251.sample.pdf +0 -0
  236. data/test/uploads/1330780386.24973.sample.pdf +0 -0
  237. data/test/uploads/1330781258.12109.sample.pdf +0 -0
  238. data/test/uploads/1330781258.63862.sample.pdf +0 -0
  239. data/test/uploads/1330781259.10465.sample.pdf +0 -0
  240. data/test/uploads/1330781262.08459.sample.pdf +0 -0
  241. data/test/uploads/1330781262.52448.sample.pdf +0 -0
  242. data/test/uploads/1330781278.37307.sample.jpg +0 -0
  243. data/test/uploads/1330781278.7309.sample.jpg +0 -0
  244. data/test/uploads/1330781279.18693.sample.jpg +0 -0
  245. data/test/uploads/1330781279.55913.sample.jpg +0 -0
  246. data/test/uploads/1330781279.92436.sample.jpg +0 -0
  247. data/test/uploads/1330781280.27391.sample.png +0 -0
  248. data/test/uploads/1330886711.00348.sample.pdf +0 -0
  249. data/test/uploads/1330886711.78495.sample.pdf +0 -0
  250. data/test/uploads/1330886712.4033.sample.pdf +0 -0
  251. data/test/uploads/1330886716.09532.sample.pdf +0 -0
  252. data/test/uploads/1330886716.7663.sample.pdf +0 -0
  253. data/test/uploads/1330886735.38676.sample.jpg +0 -0
  254. data/test/uploads/1330886736.28739.sample.jpg +0 -0
  255. data/test/uploads/1330886736.84868.sample.jpg +0 -0
  256. data/test/uploads/1330886737.64167.sample.jpg +0 -0
  257. data/test/uploads/1330886738.33938.sample.jpg +0 -0
  258. data/test/uploads/1330886738.92271.sample.png +0 -0
  259. data/test/uploads/1330886985.6679.sample.pdf +0 -0
  260. data/test/uploads/1330886986.4568.sample.pdf +0 -0
  261. data/test/uploads/1330886987.00302.sample.pdf +0 -0
  262. data/test/uploads/1330886990.4604.sample.pdf +0 -0
  263. data/test/uploads/1330886991.04681.sample.pdf +0 -0
  264. data/test/uploads/1330887008.68477.sample.jpg +0 -0
  265. data/test/uploads/1330887009.23077.sample.jpg +0 -0
  266. data/test/uploads/1330887009.82498.sample.jpg +0 -0
  267. data/test/uploads/1330887010.48937.sample.jpg +0 -0
  268. data/test/uploads/1330887011.23496.sample.jpg +0 -0
  269. data/test/uploads/1330887011.92032.sample.png +0 -0
  270. data/test/uploads/1330887633.41769.sample.pdf +0 -0
  271. data/test/uploads/1330887633.81961.sample.pdf +0 -0
  272. data/test/uploads/1330887634.25582.sample.pdf +0 -0
  273. data/test/uploads/1330887637.47958.sample.pdf +0 -0
  274. data/test/uploads/1330887638.14348.sample.pdf +0 -0
  275. data/test/uploads/1330887655.10619.sample.jpg +0 -0
  276. data/test/uploads/1330887655.80139.sample.jpg +0 -0
  277. data/test/uploads/1330887656.35041.sample.jpg +0 -0
  278. data/test/uploads/1330887656.86876.sample.jpg +0 -0
  279. data/test/uploads/1330887657.60467.sample.jpg +0 -0
  280. data/test/uploads/1330887658.23424.sample.png +0 -0
  281. data/test/uploads/1330888133.62299.WIN.gif +0 -0
  282. data/test/uploads/1330888504.16714.1.gif +0 -0
  283. data/test/uploads/1330888586.99975.1.gif +0 -0
  284. data/test/uploads/1330888607.58249.shen-logic-part1.pdf +0 -0
  285. data/test/uploads/1330889585.30006.shen-logic-part2.pdf +0 -0
  286. data/test/uploads/1330890565.79547.shen-logic-part1.pdf +0 -0
  287. data/test/uploads/1330890992.45693.sample.jpg +0 -0
  288. data/test/uploads/1330890998.10996.sample.pdf +0 -0
  289. data/test/uploads/1330890998.76199.sample.pdf +0 -0
  290. data/test/uploads/1330890999.14516.sample.pdf +0 -0
  291. data/test/uploads/1330891002.0989.sample.pdf +0 -0
  292. data/test/uploads/1330891002.49258.sample.pdf +0 -0
  293. data/test/uploads/1330891004.89888.sample.jpg +0 -0
  294. data/test/uploads/1330891007.45147.sample.jpg +0 -0
  295. data/test/uploads/1330891052.00842.sample.jpg +0 -0
  296. data/test/uploads/1330891056.46428.sample.pdf +0 -0
  297. data/test/uploads/1330891056.83678.sample.pdf +0 -0
  298. data/test/uploads/1330891057.31732.sample.pdf +0 -0
  299. data/test/uploads/1330891057.86036.sample.pdf +0 -0
  300. data/test/uploads/1330891058.49616.sample.pdf +0 -0
  301. data/test/uploads/1330891058.91288.sample.pdf +0 -0
  302. data/test/uploads/1330891138.7408.sample.pdf +0 -0
  303. data/test/uploads/1330891139.14067.sample.pdf +0 -0
  304. data/test/uploads/1330891139.46755.sample.pdf +0 -0
  305. data/test/uploads/1330891142.26432.sample.pdf +0 -0
  306. data/test/uploads/1330891142.684.sample.pdf +0 -0
  307. data/test/uploads/1330891158.04426.sample.jpg +0 -0
  308. data/test/uploads/1330891158.44159.sample.jpg +0 -0
  309. data/test/uploads/1330891158.85135.sample.jpg +0 -0
  310. data/test/uploads/1330891159.3765.sample.jpg +0 -0
  311. data/test/uploads/1330891159.79503.sample.jpg +0 -0
  312. data/test/uploads/1330891160.15479.sample.png +0 -0
  313. data/test/uploads/1330900466.37214.sample.pdf +0 -0
  314. data/test/uploads/1330900466.77443.sample.pdf +0 -0
  315. data/test/uploads/1330900467.32831.sample.pdf +0 -0
  316. data/test/uploads/1330900470.07702.sample.pdf +0 -0
  317. data/test/uploads/1330900470.48767.sample.pdf +0 -0
  318. data/test/uploads/1330900486.92727.sample.jpg +0 -0
  319. data/test/uploads/1330900487.4311.sample.jpg +0 -0
  320. data/test/uploads/1330900488.03152.sample.jpg +0 -0
  321. data/test/uploads/1330900488.43945.sample.jpg +0 -0
  322. data/test/uploads/1330900489.01433.sample.jpg +0 -0
  323. data/test/uploads/1330900489.43854.sample.png +0 -0
  324. data/vendor/assets/javascripts/simple_attachments.js +138 -0
  325. data/vendor/assets/stylesheets/simple_attachments.css +23 -0
  326. metadata +729 -0
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 Tsokurov Alex <me@ximik.net>
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,132 @@
1
+ = Simple Attachments
2
+
3
+ Simple Attachments is a plugin for Ruby on Rails 3 which implements complex solution for working with file attachments.
4
+
5
+ == Requirements
6
+
7
+ Plugin contains some CSS and JavaScript code, so Asset Pipeline should be switched on (by default).
8
+ Also you need {jQuery library}[http://jquery.com/] to make JavaScript work.
9
+
10
+ == Installation
11
+
12
+ Add this to your Gemfile and run the +bundle+ command.
13
+
14
+ gem 'simple_attachments'
15
+
16
+ == Getting Started
17
+
18
+ Let's say you have a +User+ which has one +Avatar+ and many +Document+.
19
+ The avatar can be change from user edit form. And the avatar data updates only after submiting the form.
20
+ The documents are shown on the same page. They can be managed separately with auto saving all changes in background.
21
+ You can find this app in +test+.
22
+
23
+ === Migrations
24
+
25
+ class CreateAvatars < ActiveRecord::Migration
26
+ def change
27
+ create_table :avatars do |t|
28
+ t.references :avatar, :null => true
29
+ t.attachment
30
+ end
31
+ end
32
+ end
33
+
34
+ class CreateDocuments < ActiveRecord::Migration
35
+ def change
36
+ create_table :documents do |t|
37
+ t.references :avatar, :null => true
38
+ t.attachment
39
+ end
40
+ end
41
+ end
42
+
43
+ *WARNING*: it's important to permit null value for container.
44
+
45
+ === Routes
46
+
47
+ resources :avatars, :only => [:create, :show, :destroy]
48
+ resources :documents, :only => [:create, :show, :destroy]
49
+
50
+ === Models
51
+
52
+ class User < ActiveRecord::Base
53
+ has_one_attachment :avatar, :dependent => :destroy
54
+ has_many_attachments :books, :dependent => :destroy
55
+ end
56
+
57
+ class Avatar < ActiveRecord::Base
58
+ attached_to :user
59
+ validates_mimetype %w(image/png image/gif image/jpeg)
60
+ validates_filesize :less_than_or_equal_to => 5e4
61
+ end
62
+
63
+ class Document < ActiveRecord::Base
64
+ attached_to :user
65
+ validates_mimetype %w(application/pdf)
66
+ validates_filesize :less_than_or_equal_to => 20e6
67
+ end
68
+
69
+ You can use a lot of options here. Just like with +has_one+, +has_many+ and +belongs_to+.
70
+
71
+ === Controllers
72
+
73
+ class AvatarsController < ApplicationController
74
+ attachment_controller
75
+ end
76
+
77
+ class DocumentsController < ApplicationController
78
+ attachment_controller
79
+ end
80
+
81
+ === View
82
+
83
+ <%= form_for @user do |f| %>
84
+ <%= f.file :avatar, :auto_associate => false %>
85
+ <% end %>
86
+
87
+ <%= files @user, :documents %>
88
+
89
+ *WARNING*: you also need +csrf_meta_tags+ in your layout to work with +protect_from_forgery+ filter.
90
+
91
+ === JavaScript
92
+
93
+ Plugin doesn't provide any implementation of the file appearance.
94
+ Instead it triggers events, which are easy to handle.
95
+
96
+ //= require_self
97
+ //= require simple_attachments
98
+
99
+ $(function() {
100
+ // Div is loaded and engine is ready.
101
+ $(".simple_attachments_div").bind("init", function() {
102
+ // You can add your own init features here.
103
+ });
104
+ // New field was created.
105
+ // Field is a div displaying attachment information.
106
+ $(".simple_attachments_div").bind("new_field", function(event, field) {
107
+ // You have to set field in the right place and add binds.
108
+ field.appendTo(this);
109
+ // Attachment was loaded
110
+ // data contains attachment properties and some little support variables
111
+ field.bind("loaded", function(event, data) {
112
+ // You have to create and/or set field content here
113
+ data.destroy_link.appendTo(this);
114
+ data.attachment_link.html(data.filename).appendTo(this);
115
+ });
116
+ // Attachment upload was failed
117
+ // errors is an array of strings
118
+ field.bind("failed", function(event, errors) {
119
+ // You can do something here before field would be deleted
120
+ });
121
+ });
122
+ });
123
+
124
+ *WARNING*: +simple_attachments.js+ should be required after binds.
125
+
126
+ === CSS
127
+
128
+ +simple_attachments.css+ contains some code to decorate default file input. So better require it, but it's not so necessary.
129
+
130
+ ---
131
+
132
+ (c) 2012 Tsokurov Alex <{me@ximik.net}[mailto:me@ximik.net]>, released under the MIT license
@@ -0,0 +1,15 @@
1
+ # :main: README.rdoc
2
+
3
+ module SimpleAttachments # :nodoc:
4
+ class Engine < ::Rails::Engine # :nodoc:
5
+ end
6
+ end
7
+
8
+ dir = File.expand_path(File.dirname(__FILE__))
9
+ I18n.load_path << File.join(dir, '..', 'locales', 'en.yml')
10
+
11
+ require File.join(dir, 'simple_attachments', 'attachment_model')
12
+ require File.join(dir, 'simple_attachments', 'container_model')
13
+ require File.join(dir, 'simple_attachments', 'attachments_controller')
14
+ require File.join(dir, 'simple_attachments', 'view_helpers')
15
+ require File.join(dir, 'simple_attachments', 'migration_helpers')
@@ -0,0 +1,128 @@
1
+ module SimpleAttachments::AttachmentModel
2
+
3
+ module Helpers
4
+
5
+ # Mark model as attachment and create association.
6
+ #
7
+ # Syntax is identical to +belongs_to+.
8
+ #
9
+ # attached_to :post
10
+ #
11
+ # Do not use more than one time in one model.
12
+ # However you can use polymorphic associations.
13
+ #
14
+ # attached_to :container, :polymorphic => true
15
+
16
+ def attached_to(name, options = {})
17
+ reflection = belongs_to name, options
18
+ self.class.send(:attr_accessor, :container_name)
19
+ self.container_name = reflection.name
20
+ before_save :save_file
21
+ after_destroy :destroy_file
22
+ send :extend, ClassMethods
23
+ send :include, InstanceMethods
24
+ end
25
+
26
+ end
27
+
28
+ module ClassMethods
29
+
30
+ # Validate mimetype of uploaded file.
31
+ #
32
+ # validates_mimetype %w(image/png image/gif image/jpeg), :message => 'should be an image'
33
+ #
34
+ # :message is optional.
35
+
36
+ def validates_mimetype(types, options = {})
37
+ options[:message] ||= I18n.t('simple_attachments.mimetype_isnt_allowed')
38
+ validates :mimetype, :inclusion => { :in => types, :message => options[:message] }
39
+ end
40
+
41
+ # Validate filesize. Syntax is identical to numericality validator. Filesize is given in bytes.
42
+ #
43
+ # validates_filesize :less_than_or_equal_to => 12e6, :message => 'file is too large'
44
+ #
45
+ # :message is optional.
46
+
47
+ def validates_filesize(options)
48
+ options[:message] ||= I18n.t('simple_attachments.file_is_too_large')
49
+ validates :filesize, :numericality => options
50
+ end
51
+
52
+ end
53
+
54
+ module InstanceMethods
55
+
56
+ # Set file for attachment.
57
+ # +file+ is +UploadedFile+ object
58
+
59
+ def file=(file)
60
+ if file.nil?
61
+ uploading_error
62
+ else
63
+ @file = file
64
+ self.mimetype = @file.content_type
65
+ self.filesize = @file.tempfile.size
66
+ self.filename = File.basename(@file.original_filename) # old browsers hack
67
+ self.filepath = file_path
68
+ end
69
+ end
70
+
71
+ # Generate path to file.
72
+ # Redefine this method if you want another naming logic.
73
+
74
+ def file_path
75
+ "#{Time.now.to_f}.#{filename}"
76
+ end
77
+
78
+ # Generate full path to file.
79
+ # Redefine this method if you have another place to hold files.
80
+
81
+ def full_file_path
82
+ Rails.root.join('uploads', filepath).to_s
83
+ end
84
+
85
+ # Save file in the filesystem.
86
+
87
+ def save_file
88
+ File.open(full_file_path, 'w') { |file| file.write @file.read } unless @file.nil?
89
+ rescue
90
+ uploading_error
91
+ end
92
+
93
+ # Delete file from the filesystem.
94
+
95
+ def destroy_file
96
+ File.delete full_file_path
97
+ rescue
98
+ end
99
+
100
+ def serializable_hash # :nodoc:
101
+ data = super
102
+ data['filepath'] = path # changing filepath to file url
103
+ data
104
+ end
105
+
106
+ # Test if attached to any container.
107
+
108
+ def attached?
109
+ not send(self.class.container_name).nil?
110
+ end
111
+
112
+ # Generate error connected to any server problems.
113
+
114
+ def uploading_error
115
+ errors[:base] << I18n.t('simple_attachments.uploading_error')
116
+ end
117
+
118
+ # Get url to the attachment.
119
+
120
+ def path
121
+ Rails.application.routes.url_helpers.send(self.class.to_s.underscore.concat('_path'), id)
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ ActiveRecord::Base.extend SimpleAttachments::AttachmentModel::Helpers
@@ -0,0 +1,100 @@
1
+ module SimpleAttachments::AttachmentsController
2
+
3
+ module Helpers
4
+
5
+ # Mark controller as controller for attachment resource.
6
+ #
7
+ # Just put at any place of your controller.
8
+ #
9
+ # attachment_controller
10
+ #
11
+ # Sometimes you have to specify your resource manually.
12
+ #
13
+ # attachment_controller :resource => MyNamespace::Attachment
14
+
15
+ def attachment_controller(options = {})
16
+ before_filter :load_attachment, :except => :create
17
+ self.class.send(:attr_accessor, :attachment_model)
18
+ self.attachment_model = (options[:resource] or controller_path.classify.constantize)
19
+ send :include, InstanceMethods
20
+ end
21
+
22
+ end
23
+
24
+ module InstanceMethods
25
+
26
+ def create # :nodoc:
27
+ @attachment = self.class.attachment_model.new
28
+ @attachment.file = params[:file]
29
+ if @attachment.save and params[:container_id] != 'null'
30
+ begin
31
+ container = params[:container_model].classify.constantize.find params[:container_id]
32
+ associate(container, params[:method])
33
+ container.save
34
+ rescue
35
+ @attachment.uploading_error
36
+ end
37
+ end
38
+ if @attachment.errors.any?
39
+ succeed = false
40
+ data = @attachment.errors.messages.values.flatten
41
+ @attachment.destroy
42
+ else
43
+ succeed = true
44
+ data = @attachment.serializable_hash
45
+ end
46
+ render_answer(succeed, data)
47
+ end
48
+
49
+ def show # :nodoc:
50
+ send_file @attachment.full_file_path, :type => @attachment.mimetype, :filename => @attachment.filename
51
+ end
52
+
53
+ def destroy # :nodoc:
54
+ @attachment.destroy
55
+ render :nothing => true
56
+ end
57
+
58
+ private
59
+
60
+ # Before filter to load attachment resource.
61
+ #
62
+ # If you use another way to load it then just skip this filter.
63
+ #
64
+ # skip_before_filter :load_attachment
65
+
66
+ def load_attachment # :doc:
67
+ @attachment = self.class.attachment_model.find params[:id]
68
+ rescue
69
+ raise ActionController::RoutingError.new('Not Found')
70
+ end
71
+
72
+ # Associate attachment with container.
73
+ # Works only if you use +:auto_associate+ option (switched on by default).
74
+ #
75
+ # Redefine it if you want to have some extra control. E.g. CanCan authorization.
76
+ #
77
+ # def associate(container, method)
78
+ # authorize! :update, container
79
+ # super
80
+ # end
81
+
82
+ def associate(container, method) # :doc:
83
+ container.add_attachment method, @attachment
84
+ end
85
+
86
+ # Renders answer for javascript.
87
+
88
+ def render_answer(succeed, data) # :nodoc:
89
+ render :text => {'succeed' => succeed, 'data' => data}.to_json
90
+ end
91
+
92
+ def handle_unverified_request # :nodoc:
93
+ render :nothing => true
94
+ end
95
+
96
+ end
97
+
98
+ end
99
+
100
+ ActionController::Base.extend SimpleAttachments::AttachmentsController::Helpers
@@ -0,0 +1,73 @@
1
+ module SimpleAttachments::ContainerModel
2
+
3
+ module Helpers
4
+
5
+ # Mark model as container and create association.
6
+ #
7
+ # Syntax is identical to +has_many+.
8
+ #
9
+ # has_many_attachments :attachments
10
+
11
+ def has_many_attachments(name, options = {})
12
+ reflection = has_many name, options
13
+ send(:define_method, reflection.plural_name + '_=') do |attachment_ids|
14
+ method, model = recover_vars(__method__)
15
+ old_attachment_ids = send method.singularize.concat('_ids')
16
+ attachment_ids = attachment_ids.map { |id| id.to_i }
17
+ model.destroy_all :id => (old_attachment_ids - attachment_ids)
18
+ (attachment_ids - old_attachment_ids).each do |attachment_id|
19
+ find_and_add_attachment(method, model, attachment_id)
20
+ end
21
+ end
22
+ send :include, InstanceMethods
23
+ end
24
+
25
+ # Mark model as container and create association.
26
+ #
27
+ # Syntax is identical to +has_one+.
28
+ #
29
+ # has_one_attachment :attachment
30
+
31
+ def has_one_attachment(name, options = {})
32
+ reflection = has_one name, options
33
+ send(:define_method, reflection.name.to_s + '_=') do |attachment_id|
34
+ method, model = recover_vars(__method__)
35
+ find_and_add_attachment(method, model, attachment_id)
36
+ end
37
+ send :include, InstanceMethods
38
+ end
39
+
40
+ end
41
+
42
+ module InstanceMethods
43
+
44
+ def add_attachment(method, attachment) # :nodoc:
45
+ if reflections[method.to_sym].instance_variable_get :@collection
46
+ send(method) << attachment
47
+ else
48
+ old_attachment = send(method)
49
+ old_attachment.destroy unless old_attachment.nil?
50
+ send (method + '='), attachment
51
+ end
52
+ end
53
+
54
+ private
55
+
56
+ def recover_vars(method) # :nodoc:
57
+ method = method.to_s.chomp('_=')
58
+ model = reflections[method.to_sym].klass
59
+ [method, model]
60
+ end
61
+
62
+ def find_and_add_attachment(method, model, attachment_id) # :nodoc:
63
+ attachment = model.find_by_id attachment_id
64
+ return if attachment.nil?
65
+ return if attachment.attached?
66
+ add_attachment method, attachment
67
+ end
68
+
69
+ end
70
+
71
+ end
72
+
73
+ ActiveRecord::Base.extend SimpleAttachments::ContainerModel::Helpers