calagator 0.0.1.pre1

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 (384) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE.txt +23 -0
  3. data/README.md +75 -0
  4. data/Rakefile +12 -0
  5. data/app/assets/images/confused-alligator-sm.png +0 -0
  6. data/app/assets/images/disk.png +0 -0
  7. data/app/assets/images/edit.png +0 -0
  8. data/app/assets/images/external_sites/epdx.png +0 -0
  9. data/app/assets/images/external_sites/external.gif +0 -0
  10. data/app/assets/images/external_sites/facebook.png +0 -0
  11. data/app/assets/images/external_sites/foursquare.png +0 -0
  12. data/app/assets/images/external_sites/gowalla.png +0 -0
  13. data/app/assets/images/external_sites/lanyrd.png +0 -0
  14. data/app/assets/images/external_sites/meetup.png +0 -0
  15. data/app/assets/images/external_sites/plancast.png +0 -0
  16. data/app/assets/images/external_sites/shizzow.png +0 -0
  17. data/app/assets/images/external_sites/upcoming.png +0 -0
  18. data/app/assets/images/external_sites/yelp.png +0 -0
  19. data/app/assets/images/feed.png +0 -0
  20. data/app/assets/images/heart.png +0 -0
  21. data/app/assets/images/icon_ical.gif +0 -0
  22. data/app/assets/images/information.png +0 -0
  23. data/app/assets/images/nav_marker.gif +0 -0
  24. data/app/assets/images/nav_marker.png +0 -0
  25. data/app/assets/images/plus.png +0 -0
  26. data/app/assets/images/redx.png +0 -0
  27. data/app/assets/images/site-icon.png +0 -0
  28. data/app/assets/images/spinner.gif +0 -0
  29. data/app/assets/images/star.png +0 -0
  30. data/app/assets/images/subnav_marker.gif +0 -0
  31. data/app/assets/images/subnav_marker.png +0 -0
  32. data/app/assets/images/tag_blue.png +0 -0
  33. data/app/assets/images/tag_icons/angular.png +0 -0
  34. data/app/assets/images/tag_icons/beer.png +0 -0
  35. data/app/assets/images/tag_icons/bitcoin.png +0 -0
  36. data/app/assets/images/tag_icons/free.png +0 -0
  37. data/app/assets/images/tag_icons/golang.png +0 -0
  38. data/app/assets/images/tag_icons/html.png +0 -0
  39. data/app/assets/images/tag_icons/javascript.png +0 -0
  40. data/app/assets/images/tag_icons/linux.png +0 -0
  41. data/app/assets/images/tag_icons/php.png +0 -0
  42. data/app/assets/images/tag_icons/pizza.png +0 -0
  43. data/app/assets/images/tag_icons/python.png +0 -0
  44. data/app/assets/images/tag_icons/rails.png +0 -0
  45. data/app/assets/images/tag_icons/ruby.png +0 -0
  46. data/app/assets/images/tag_icons/sass.png +0 -0
  47. data/app/assets/images/tag_icons/swift.png +0 -0
  48. data/app/assets/images/transmit_blue.png +0 -0
  49. data/app/assets/images/weekday_background.gif +0 -0
  50. data/app/assets/javascripts/calagator.js +18 -0
  51. data/app/assets/javascripts/calagator/forms.js +60 -0
  52. data/app/assets/stylesheets/calagator.scss +8 -0
  53. data/app/assets/stylesheets/calagator/common.scss +14 -0
  54. data/app/assets/stylesheets/calagator/datepicker.scss +177 -0
  55. data/app/assets/stylesheets/calagator/errors.css +110 -0
  56. data/app/assets/stylesheets/calagator/forms.scss +4 -0
  57. data/app/assets/stylesheets/calagator/reset.css +40 -0
  58. data/app/assets/stylesheets/calagator/theme.css +0 -0
  59. data/app/controllers/calagator/admin_controller.rb +27 -0
  60. data/app/controllers/calagator/application_controller.rb +82 -0
  61. data/app/controllers/calagator/events_controller.rb +171 -0
  62. data/app/controllers/calagator/site_controller.rb +35 -0
  63. data/app/controllers/calagator/sources_controller.rb +94 -0
  64. data/app/controllers/calagator/venues_controller.rb +133 -0
  65. data/app/controllers/calagator/versions_controller.rb +20 -0
  66. data/app/helpers/calagator/application_helper.rb +128 -0
  67. data/app/helpers/calagator/events_helper.rb +184 -0
  68. data/app/helpers/calagator/google_event_export_helper.rb +67 -0
  69. data/app/helpers/calagator/mapping_helper.rb +103 -0
  70. data/app/helpers/calagator/sources_helper.rb +10 -0
  71. data/app/helpers/calagator/tags_helper.rb +42 -0
  72. data/app/helpers/calagator/time_range_helper.rb +166 -0
  73. data/app/models/calagator/event.rb +246 -0
  74. data/app/models/calagator/event/cloner.rb +39 -0
  75. data/app/models/calagator/event/ical_renderer.rb +155 -0
  76. data/app/models/calagator/event/overview.rb +45 -0
  77. data/app/models/calagator/event/saver.rb +58 -0
  78. data/app/models/calagator/event/search.rb +72 -0
  79. data/app/models/calagator/event/search_engine.rb +28 -0
  80. data/app/models/calagator/event/search_engine/apache_sunspot.rb +106 -0
  81. data/app/models/calagator/event/search_engine/sql.rb +107 -0
  82. data/app/models/calagator/source.rb +115 -0
  83. data/app/models/calagator/source/importer.rb +46 -0
  84. data/app/models/calagator/source/parser.rb +128 -0
  85. data/app/models/calagator/source/parser/facebook.rb +67 -0
  86. data/app/models/calagator/source/parser/hcal.rb +108 -0
  87. data/app/models/calagator/source/parser/http_authentication_required_error.rb +6 -0
  88. data/app/models/calagator/source/parser/ical.rb +186 -0
  89. data/app/models/calagator/source/parser/meetup.rb +72 -0
  90. data/app/models/calagator/source/parser/not_found.rb +9 -0
  91. data/app/models/calagator/source/parser/plancast.rb +59 -0
  92. data/app/models/calagator/venue.rb +161 -0
  93. data/app/models/calagator/venue/geocoder.rb +51 -0
  94. data/app/models/calagator/venue/search.rb +63 -0
  95. data/app/models/calagator/venue/search_engine.rb +24 -0
  96. data/app/models/calagator/venue/search_engine/apache_sunspot.rb +85 -0
  97. data/app/models/calagator/venue/search_engine/sql.rb +68 -0
  98. data/app/models/event/search_engine/base.rb +0 -0
  99. data/app/observers/calagator/cache_observer.rb +37 -0
  100. data/app/views/calagator/admin/events.html.erb +28 -0
  101. data/app/views/calagator/admin/index.html.erb +8 -0
  102. data/app/views/calagator/events/_feed_item.html.erb +62 -0
  103. data/app/views/calagator/events/_form.html.erb +63 -0
  104. data/app/views/calagator/events/_gcal_reminder.html.erb +1 -0
  105. data/app/views/calagator/events/_hcal.html.erb +41 -0
  106. data/app/views/calagator/events/_item.html.erb +120 -0
  107. data/app/views/calagator/events/_list.html.erb +30 -0
  108. data/app/views/calagator/events/_list_item.html.erb +37 -0
  109. data/app/views/calagator/events/_search_section.html.erb +15 -0
  110. data/app/views/calagator/events/_subnav.html.erb +13 -0
  111. data/app/views/calagator/events/_table.html.erb +74 -0
  112. data/app/views/calagator/events/duplicates.html.erb +58 -0
  113. data/app/views/calagator/events/edit.html.erb +3 -0
  114. data/app/views/calagator/events/index.atom.builder +32 -0
  115. data/app/views/calagator/events/index.html.erb +51 -0
  116. data/app/views/calagator/events/index.kml.erb +20 -0
  117. data/app/views/calagator/events/new.html.erb +7 -0
  118. data/app/views/calagator/events/search.html.erb +25 -0
  119. data/app/views/calagator/events/show.html.erb +81 -0
  120. data/app/views/calagator/site/_appropriateness_message.html.erb +15 -0
  121. data/app/views/calagator/site/_description.html.erb +3 -0
  122. data/app/views/calagator/site/about.html.erb +7 -0
  123. data/app/views/calagator/site/defunct.html.erb +15 -0
  124. data/app/views/calagator/site/export.html.erb +4 -0
  125. data/app/views/calagator/site/index.html.erb +40 -0
  126. data/app/views/calagator/site/opensearch.xml.builder +8 -0
  127. data/app/views/calagator/sources/_subnav.html.erb +0 -0
  128. data/app/views/calagator/sources/edit.html.erb +12 -0
  129. data/app/views/calagator/sources/import.html.erb +10 -0
  130. data/app/views/calagator/sources/index.html.erb +22 -0
  131. data/app/views/calagator/sources/new.html.erb +32 -0
  132. data/app/views/calagator/sources/show.html.erb +16 -0
  133. data/app/views/calagator/venues/_form.html.erb +57 -0
  134. data/app/views/calagator/venues/_subnav.html.erb +10 -0
  135. data/app/views/calagator/venues/duplicates.html.erb +65 -0
  136. data/app/views/calagator/venues/edit.html.erb +3 -0
  137. data/app/views/calagator/venues/index.html.erb +93 -0
  138. data/app/views/calagator/venues/index.kml.erb +15 -0
  139. data/app/views/calagator/venues/map.html.erb +4 -0
  140. data/app/views/calagator/venues/new.html.erb +5 -0
  141. data/app/views/calagator/venues/show.html.erb +113 -0
  142. data/app/views/calagator/versions/_chooser.html.erb +28 -0
  143. data/app/views/calagator/versions/_edit_with_chooser.html.erb +16 -0
  144. data/app/views/layouts/calagator/application.html.erb +110 -0
  145. data/config/deploy/local.rb +37 -0
  146. data/config/deploy/lucca.rb +33 -0
  147. data/config/initializers/dates.rb +7 -0
  148. data/config/initializers/formtastic.rb +82 -0
  149. data/config/initializers/geokit.rb +74 -0
  150. data/config/initializers/ics_renderer.rb +6 -0
  151. data/config/initializers/load_tag_model_extensions.rb +3 -0
  152. data/config/initializers/mime_types.rb +9 -0
  153. data/config/initializers/observers.rb +1 -0
  154. data/config/initializers/search_engine.rb +4 -0
  155. data/config/initializers/set_default_url_host.rb +5 -0
  156. data/config/initializers/time_get_zone.rb +8 -0
  157. data/config/locales/en.yml +5 -0
  158. data/config/routes.rb +55 -0
  159. data/config/secrets.yml.blag +75 -0
  160. data/config/sunspot.yml +23 -0
  161. data/db/development.sqlite3 +0 -0
  162. data/db/development.sqlite3.bak +0 -0
  163. data/db/development.sqlite3.old +0 -0
  164. data/db/development~20111112@110950.sqlite3 +0 -0
  165. data/db/migrate/001_create_events.rb +17 -0
  166. data/db/migrate/002_create_venues.rb +17 -0
  167. data/db/migrate/003_create_sources.rb +16 -0
  168. data/db/migrate/004_add_detailed_fields_to_venue.rb +19 -0
  169. data/db/migrate/005_add_end_time_to_events.rb +9 -0
  170. data/db/migrate/006_add_source_id_to_events.rb +9 -0
  171. data/db/migrate/008_add_source_id_to_venues.rb +10 -0
  172. data/db/migrate/009_add_duplicate_of_column_to_venues.rb +9 -0
  173. data/db/migrate/010_add_duplicate_of_column_to_events.rb +9 -0
  174. data/db/migrate/011_change_lat_long_type.rb +12 -0
  175. data/db/migrate/012_add_source_reimport.rb +9 -0
  176. data/db/migrate/013_change_end_time_to_duration.rb +11 -0
  177. data/db/migrate/014_remove_format_type_from_source.rb +9 -0
  178. data/db/migrate/015_create_updates.rb +15 -0
  179. data/db/migrate/016_remove_next_update_from_source.rb +9 -0
  180. data/db/migrate/20080705163959_change_duration_to_end_time.rb +11 -0
  181. data/db/migrate/20080705164959_create_tags_and_taggings.rb +28 -0
  182. data/db/migrate/20081011181519_create_versioned_events.rb +25 -0
  183. data/db/migrate/20081011193124_create_versioned_venues.rb +32 -0
  184. data/db/migrate/20081115190515_add_rrule_to_events.rb +15 -0
  185. data/db/migrate/20090912082129_create_versions.rb +18 -0
  186. data/db/migrate/20110219205156_add_closed_flag_to_venues.rb +9 -0
  187. data/db/migrate/20110220001008_add_wifi_flag_to_venues.rb +9 -0
  188. data/db/migrate/20110220011427_add_access_notes_to_venues.rb +9 -0
  189. data/db/migrate/20110220031117_add_events_count_to_venues.rb +8 -0
  190. data/db/migrate/20110604174521_add_venue_details_to_events.rb +9 -0
  191. data/db/migrate/20110717231316_acts_as_taggable_on_migration.rb +50 -0
  192. data/db/migrate/20120709092821_cleanup.rb +14 -0
  193. data/db/migrate/20120831234448_specify_venues_latitude_and_longitude_precision.rb +11 -0
  194. data/db/migrate/20150206085809_remove_updates.rb +13 -0
  195. data/db/migrate/20150207231355_add_locked_status_to_events.rb +5 -0
  196. data/db/production.sqlite3 +0 -0
  197. data/db/schema.rb +102 -0
  198. data/db/seeds.rb +16 -0
  199. data/db/test.sqlite3 +0 -0
  200. data/db/test2.sqlite3 +0 -0
  201. data/lib/calagator.rb +30 -0
  202. data/lib/calagator/blacklist_validator.rb +69 -0
  203. data/lib/calagator/decode_html_entities_hack.rb +33 -0
  204. data/lib/calagator/duplicate_checking.rb +133 -0
  205. data/lib/calagator/duplicate_checking/controller_actions.rb +38 -0
  206. data/lib/calagator/duplicate_checking/duplicate_finder.rb +83 -0
  207. data/lib/calagator/duplicate_checking/duplicate_squasher.rb +74 -0
  208. data/lib/calagator/engine.rb +30 -0
  209. data/lib/calagator/strip_whitespace.rb +19 -0
  210. data/lib/calagator/tag_model_extensions.rb +104 -0
  211. data/lib/calagator/url_prefixer.rb +9 -0
  212. data/lib/calagator/version.rb +3 -0
  213. data/lib/generators/calagator/install_generator.rb +39 -0
  214. data/lib/generators/calagator/templates/config/calagator.rb +26 -0
  215. data/lib/generators/calagator/templates/config/secrets.yml.sample +83 -0
  216. data/lib/secrets_reader.rb +76 -0
  217. data/lib/tasks/spec_db.rake +53 -0
  218. data/lib/tasks/sunspot_reindex_calagator.rake +6 -0
  219. data/lib/tasks/sunspot_solr_restart_enhancements.rake +19 -0
  220. data/lib/tasks/update_counter_caches.rake +13 -0
  221. data/lib/templates/erb/scaffold/_form.html.erb +11 -0
  222. data/lib/theme_reader.rb +17 -0
  223. data/lib/wait_for_solr.rb +25 -0
  224. data/spec/controllers/calagator/application_controller_spec.rb +47 -0
  225. data/spec/controllers/calagator/events_controller_spec.rb +794 -0
  226. data/spec/controllers/calagator/site_controller_spec.rb +59 -0
  227. data/spec/controllers/calagator/sources_controller_spec.rb +439 -0
  228. data/spec/controllers/calagator/venues_controller_spec.rb +319 -0
  229. data/spec/controllers/calagator/versions_controller_spec.rb +82 -0
  230. data/spec/controllers/squash_many_duplicates_examples.rb +49 -0
  231. data/spec/dummy/Gemfile +39 -0
  232. data/spec/dummy/Gemfile.lock +195 -0
  233. data/spec/dummy/README.rdoc +261 -0
  234. data/spec/dummy/Rakefile +7 -0
  235. data/spec/dummy/app/assets/images/rails.png +0 -0
  236. data/spec/dummy/app/assets/javascripts/application.js +16 -0
  237. data/spec/dummy/app/assets/stylesheets/application.css +14 -0
  238. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  239. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  240. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  241. data/spec/dummy/config.ru +4 -0
  242. data/spec/dummy/config/application.rb +62 -0
  243. data/spec/dummy/config/boot.rb +6 -0
  244. data/spec/dummy/config/database.yml +25 -0
  245. data/spec/dummy/config/environment.rb +5 -0
  246. data/spec/dummy/config/environments/development.rb +37 -0
  247. data/spec/dummy/config/environments/production.rb +67 -0
  248. data/spec/dummy/config/environments/test.rb +37 -0
  249. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  250. data/spec/dummy/config/initializers/calagator.rb +26 -0
  251. data/spec/dummy/config/initializers/inflections.rb +15 -0
  252. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  253. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  254. data/spec/dummy/config/initializers/session_store.rb +8 -0
  255. data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
  256. data/spec/dummy/config/locales/en.yml +5 -0
  257. data/spec/dummy/config/routes.rb +59 -0
  258. data/spec/dummy/config/secrets.yml +83 -0
  259. data/spec/dummy/db/development.sqlite3 +0 -0
  260. data/spec/dummy/db/migrate/20150309023304_create_events.calagator.rb +18 -0
  261. data/spec/dummy/db/migrate/20150309023305_create_venues.calagator.rb +18 -0
  262. data/spec/dummy/db/migrate/20150309023306_create_sources.calagator.rb +17 -0
  263. data/spec/dummy/db/migrate/20150309023307_add_detailed_fields_to_venue.calagator.rb +20 -0
  264. data/spec/dummy/db/migrate/20150309023308_add_end_time_to_events.calagator.rb +10 -0
  265. data/spec/dummy/db/migrate/20150309023309_add_source_id_to_events.calagator.rb +10 -0
  266. data/spec/dummy/db/migrate/20150309023310_add_source_id_to_venues.calagator.rb +11 -0
  267. data/spec/dummy/db/migrate/20150309023311_add_duplicate_of_column_to_venues.calagator.rb +10 -0
  268. data/spec/dummy/db/migrate/20150309023312_add_duplicate_of_column_to_events.calagator.rb +10 -0
  269. data/spec/dummy/db/migrate/20150309023313_change_lat_long_type.calagator.rb +13 -0
  270. data/spec/dummy/db/migrate/20150309023314_add_source_reimport.calagator.rb +10 -0
  271. data/spec/dummy/db/migrate/20150309023315_change_end_time_to_duration.calagator.rb +12 -0
  272. data/spec/dummy/db/migrate/20150309023316_remove_format_type_from_source.calagator.rb +10 -0
  273. data/spec/dummy/db/migrate/20150309023317_create_updates.calagator.rb +16 -0
  274. data/spec/dummy/db/migrate/20150309023318_remove_next_update_from_source.calagator.rb +10 -0
  275. data/spec/dummy/db/migrate/20150309023319_change_duration_to_end_time.calagator.rb +12 -0
  276. data/spec/dummy/db/migrate/20150309023320_create_tags_and_taggings.calagator.rb +29 -0
  277. data/spec/dummy/db/migrate/20150309023321_create_versioned_events.calagator.rb +26 -0
  278. data/spec/dummy/db/migrate/20150309023322_create_versioned_venues.calagator.rb +33 -0
  279. data/spec/dummy/db/migrate/20150309023323_add_rrule_to_events.calagator.rb +16 -0
  280. data/spec/dummy/db/migrate/20150309023324_create_versions.calagator.rb +19 -0
  281. data/spec/dummy/db/migrate/20150309023325_add_closed_flag_to_venues.calagator.rb +10 -0
  282. data/spec/dummy/db/migrate/20150309023326_add_wifi_flag_to_venues.calagator.rb +10 -0
  283. data/spec/dummy/db/migrate/20150309023327_add_access_notes_to_venues.calagator.rb +10 -0
  284. data/spec/dummy/db/migrate/20150309023328_add_events_count_to_venues.calagator.rb +9 -0
  285. data/spec/dummy/db/migrate/20150309023329_add_venue_details_to_events.calagator.rb +10 -0
  286. data/spec/dummy/db/migrate/20150309023330_acts_as_taggable_on_migration.calagator.rb +51 -0
  287. data/spec/dummy/db/migrate/20150309023331_cleanup.calagator.rb +15 -0
  288. data/spec/dummy/db/migrate/20150309023332_specify_venues_latitude_and_longitude_precision.calagator.rb +12 -0
  289. data/spec/dummy/db/migrate/20150309023333_remove_updates.calagator.rb +14 -0
  290. data/spec/dummy/db/migrate/20150309023334_add_locked_status_to_events.calagator.rb +6 -0
  291. data/spec/dummy/db/schema.rb +95 -0
  292. data/spec/dummy/db/seeds.rb +7 -0
  293. data/spec/dummy/db/test.sqlite3 +0 -0
  294. data/spec/dummy/doc/README_FOR_APP +2 -0
  295. data/spec/dummy/log/development.log +273 -0
  296. data/spec/dummy/public/404.html +26 -0
  297. data/spec/dummy/public/422.html +26 -0
  298. data/spec/dummy/public/500.html +25 -0
  299. data/spec/dummy/public/favicon.ico +0 -0
  300. data/spec/dummy/public/robots.txt +5 -0
  301. data/spec/dummy/script/rails +6 -0
  302. data/spec/dummy/test/performance/browsing_test.rb +12 -0
  303. data/spec/dummy/test/test_helper.rb +13 -0
  304. data/spec/factories.rb +93 -0
  305. data/spec/features/add_event_spec.rb +99 -0
  306. data/spec/features/add_venue_spec.rb +34 -0
  307. data/spec/features/admin_auth_spec.rb +22 -0
  308. data/spec/features/admin_lock_event_spec.rb +41 -0
  309. data/spec/features/import_events_from_feed_spec.rb +43 -0
  310. data/spec/features/managing_event_spec.rb +111 -0
  311. data/spec/features/managing_venue_spec.rb +71 -0
  312. data/spec/features/search_event_spec.rb +27 -0
  313. data/spec/helpers/calagator/application_helper_spec.rb +82 -0
  314. data/spec/helpers/calagator/events_helper_spec.rb +172 -0
  315. data/spec/helpers/calagator/google_event_export_helper_spec.rb +70 -0
  316. data/spec/helpers/calagator/sources_helper_spec.rb +12 -0
  317. data/spec/helpers/calagator/tags_helper_spec.rb +85 -0
  318. data/spec/helpers/calagator/time_range_helper_spec.rb +59 -0
  319. data/spec/lib/calagator/blacklist_validator_spec.rb +65 -0
  320. data/spec/lib/calagator/decode_html_entities_hack_spec.rb +54 -0
  321. data/spec/lib/calagator/settings_spec.rb +20 -0
  322. data/spec/lib/calagator/url_prefixer_spec.rb +33 -0
  323. data/spec/lib/secrets_reader_spec.rb +65 -0
  324. data/spec/models/calagator/event/cloner_spec.rb +43 -0
  325. data/spec/models/calagator/event/overview_spec.rb +79 -0
  326. data/spec/models/calagator/event/search_spec.rb +103 -0
  327. data/spec/models/calagator/event_search_spec.rb +149 -0
  328. data/spec/models/calagator/event_spec.rb +859 -0
  329. data/spec/models/calagator/source/parser_facebook_spec.rb +73 -0
  330. data/spec/models/calagator/source/parser_hcal_spec.rb +69 -0
  331. data/spec/models/calagator/source/parser_ical_non_standard_spec.rb +91 -0
  332. data/spec/models/calagator/source/parser_ical_spec.rb +322 -0
  333. data/spec/models/calagator/source/parser_meetup_spec.rb +69 -0
  334. data/spec/models/calagator/source/parser_plancast_spec.rb +53 -0
  335. data/spec/models/calagator/source/parser_spec.rb +238 -0
  336. data/spec/models/calagator/source_spec.rb +135 -0
  337. data/spec/models/calagator/venue/search_spec.rb +92 -0
  338. data/spec/models/calagator/venue_search_spec.rb +124 -0
  339. data/spec/models/calagator/venue_spec.rb +346 -0
  340. data/spec/models/tag_spec.rb +35 -0
  341. data/spec/rails_helper.rb +39 -0
  342. data/spec/spec_helper.rb +140 -0
  343. data/spec/support/disable_geocoding.rb +1 -0
  344. data/spec/support/http_samples.rb +5 -0
  345. data/spec/support/samples/facebook.json +23 -0
  346. data/spec/support/samples/hcal_basic.xml +6 -0
  347. data/spec/support/samples/hcal_dup_event_dup_venue.xml +13 -0
  348. data/spec/support/samples/hcal_event_duplicates_fixture.xml +13 -0
  349. data/spec/support/samples/hcal_event_wo_lat_and_long.xml +14 -0
  350. data/spec/support/samples/hcal_multiple.xml +16 -0
  351. data/spec/support/samples/hcal_same_event_twice_with_different_venues.xml +12 -0
  352. data/spec/support/samples/hcal_single.xml +8 -0
  353. data/spec/support/samples/hcal_two_identical_events.xml +14 -0
  354. data/spec/support/samples/hcal_upcoming_v1.html +412 -0
  355. data/spec/support/samples/hcal_upcoming_v2.html +749 -0
  356. data/spec/support/samples/hcal_upcoming_v3.html +685 -0
  357. data/spec/support/samples/hcal_upcoming_v4.html +761 -0
  358. data/spec/support/samples/ical_apple.ics +22 -0
  359. data/spec/support/samples/ical_apple_v3.ics +37 -0
  360. data/spec/support/samples/ical_basic.ics +15 -0
  361. data/spec/support/samples/ical_basic_with_duration.ics +16 -0
  362. data/spec/support/samples/ical_event_with_squashed_venue.ics +12 -0
  363. data/spec/support/samples/ical_eventful_many.ics +504 -0
  364. data/spec/support/samples/ical_gmt.ics +12 -0
  365. data/spec/support/samples/ical_google.ics +786 -0
  366. data/spec/support/samples/ical_multiple_calendars.ics +111 -0
  367. data/spec/support/samples/ical_upcoming.ics +36 -0
  368. data/spec/support/samples/ical_upcoming_many.ics +682 -0
  369. data/spec/support/samples/ical_upcoming_v2.ics +43 -0
  370. data/spec/support/samples/ical_z.ics +10 -0
  371. data/spec/support/samples/meetup.ics +16 -0
  372. data/spec/support/samples/meetup.json +31 -0
  373. data/spec/support/samples/plancast.ics +59 -0
  374. data/spec/support/samples/plancast.json +51 -0
  375. data/spec/support/samples/plancast_with_missing_venue.json +39 -0
  376. data/spec/support/samples/upcoming_v1.xml +8 -0
  377. data/spec/support/samples/upcoming_v2_with_invalid_utc_dates.xml +8 -0
  378. data/spec/support/time_convenience_methods.rb +8 -0
  379. data/spec/support/time_zones.rb +12 -0
  380. data/spec/support/url_helpers.rb +5 -0
  381. data/spec/support/wait_for_ajax.rb +15 -0
  382. data/spec/support/webmock.rb +8 -0
  383. data/spec/travis_spec.rb +7 -0
  384. metadata +1194 -0
@@ -0,0 +1,30 @@
1
+ module Calagator
2
+ class Engine < ::Rails::Engine
3
+ isolate_namespace Calagator
4
+
5
+ config.before_initialize do
6
+ # Read secrets
7
+ require 'secrets_reader'
8
+ ::SECRETS = SecretsReader.read
9
+ end
10
+ end
11
+
12
+ # settings with defaults
13
+ class << self
14
+ mattr_accessor :title, :tagline, :url, :venues_map_options, :blacklist_patterns
15
+
16
+ self.title = 'Calagator'
17
+ self.tagline = 'A Tech Calendar'
18
+ self.url = 'http://my-calagator.org/'
19
+ self.venues_map_options = {}
20
+ self.blacklist_patterns = [
21
+ /\b(online|overseas).+(drugstore|pharmacy)\b/,
22
+ /\bcialis\b/,
23
+ ]
24
+
25
+ # map the attrs from initializer
26
+ def setup(&block)
27
+ yield self
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,19 @@
1
+ module StripWhitespace
2
+ def self.included(base)
3
+ base.extend(ClassMethods)
4
+ end
5
+
6
+ module ClassMethods
7
+ def strip_whitespace!(*fields)
8
+ before_validation do |record|
9
+ fields.each do |field|
10
+ setter = "#{field}=".to_sym
11
+ value = record.send(field.to_sym)
12
+ if value.respond_to?(:strip) and record.respond_to?(setter)
13
+ record.send(setter, value.strip)
14
+ end
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,104 @@
1
+ # We're extending ActsAsTaggableOn's Tag model to include support for machine tags and such.
2
+ module Calagator
3
+
4
+ module TagModelExtensions
5
+ def self.included(base)
6
+ base.class_eval do
7
+ scope :machine_tags, where("name LIKE '%:%=%'")
8
+ end
9
+ end
10
+
11
+ #---[ Machine tags ]----------------------------------------------------
12
+
13
+ # Structure of machine tag namespaces and predicates to their URLs. See
14
+ # #machine_tag for details.
15
+ MACHINE_TAG_URLS = {
16
+ 'epdx' => {
17
+ 'company' => 'http://epdx.org/companies/%s',
18
+ 'group' => 'http://epdx.org/groups/%s',
19
+ 'person' => 'http://epdx.org/people/%s',
20
+ 'project' => 'http://epdx.org/projects/%s',
21
+ },
22
+ 'upcoming' => {
23
+ 'event' => "http://upcoming.yahoo.com/event/%s",
24
+ 'venue' => "http://upcoming.yahoo.com/venue/%s"
25
+ },
26
+ 'plancast' => {
27
+ 'activity' => "http://plancast.com/a/%s",
28
+ 'plan' => "http://plancast.com/p/%s"
29
+ },
30
+ 'yelp' => {
31
+ 'biz' => "http://www.yelp.com/biz/%s"
32
+ },
33
+ 'foursquare' => {
34
+ 'venue' => "http://foursquare.com/venue/%s"
35
+ },
36
+ 'gowalla' => {
37
+ 'spot' => "http://gowalla.com/spots/%s"
38
+ },
39
+ 'shizzow' => {
40
+ 'place' => "http://www.shizzow.com/places/%s"
41
+ },
42
+ 'meetup' => {
43
+ 'group' => "http://www.meetup.com/%s"
44
+ },
45
+ 'facebook' => {
46
+ 'event' => "http://www.facebook.com/event.php?eid=%s"
47
+ },
48
+ 'lanyrd' => {
49
+ 'event' => "http://lanyrd.com/%s"
50
+ }
51
+ } unless defined?(MACHINE_TAG_URLS)
52
+
53
+ # Regular expression for parsing machine tags
54
+ MACHINE_TAG_PATTERN = /([^:]+):([^=]+)=(.+)/ unless defined?(MACHINE_TAG_PATTERN)
55
+
56
+ # Machine tag predicates that refer to place entries
57
+ VENUE_PREDICATES = %w(venue place spot biz) unless defined?(VENUE_PREDICATES)
58
+
59
+ # Return a machine tag hash for this tag, or an empty hash if this isn't a
60
+ # machine tag. The hash will always contain :namespace, :predicate and :value
61
+ # key-value pairs. It may also contain an :url if one is known.
62
+ #
63
+ # Machine tags describe references to remote resources. For example, a
64
+ # Calagator event imported from an Meetup event may have a machine
65
+ # linking it back to the Meetup event.
66
+ #
67
+ # Example:
68
+ # # A tag named "meetup:group=1234" will produce this machine tag:
69
+ # tag.machine_tag == {
70
+ # :namespace => "meetup",
71
+ # :predicate => "group",
72
+ # :value => "1234",
73
+ # :url => "http://www.meetup.com/1234",
74
+ def machine_tag
75
+ if components = self.name.match(MACHINE_TAG_PATTERN)
76
+ namespace, predicate, value = components.captures
77
+
78
+ result = {
79
+ :namespace => namespace,
80
+ :predicate => predicate,
81
+ :value => value,
82
+ }
83
+
84
+ if machine_tag = MACHINE_TAG_URLS[namespace]
85
+ if url_template = machine_tag[predicate]
86
+ result[:url] = sprintf(url_template, value)
87
+ if namespace =~ /\A(upcoming|gowalla|shizzow)\Z/
88
+ domain = "http://localhost:3000" if Rails.env.development? || Rails.env.test?
89
+ domain = "http://calagator.org" if Rails.env.production?
90
+ archive_date = Event.tagged_with(self).first.start_time.strftime("%Y%m%d") if Event.tagged_with(self).first
91
+ archive_date = Venue.tagged_with(self).first.created_at.strftime("%Y%m%d") if Venue.tagged_with(self).first
92
+ result[:url] = "#{domain}/defunct?url=https://web.archive.org/web/#{archive_date}/#{result[:url]}"
93
+ end
94
+ end
95
+ end
96
+
97
+ return result
98
+ else
99
+ return {}
100
+ end
101
+ end
102
+ end
103
+
104
+ end
@@ -0,0 +1,9 @@
1
+ class UrlPrefixer
2
+ def self.prefix(value)
3
+ if value.blank? || value.include?("://")
4
+ value
5
+ else
6
+ "http://#{value.lstrip}"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,3 @@
1
+ module Calagator
2
+ VERSION = "0.0.1.pre1"
3
+ end
@@ -0,0 +1,39 @@
1
+ module Calagator
2
+ class InstallGenerator < Rails::Generators::Base
3
+ source_root File.expand_path('../templates', __FILE__)
4
+
5
+ def install
6
+ add_route
7
+ add_secrets
8
+ add_initializer
9
+ add_javascripts
10
+ add_stylesheets
11
+ rake 'calagator:install:migrations'
12
+ rake 'db:migrate'
13
+ rake 'db:test:prepare'
14
+ run 'rm -f public/index.html'
15
+ end
16
+
17
+ private
18
+
19
+ def add_route
20
+ inject_into_file 'config/routes.rb', "\s\smount Calagator::Engine => '/'\n", after: "Application.routes.draw do\n"
21
+ end
22
+
23
+ def add_secrets
24
+ copy_file File.expand_path(File.join(__FILE__, '../templates/config/secrets.yml.sample')), 'config/secrets.yml'
25
+ end
26
+
27
+ def add_initializer
28
+ copy_file File.expand_path(File.join(__FILE__, '../templates/config/calagator.rb')), 'config/initializers/calagator.rb'
29
+ end
30
+
31
+ def add_javascripts
32
+ append_file 'app/assets/javascripts/application.js', '//= require calagator'
33
+ end
34
+
35
+ def add_stylesheets
36
+ append_file 'app/assets/stylesheets/application.css', '//= require calagator'
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,26 @@
1
+ Calagator.setup do |config|
2
+
3
+ # # Site's name
4
+ # config.title = 'Calagator'
5
+
6
+ # # Site's tagline
7
+ # config.tagline = 'A Tech Calendar'
8
+
9
+ # # Site's URL with trailing slash
10
+ # config.url = 'http://my-calagator.org/'
11
+
12
+ # # Map to display on /venues page:
13
+ # config.venues_map_options = {
14
+ # # Zoom magnification level:
15
+ # zoom: 12,
16
+ # # Center of the map, in latitude and longitude.
17
+ # # If no center is specified, the map will zoom to fit all markers.
18
+ # center: [45.518493, -122.660737]
19
+ # }
20
+
21
+ # # Patterns for detecting spam events and venues
22
+ # config.blacklist_patterns = [
23
+ # /\b(online|overseas).+(drugstore|pharmacy)\b/,
24
+ # /\bcialis\b/,
25
+ # ]
26
+ end
@@ -0,0 +1,83 @@
1
+ #===[ Secrets ]=========================================================
2
+ #
3
+ # This file is meant for storing secret information that is never
4
+ # published or committed to a revision control system.
5
+ #
6
+ # Do not modify this "config/secrets.yml.sample" file directly -- you
7
+ # should copy it to "config/secrets.yml" and customize it there.
8
+ #
9
+ #---[ Values ]----------------------------------------------------------
10
+
11
+ # Email address of administrator that will get exception notifications
12
+ # and requests for assistance from users:
13
+ administrator_email: 'your@email.addr'
14
+
15
+ # Admin username and password to use when accessing /admin pages
16
+ admin_username: 'admin'
17
+ admin_password: 'kitties!'
18
+
19
+ # Secret code for verifying cookie session data integrity. If you change it,
20
+ # all old sessions will become invalid! Make sure the secret is at least 30
21
+ # characters and all random, no regular words or you'll be exposed to
22
+ # dictionary attacks.
23
+ session_secret: '1290832312281326461234712c347134618233441234513341132032545424856956711678856985f0575586671765c678659e7855bd58c6978856178b56e8f6'
24
+
25
+ # Name to use for storing application's session cookies, this is often a
26
+ # shortened form of your organization and application name, e.g.,
27
+ # "igniteportlandproposals", "igniteproposals", "openproposals", etc:
28
+ session_name: 'calagator'
29
+
30
+ # API key for Meetup.com, get your own from: http://www.meetup.com/meetup_api/key/
31
+ # meetup_api_key: registerNow
32
+
33
+ # Search engine to use for searching events, uncomment the line to specify that
34
+ # search engine. Defaults to 'sql'. For further information, see `INSTALL.md`.
35
+ ### search_engine: sql
36
+ ### search_engine: sunspot
37
+
38
+ # Configure a mapping provider
39
+ # Stamen's terrain tiles will be used by default.
40
+ mapping:
41
+ # Map marker color
42
+ # Values: red, darkred, orange, green, darkgreen, blue, purple, darkpuple, cadetblue
43
+ marker_color: green
44
+
45
+ # A Google Maps API key is required to use Google's geocoding service
46
+ # as well as to display maps using their API.
47
+ #
48
+ # Get one at: https://developers.google.com/maps/documentation/javascript/tutorial#api_key
49
+ google_maps_api_key: <your google maps v3 API key>
50
+
51
+ # The tile provider to use when rendering maps with Leaflet.
52
+ # One of: leaflet, stamen, mapbox, google
53
+ # provider: stamen
54
+ #
55
+ # The tiles to use for the map, see the docs for individual Leaflet plugins.
56
+ # For stamen, this can be one of: terrain, toner, watercolor
57
+ # tiles: terrain
58
+ #
59
+ #== Examples ==
60
+ # Stamen
61
+ # (available tiles: terrain, toner, watercolor)
62
+ # provider: stamen
63
+ # tiles: watercolor
64
+ #
65
+ # MapBox Streets (use a map from your own account)
66
+ # provider: mapbox
67
+ # tiles: examples.map-9ijuk24y
68
+ #
69
+ # Google Maps
70
+ # provider: google
71
+ # tiles: ROADMAP
72
+ # google_maps_api_key: <your google maps v3 API key>
73
+ #
74
+ # OpenStreetMap
75
+ # provider: leaflet
76
+ # tiles: http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png
77
+ #
78
+ # Esri
79
+ # (available tiles: Gray, Streets, Oceans, Topographic)
80
+ # provider: esri
81
+ # tiles: Gray
82
+
83
+ #===[ fin ]=============================================================
@@ -0,0 +1,76 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+ require 'ostruct'
4
+ require 'set'
5
+
6
+ # = SecretsReader
7
+ #
8
+ # Reads secrets from an ERB-parsed YAML file and returns an OpenStruct object.
9
+ #
10
+ # Examples:
11
+ # # Read from default "config/secrets.yml" and "config/secrets.yml.sample" files:
12
+ # Secrets = SecretsReader.read
13
+ #
14
+ # # Read a specific file:
15
+ # Secrets = SecretsReader.read("myfile.yml") #
16
+ #
17
+ class SecretsReader
18
+ # Return an OpenStruct object with secret information. The secrets are read
19
+ # from an ERB-parsed YAML file.
20
+ #
21
+ # Arguments:
22
+ # * Filename to read secrets from. Optional, if not given will try
23
+ # "config/secret.yml" and "config/secret.yml.sample".
24
+ #
25
+ # Options:
26
+ # * :verbose => Print status to screen on error. Defaults to true.
27
+ # * :silent => Display nothing, not even errors. Defaults to false.
28
+ def self.read(*args)
29
+ given_file = args.first.kind_of?(String) ? args.first : nil
30
+ opts = args.last.kind_of?(Hash) ? args.last : {}
31
+ verbose = opts[:verbose] != false
32
+ silent = opts[:silent] == true
33
+
34
+ normal_file = "config/secrets.yml"
35
+ sample_file = "config/secrets.yml.sample"
36
+ rails_root = defined?(Rails) ? ::Rails.root : File.dirname(File.dirname(__FILE__))
37
+
38
+ message = ""
39
+ error = false
40
+
41
+ if object = self.filename_to_ostruct(given_file)
42
+ message << "loaded '#{given_file}'"
43
+ elsif object = self.filename_to_ostruct(File.join(rails_root, normal_file))
44
+ message << "loaded '#{normal_file}'"
45
+ elsif object = self.filename_to_ostruct(File.join(rails_root, sample_file))
46
+ message << "WARNING! Using insecure '#{sample_file}' settings, see 'Security' in INSTALL.md" unless defined?($INSECURE_SECRETS)
47
+ $INSECURE_SECRETS = true
48
+ error = true
49
+ else
50
+ object = OpenStruct.new
51
+ message << "Couldn't find '#{normal_file}'"
52
+ error = true
53
+ end
54
+
55
+ unless silent
56
+ if message.present?
57
+ message = "** SecretsReader - #{message}"
58
+ puts message if error
59
+ if message.present? && defined?(Rails)
60
+ Rails.logger.info(message)
61
+ end
62
+ end
63
+ end
64
+
65
+ return object
66
+ end
67
+
68
+ # Return an OpenStruct object by reading the +filename+ and parsing it with ERB and YAML.
69
+ def self.filename_to_ostruct(filename)
70
+ if filename.nil? or not File.exist?(filename)
71
+ return nil
72
+ else
73
+ return OpenStruct.new(YAML.load(ERB.new(File.read(filename)).result))
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,53 @@
1
+ namespace :spec do
2
+ namespace :db do
3
+ databases = [:postgresql, :mysql, :sqlite3]
4
+
5
+ desc "Run specs against all databases"
6
+ task :all do
7
+ failed = false
8
+
9
+ databases.each do |database|
10
+ test_against database
11
+ end
12
+ end
13
+
14
+ databases.each do |database|
15
+ desc "Run specs against '#{database}' database"
16
+ task database do
17
+ return test_against database
18
+ end
19
+ end
20
+
21
+ def test_against(kind)
22
+ sample = Rails.root + "config/database~#{kind}.sample.yml"
23
+ custom = Rails.root + "config/database~custom.yml"
24
+ backup = Rails.root + "config/database~custom.yml.backup"
25
+
26
+ if custom.exist?
27
+ mv custom, backup
28
+ end
29
+
30
+ cp sample, custom
31
+
32
+ succeeded = nil
33
+
34
+ begin
35
+ Dir.chdir(Rails.root) do
36
+ puts
37
+ puts "## Database: #{kind}"
38
+ succeeded = system "unset BUNDLE_GEMFILE BUNDLE_BIN_PATH RUBYOPT; bundle --quiet && rake db:create:all db:migrate db:test:prepare spec"
39
+ end
40
+ ensure
41
+ rm custom
42
+
43
+ if backup.exist?
44
+ mv backup, custom
45
+ end
46
+ end
47
+
48
+ unless succeeded
49
+ raise "Tests failed against database '#{kind}'"
50
+ end
51
+ end
52
+ end
53
+ end