Skip to content
Browse files

getting ready for first deploy

  • Loading branch information...
1 parent a4fe842 commit 72c843c2a266de7ae6611fe44e26c6f962919a42 Brian Armstrong committed
Showing with 5,720 additions and 307 deletions.
  1. BIN .DS_Store
  2. +1 −0 .rspec
  3. +31 −25 Gemfile
  4. +151 −6 Gemfile.lock
  5. +21 −0 Guardfile
  6. BIN app/.DS_Store
  7. BIN app/assets/images/tag_remove.png
  8. +3 −0 app/assets/javascripts/account/comments.js.coffee
  9. +3 −0 app/assets/javascripts/account/profiles.js.coffee
  10. +3 −0 app/assets/javascripts/account/settings.js.coffee
  11. +3 −0 app/assets/javascripts/account/submissions.js.coffee
  12. +3 −0 app/assets/javascripts/account/themes.js.coffee
  13. +3 −0 app/assets/javascripts/account/users.js.coffee
  14. +3 −1 app/assets/javascripts/application.js
  15. +16 −0 app/assets/javascripts/comments.js.coffee
  16. +9 −0 app/assets/javascripts/layout.js.coffee
  17. +3 −0 app/assets/javascripts/password_resets.js.coffee
  18. +15 −0 app/assets/javascripts/posts.js.coffee
  19. +31 −0 app/assets/javascripts/tags.js.coffee
  20. +3 −0 app/assets/javascripts/verifications.js.coffee
  21. +39 −0 app/assets/javascripts/votes.js.coffee
  22. +3 −0 app/assets/stylesheets/account/comments.css.scss
  23. +3 −0 app/assets/stylesheets/account/profiles.css.scss
  24. +3 −0 app/assets/stylesheets/account/settings.css.scss
  25. +3 −0 app/assets/stylesheets/account/submissions.css.scss
  26. +3 −0 app/assets/stylesheets/account/themes.css.scss
  27. +3 −0 app/assets/stylesheets/account/users.css.scss
  28. +0 −7 app/assets/stylesheets/application.css
  29. +30 −0 app/assets/stylesheets/application.css.scss
  30. +17 −0 app/assets/stylesheets/comments.css.scss
  31. +3 −0 app/assets/stylesheets/password_resets.css.scss
  32. +12 −0 app/assets/stylesheets/posts.css.scss
  33. 0 test/unit/.gitkeep → app/assets/stylesheets/scaffolds.css.scss
  34. +40 −0 app/assets/stylesheets/tags.css.scss
  35. +3 −0 app/assets/stylesheets/verifications.css.scss
  36. +16 −0 app/assets/stylesheets/votes.css.scss
  37. +12 −0 app/controllers/account/comments_controller.rb
  38. +12 −0 app/controllers/account/posts_controller.rb
  39. +17 −0 app/controllers/account/profiles_controller.rb
  40. +18 −0 app/controllers/account/settings_controller.rb
  41. +38 −0 app/controllers/account/tags_controller.rb
  42. +5 −0 app/controllers/account/themes_controller.rb
  43. +12 −0 app/controllers/account/users_controller.rb
  44. +25 −0 app/controllers/application_controller.rb
  45. +50 −0 app/controllers/comments_controller.rb
  46. +23 −0 app/controllers/forums_controller.rb
  47. +16 −0 app/controllers/participations_controller.rb
  48. +34 −0 app/controllers/password_resets_controller.rb
  49. +65 −0 app/controllers/posts_controller.rb
  50. +21 −0 app/controllers/sessions_controller.rb
  51. +8 −0 app/controllers/static_controller.rb
  52. +69 −0 app/controllers/users_controller.rb
  53. +28 −0 app/controllers/verifications_controller.rb
  54. +24 −0 app/controllers/votes_controller.rb
  55. +2 −0 app/helpers/account/comments_helper.rb
  56. +2 −0 app/helpers/account/profiles_helper.rb
  57. +2 −0 app/helpers/account/settings_helper.rb
  58. +2 −0 app/helpers/account/submissions_helper.rb
  59. +2 −0 app/helpers/account/themes_helper.rb
  60. +2 −0 app/helpers/account/users_helper.rb
  61. +40 −0 app/helpers/application_helper.rb
  62. +2 −0 app/helpers/password_resets_helper.rb
  63. +3 −0 app/helpers/posts_helper.rb
  64. +5 −0 app/helpers/static_helper.rb
  65. +14 −0 app/helpers/url_helper.rb
  66. +2 −0 app/helpers/verifications_helper.rb
  67. +2 −0 app/helpers/votes_helper.rb
  68. +13 −0 app/mailers/mailer.rb
  69. +44 −0 app/models/ability.rb
  70. +70 −0 app/models/comment.rb
  71. +59 −0 app/models/forum.rb
  72. +25 −0 app/models/participation.rb
  73. +107 −0 app/models/post.rb
  74. +17 −0 app/models/tag.rb
  75. +103 −0 app/models/user.rb
  76. BIN app/views/.DS_Store
  77. +13 −0 app/views/account/comments/index.html.erb
  78. +15 −0 app/views/account/posts/index.html.erb
  79. +53 −0 app/views/account/profiles/show.html.erb
  80. +46 −0 app/views/account/settings/index.html.erb
  81. +18 −0 app/views/account/tags/_tag.html.erb
  82. +10 −0 app/views/account/tags/create.js.erb
  83. +7 −0 app/views/account/tags/destroy.js.erb
  84. +26 −0 app/views/account/tags/index.html.erb
  85. +2 −0 app/views/account/tags/update.js.erb
  86. +7 −0 app/views/account/themes/index.html.erb
  87. +21 −0 app/views/account/users/index.html.erb
  88. +30 −0 app/views/comments/_comment.html.erb
  89. +21 −0 app/views/comments/_form.html.erb
  90. +4 −0 app/views/comments/create.js.erb
  91. +1 −0 app/views/comments/edit.html.erb
  92. +8 −0 app/views/forums/index.html.erb
  93. +20 −0 app/views/forums/new.html.erb
  94. +13 −0 app/views/kaminari/_first_page.html.erb
  95. +8 −0 app/views/kaminari/_gap.html.erb
  96. +13 −0 app/views/kaminari/_last_page.html.erb
  97. +13 −0 app/views/kaminari/_next_page.html.erb
  98. +12 −0 app/views/kaminari/_page.html.erb
  99. +25 −0 app/views/kaminari/_paginator.html.erb
  100. +13 −0 app/views/kaminari/_prev_page.html.erb
  101. +71 −3 app/views/layouts/application.html.erb
  102. +5 −0 app/views/mailer/email_verification.text.erb
  103. +5 −0 app/views/mailer/password_reset.text.erb
  104. +14 −0 app/views/participations/_participation.html.erb
  105. +2 −0 app/views/participations/ban.js.erb
  106. +23 −0 app/views/password_resets/edit.html.erb
  107. +16 −0 app/views/password_resets/new.html.erb
  108. +49 −0 app/views/posts/_form.html.erb
  109. +20 −0 app/views/posts/_post.html.erb
  110. +1 −0 app/views/posts/edit.html.erb
  111. +43 −0 app/views/posts/index.html.erb
  112. +1 −0 app/views/posts/new.html.erb
  113. +35 −0 app/views/posts/show.html.erb
  114. +47 −0 app/views/sessions/new.html.erb
  115. +21 −0 app/views/shared/_ads.html.erb
  116. +36 −0 app/views/shared/_byline.html.erb
  117. +10 −0 app/views/shared/_flashy.html.erb
  118. +15 −0 app/views/shared/_sidebar.html.erb
  119. +12 −0 app/views/shared/_tags.html.erb
  120. +11 −0 app/views/static/features.html.erb
  121. +21 −0 app/views/static/pricing.html.erb
  122. +44 −0 app/views/users/new.html.erb
  123. +2 −0 app/views/users/show.html.erb
  124. +5 −0 app/views/verifications/index.html.erb
  125. +13 −0 app/views/votes/_vote.html.erb
  126. +3 −0 app/views/votes/create.js.erb
  127. +9 −1 config/application.rb
  128. +3 −1 config/environments/development.rb
  129. +2 −0 config/environments/test.rb
  130. +15 −0 config/initializers/mongoid_inc_all.rb
  131. +7 −0 config/initializers/quiet_assets.rb
  132. +3 −2 config/initializers/session_store.rb
  133. +2 −0 config/initializers/sunspot_mongoid.rb
  134. +12 −0 config/initializers/to_model.rb
  135. +20 −0 config/mongoid.yml
  136. +49 −1 config/routes.rb
  137. +17 −0 config/sunspot.yml
  138. +26 −0 db/seeds.rb
  139. +43 −0 lib/authentication.rb
  140. +5 −0 lib/subdomain.rb
  141. 0 test/integration/.gitkeep → log/sunspot-solr-development.log.lck
  142. BIN public/favicon.ico
  143. +0 −241 public/index.html
  144. +36 −0 solr/conf/elevate.xml
  145. +238 −0 solr/conf/schema.xml
  146. +934 −0 solr/conf/solrconfig.xml
  147. +2 −0 solr/conf/spellings.txt
  148. +58 −0 solr/conf/stopwords.txt
  149. +31 −0 solr/conf/synonyms.txt
  150. BIN solr/data/development/index/_46.fdt
  151. BIN solr/data/development/index/_46.fdx
  152. +5 −0 solr/data/development/index/_46.fnm
  153. BIN solr/data/development/index/_46.frq
  154. +1 −0 solr/data/development/index/_46.nrm
  155. BIN solr/data/development/index/_46.prx
  156. BIN solr/data/development/index/_46.tii
  157. BIN solr/data/development/index/_46.tis
  158. BIN solr/data/development/index/_46_1.del
  159. BIN solr/data/development/index/_47.fdt
  160. BIN solr/data/development/index/_47.fdx
  161. +4 −0 solr/data/development/index/_47.fnm
  162. +1 −0 solr/data/development/index/_47.frq
  163. +1 −0 solr/data/development/index/_47.nrm
  164. BIN solr/data/development/index/_47.prx
  165. BIN solr/data/development/index/_47.tii
  166. BIN solr/data/development/index/_47.tis
  167. BIN solr/data/development/index/_47_1.del
  168. BIN solr/data/development/index/_48.fdt
  169. BIN solr/data/development/index/_48.fdx
  170. +4 −0 solr/data/development/index/_48.fnm
  171. +1 −0 solr/data/development/index/_48.frq
  172. +1 −0 solr/data/development/index/_48.nrm
  173. BIN solr/data/development/index/_48.prx
  174. BIN solr/data/development/index/_48.tii
  175. BIN solr/data/development/index/_48.tis
  176. 0 test/functional/.gitkeep → solr/data/development/index/_49.fdt
  177. 0 test/fixtures/.gitkeep → solr/data/development/index/_49.fdx
  178. 0 solr/data/development/index/lucene-7ff76e89dc0ab2f262841fab5c072848-write.lock
  179. BIN solr/data/development/index/segments.gen
  180. BIN solr/data/development/index/segments_3w
  181. BIN solr/data/development/spellchecker/segments.gen
  182. BIN solr/data/development/spellchecker/segments_1
  183. BIN solr/data/test/index/_0.fdt
  184. BIN solr/data/test/index/_0.fdx
  185. +4 −0 solr/data/test/index/_0.fnm
  186. +1 −0 solr/data/test/index/_0.frq
  187. +1 −0 solr/data/test/index/_0.nrm
  188. BIN solr/data/test/index/_0.prx
  189. BIN solr/data/test/index/_0.tii
  190. BIN solr/data/test/index/_0.tis
  191. BIN solr/data/test/index/_0_1.del
  192. BIN solr/data/test/index/_1.fdt
  193. BIN solr/data/test/index/_1.fdx
  194. +4 −0 solr/data/test/index/_1.fnm
  195. +1 −0 solr/data/test/index/_1.frq
  196. +1 −0 solr/data/test/index/_1.nrm
  197. BIN solr/data/test/index/_1.prx
  198. BIN solr/data/test/index/_1.tii
  199. BIN solr/data/test/index/_1.tis
  200. BIN solr/data/test/index/_2.fdt
  201. BIN solr/data/test/index/_2.fdx
  202. +4 −0 solr/data/test/index/_2.fnm
  203. +1 −0 solr/data/test/index/_2.frq
  204. +1 −0 solr/data/test/index/_2.nrm
  205. BIN solr/data/test/index/_2.prx
  206. BIN solr/data/test/index/_2.tii
  207. BIN solr/data/test/index/_2.tis
  208. BIN solr/data/test/index/_2_1.del
  209. BIN solr/data/test/index/_3.fdt
  210. BIN solr/data/test/index/_3.fdx
  211. +4 −0 solr/data/test/index/_3.fnm
  212. +1 −0 solr/data/test/index/_3.frq
  213. +1 −0 solr/data/test/index/_3.nrm
  214. BIN solr/data/test/index/_3.prx
  215. BIN solr/data/test/index/_3.tii
  216. BIN solr/data/test/index/_3.tis
  217. BIN solr/data/test/index/_4.fdt
  218. BIN solr/data/test/index/_4.fdx
  219. +4 −0 solr/data/test/index/_4.fnm
  220. +1 −0 solr/data/test/index/_4.frq
  221. +1 −0 solr/data/test/index/_4.nrm
  222. BIN solr/data/test/index/_4.prx
  223. BIN solr/data/test/index/_4.tii
  224. BIN solr/data/test/index/_4.tis
  225. BIN solr/data/test/index/_4_1.del
  226. BIN solr/data/test/index/_5.fdt
  227. BIN solr/data/test/index/_5.fdx
  228. +4 −0 solr/data/test/index/_5.fnm
  229. +1 −0 solr/data/test/index/_5.frq
  230. +1 −0 solr/data/test/index/_5.nrm
  231. BIN solr/data/test/index/_5.prx
  232. BIN solr/data/test/index/_5.tii
  233. BIN solr/data/test/index/_5.tis
  234. BIN solr/data/test/index/_6.fdt
  235. BIN solr/data/test/index/_6.fdx
  236. +4 −0 solr/data/test/index/_6.fnm
  237. +1 −0 solr/data/test/index/_6.frq
  238. +1 −0 solr/data/test/index/_6.nrm
  239. BIN solr/data/test/index/_6.prx
  240. BIN solr/data/test/index/_6.tii
  241. BIN solr/data/test/index/_6.tis
  242. BIN solr/data/test/index/_6_1.del
  243. BIN solr/data/test/index/_7.fdt
  244. BIN solr/data/test/index/_7.fdx
  245. +4 −0 solr/data/test/index/_7.fnm
  246. +1 −0 solr/data/test/index/_7.frq
  247. +1 −0 solr/data/test/index/_7.nrm
  248. BIN solr/data/test/index/_7.prx
  249. BIN solr/data/test/index/_7.tii
  250. BIN solr/data/test/index/_7.tis
  251. BIN solr/data/test/index/segments.gen
  252. BIN solr/data/test/index/segments_9
  253. BIN solr/data/test/spellchecker/segments.gen
  254. BIN solr/data/test/spellchecker/segments_1
  255. +33 −0 spec/requests/account_spec.rb
  256. +65 −0 spec/requests/comments_spec.rb
  257. +56 −0 spec/requests/forums_spec.rb
  258. +50 −0 spec/requests/moderation_spec.rb
  259. +39 −0 spec/requests/posts_spec.rb
  260. 0 spec/requests/search_spec.rb
  261. +49 −0 spec/requests/signup_spec.rb
  262. +78 −0 spec/requests/tags_spec.rb
  263. +124 −0 spec/requests/votes_spec.rb
  264. +90 −0 spec/spec_helper.rb
  265. +13 −0 spec/support/assert_difference.rb
  266. +3 −0 spec/support/capybara.rb
  267. +83 −0 spec/support/factories.rb
  268. +11 −0 spec/support/mailer_macros.rb
  269. +13 −0 spec/support/ribbot_dsl.rb
  270. +5 −0 spec/views/account/themes/index.html.erb_spec.rb
  271. +1 −0 sunspot-solr.pid
  272. +0 −12 test/performance/browsing_test.rb
  273. +0 −7 test/test_helper.rb
  274. BIN vendor/.DS_Store
  275. BIN vendor/plugins/.DS_Store
  276. +20 −0 vendor/plugins/dynamic_form/MIT-LICENSE
  277. +13 −0 vendor/plugins/dynamic_form/README
  278. +10 −0 vendor/plugins/dynamic_form/Rakefile
  279. +12 −0 vendor/plugins/dynamic_form/dynamic_form.gemspec
  280. +1 −0 vendor/plugins/dynamic_form/init.rb
  281. +300 −0 vendor/plugins/dynamic_form/lib/action_view/helpers/dynamic_form.rb
  282. +8 −0 vendor/plugins/dynamic_form/lib/action_view/locale/en.yml
  283. +5 −0 vendor/plugins/dynamic_form/lib/dynamic_form.rb
  284. +42 −0 vendor/plugins/dynamic_form/test/dynamic_form_i18n_test.rb
  285. +370 −0 vendor/plugins/dynamic_form/test/dynamic_form_test.rb
  286. +9 −0 vendor/plugins/dynamic_form/test/test_helper.rb
  287. +8 −0 vendor/plugins/jquery-ui-themes-rails/Gemfile
  288. +107 −0 vendor/plugins/jquery-ui-themes-rails/Gemfile.lock
  289. +20 −0 vendor/plugins/jquery-ui-themes-rails/MIT-LICENSE
  290. +66 −0 vendor/plugins/jquery-ui-themes-rails/README.markdown
  291. +39 −0 vendor/plugins/jquery-ui-themes-rails/Rakefile
  292. BIN ...ry-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_diagonals-thick_8_333333_40x40.png
  293. BIN ...gins/jquery-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_flat_65_ffffff_40x100.png
  294. BIN ...gins/jquery-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_glass_40_111111_1x400.png
  295. BIN ...gins/jquery-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_glass_55_1c1c1c_1x400.png
  296. BIN ...y-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_highlight-hard_100_f9f9f9_1x100.png
  297. BIN ...ry-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_highlight-hard_40_aaaaaa_1x100.png
  298. BIN ...ry-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_highlight-soft_50_aaaaaa_1x100.png
  299. BIN ...jquery-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_inset-hard_45_cd0a0a_1x100.png
  300. BIN ...jquery-ui-themes-rails/app/assets/images/jquery-ui/black-tie/ui-bg_inset-hard_55_ffeb80_1x100.png
Sorry, we could not display the entire diff because too many files (698) changed.
View
BIN .DS_Store
Binary file not shown.
View
1 .rspec
@@ -0,0 +1 @@
+--colour
View
56 Gemfile
@@ -1,35 +1,41 @@
source 'http://rubygems.org'
-gem 'rails', '3.1.1'
+gem 'rails', '3.1.1'
+gem 'mongoid', '2.3.3'
+gem 'bson_ext', '1.4.1'
+gem 'jquery-rails', '1.0.16'
+gem 'twitter-bootstrap-rails', '1.4.0'
+gem 'database_cleaner', '0.6.7'
+gem 'bcrypt-ruby', '3.0.1'
+gem 'kaminari', '0.12.4'
+gem 'gravtastic', '3.2.6'
+gem 'mongoid_nested_set', '0.1.3'
+gem 'cancan', '1.6.7'
+gem 'sunspot_mongoid', '0.4.1', :git => "git://github.com/TV4/sunspot_mongoid.git"
+gem 'sunspot_rails', :git => "git://github.com/sunspot/sunspot.git"
+gem 'sunspot_with_kaminari', '0.1.0'
+gem 'voteable_mongo', '0.9.3'
+gem 'acts_as_list_mongoid', '0.2.4'
-# Bundle edge Rails instead:
-# gem 'rails', :git => 'git://github.com/rails/rails.git'
-
-
-# Gems used only for assets and not required
-# in production environments by default.
group :assets do
- gem 'sass-rails', '~> 3.1.4'
- gem 'coffee-rails', '~> 3.1.1'
+ gem 'sass-rails', " ~> 3.1.4"
+ gem 'coffee-rails', "~> 3.1.1"
gem 'uglifier', '>= 1.0.3'
end
-gem 'jquery-rails'
-
-# To use ActiveModel has_secure_password
-# gem 'bcrypt-ruby', '~> 3.0.0'
-
-# Use unicorn as the web server
-# gem 'unicorn'
-
-# Deploy with Capistrano
-# gem 'capistrano'
-
-# To use debugger
-# gem 'ruby-debug19', :require => 'ruby-debug'
+group :test, :development do
+ gem "rspec-rails"
+end
group :test do
- # Pretty printed test output
- gem 'turn', :require => false
-end
+ gem "capybara", '1.1.1'
+ gem "guard-rspec", '0.5.0'
+ gem "mocha", '0.10.0'
+ gem "growl", '1.0.3' # requires "brew install growlnotify"
+ gem "spork", '> 0.9.0.rc'
+ gem "guard-spork", '0.3.1'
+ gem "launchy", '2.0.5'
+ gem 'sunspot_test', '0.4.0'
+ gem 'capybara-webkit', '0.7.2' # requires "brew install qt"
+end
View
157 Gemfile.lock
@@ -1,3 +1,24 @@
+GIT
+ remote: git://github.com/TV4/sunspot_mongoid.git
+ revision: c67c8265141988f4443a431c6f4ca65bdc2364f5
+ specs:
+ sunspot_mongoid (0.4.1)
+ mongoid
+ sunspot (>= 1.1.0)
+ sunspot_rails (>= 1.1.0)
+
+GIT
+ remote: git://github.com/sunspot/sunspot.git
+ revision: 126e50710803d6d988402b332d72d7c5c3bcde7f
+ specs:
+ sunspot (1.3.0.rc6)
+ escape (~> 0.0.4)
+ pr_geohash (~> 1.0)
+ rsolr (~> 1.0.3)
+ sunspot_rails (1.3.0.rc6)
+ nokogiri
+ sunspot (= 1.3.0.rc6)
+
GEM
remote: http://rubygems.org/
specs:
@@ -29,9 +50,27 @@ GEM
activesupport (= 3.1.1)
activesupport (3.1.1)
multi_json (~> 1.0)
- ansi (1.3.0)
+ acts_as_list_mongoid (0.2.4)
+ mongoid (>= 2.0.1)
+ mongoid_embedded_helper (>= 0.2.5)
+ addressable (2.2.6)
arel (2.2.1)
+ bcrypt-ruby (3.0.1)
+ bson (1.4.1)
+ bson_ext (1.4.1)
builder (3.0.0)
+ cancan (1.6.7)
+ capybara (1.1.1)
+ mime-types (>= 1.16)
+ nokogiri (>= 1.3.3)
+ rack (>= 1.0.0)
+ rack-test (>= 0.5.4)
+ selenium-webdriver (~> 2.0)
+ xpath (~> 0.1.4)
+ capybara-webkit (0.7.2)
+ capybara (>= 1.0.0, < 1.2)
+ childprocess (0.2.2)
+ ffi (~> 1.0.6)
coffee-rails (3.1.1)
coffee-script (>= 2.2.0)
railties (~> 3.1.0)
@@ -39,22 +78,69 @@ GEM
coffee-script-source
execjs
coffee-script-source (1.1.2)
+ database_cleaner (0.6.7)
+ diff-lcs (1.1.3)
erubis (2.7.0)
+ escape (0.0.4)
execjs (1.2.9)
multi_json (~> 1.0)
+ ffi (1.0.9)
+ gravtastic (3.2.6)
+ growl (1.0.3)
+ guard (0.8.8)
+ thor (~> 0.14.6)
+ guard-rspec (0.5.0)
+ guard (>= 0.8.4)
+ guard-spork (0.3.1)
+ guard (>= 0.8.4)
+ spork (>= 0.8.4)
hike (1.2.1)
i18n (0.6.0)
jquery-rails (1.0.16)
railties (~> 3.0)
thor (~> 0.14)
json (1.6.1)
+ json_pure (1.6.1)
+ kaminari (0.12.4)
+ rails (>= 3.0.0)
+ launchy (2.0.5)
+ addressable (~> 2.2.6)
+ less (2.0.7)
+ therubyracer (~> 0.9.2)
+ less-rails (2.0.2)
+ actionpack (~> 3.1.1)
+ less (~> 2.0.7)
+ libv8 (3.3.10.2)
mail (2.3.0)
i18n (>= 0.4.0)
mime-types (~> 1.16)
treetop (~> 1.4.8)
+ metaclass (0.0.1)
mime-types (1.16)
+ mocha (0.10.0)
+ metaclass (~> 0.0.1)
+ mongo (1.4.1)
+ bson (= 1.4.1)
+ mongoid (2.3.3)
+ activemodel (~> 3.1)
+ mongo (~> 1.3)
+ tzinfo (~> 0.3.22)
+ mongoid_adjust (0.1.2)
+ bson (>= 1.2)
+ mongoid (>= 2.0.1)
+ mongoid_embedded_helper (0.3.2)
+ bson (>= 1.2)
+ bson (>= 1.2)
+ mongoid (>= 2.0.1)
+ mongoid (>= 2.0.1)
+ mongoid_adjust (>= 0.1.1)
+ mongoid_adjust (>= 0.1.1)
+ mongoid_nested_set (0.1.3)
+ mongoid (>= 2.1.0)
multi_json (1.0.3)
+ nokogiri (1.5.0)
polyglot (0.3.2)
+ pr_geohash (1.0.0)
rack (1.3.5)
rack-cache (1.1)
rack (>= 0.4)
@@ -82,6 +168,23 @@ GEM
rake (0.9.2.2)
rdoc (3.11)
json (~> 1.4)
+ rsolr (1.0.3)
+ builder (= 3.0.0)
+ builder (>= 2.1.2)
+ rspec (2.7.0)
+ rspec-core (~> 2.7.0)
+ rspec-expectations (~> 2.7.0)
+ rspec-mocks (~> 2.7.0)
+ rspec-core (2.7.1)
+ rspec-expectations (2.7.0)
+ diff-lcs (~> 1.1.2)
+ rspec-mocks (2.7.0)
+ rspec-rails (2.7.0)
+ actionpack (~> 3.0)
+ activesupport (~> 3.0)
+ railties (~> 3.0)
+ rspec (~> 2.7.0)
+ rubyzip (0.9.4)
sass (3.1.10)
sass-rails (3.1.4)
actionpack (~> 3.1.0)
@@ -89,29 +192,71 @@ GEM
sass (>= 3.1.4)
sprockets (~> 2.0.0)
tilt (~> 1.3.2)
+ selenium-webdriver (2.9.1)
+ childprocess (>= 0.2.1)
+ ffi (= 1.0.9)
+ json_pure
+ rubyzip
+ spork (0.9.0.rc9)
sprockets (2.0.3)
hike (~> 1.2)
rack (~> 1.0)
tilt (~> 1.1, != 1.3.0)
+ sunspot_test (0.4.0)
+ sunspot_rails (>= 1.2.1)
+ sunspot_with_kaminari (0.1.0)
+ kaminari
+ sunspot_rails
+ therubyracer (0.9.9)
+ libv8 (~> 3.3.10)
thor (0.14.6)
tilt (1.3.3)
treetop (1.4.10)
polyglot
polyglot (>= 0.3.1)
- turn (0.8.3)
- ansi
- tzinfo (0.3.30)
+ twitter-bootstrap-rails (1.4.0)
+ actionpack
+ less
+ less-rails (~> 2.0.1)
+ railties
+ tzinfo (0.3.31)
uglifier (1.0.4)
execjs (>= 0.3.0)
multi_json (>= 1.0.2)
+ voteable_mongo (0.9.3)
+ xpath (0.1.4)
+ nokogiri (~> 1.3)
PLATFORMS
ruby
DEPENDENCIES
+ acts_as_list_mongoid (= 0.2.4)
+ bcrypt-ruby (= 3.0.1)
+ bson_ext (= 1.4.1)
+ cancan (= 1.6.7)
+ capybara (= 1.1.1)
+ capybara-webkit (= 0.7.2)
coffee-rails (~> 3.1.1)
- jquery-rails
+ database_cleaner (= 0.6.7)
+ gravtastic (= 3.2.6)
+ growl (= 1.0.3)
+ guard-rspec (= 0.5.0)
+ guard-spork (= 0.3.1)
+ jquery-rails (= 1.0.16)
+ kaminari (= 0.12.4)
+ launchy (= 2.0.5)
+ mocha (= 0.10.0)
+ mongoid (= 2.3.3)
+ mongoid_nested_set (= 0.1.3)
rails (= 3.1.1)
+ rspec-rails
sass-rails (~> 3.1.4)
- turn
+ spork (> 0.9.0.rc)
+ sunspot_mongoid (= 0.4.1)!
+ sunspot_rails!
+ sunspot_test (= 0.4.0)
+ sunspot_with_kaminari (= 0.1.0)
+ twitter-bootstrap-rails (= 1.4.0)
uglifier (>= 1.0.3)
+ voteable_mongo (= 0.9.3)
View
21 Guardfile
@@ -0,0 +1,21 @@
+# A sample Guardfile
+# More info at https://github.com/guard/guard#readme
+
+guard 'rspec', :version => 2 do
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
+ watch('spec/spec_helper.rb') { "spec" }
+
+ # Rails example
+ watch(%r{^spec/.+_spec\.rb$})
+ watch(%r{^app/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
+ watch(%r{^app/controllers/(.+)_(controller)\.rb$}) { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
+ watch(%r{^spec/support/(.+)\.rb$}) { "spec" }
+ watch('spec/spec_helper.rb') { "spec" }
+ watch('config/routes.rb') { "spec/routing" }
+ watch('app/controllers/application_controller.rb') { "spec/controllers" }
+ # Capybara request specs
+ watch(%r{^app/views/(.+)/.*\.(erb|haml)$}) { |m| "spec/requests/#{m[1]}_spec.rb" }
+end
+
View
BIN app/.DS_Store
Binary file not shown.
View
BIN app/assets/images/tag_remove.png
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
View
3 app/assets/javascripts/account/comments.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
3 app/assets/javascripts/account/profiles.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
3 app/assets/javascripts/account/settings.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
3 app/assets/javascripts/account/submissions.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
3 app/assets/javascripts/account/themes.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
3 app/assets/javascripts/account/users.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
4 app/assets/javascripts/application.js
@@ -5,5 +5,7 @@
// the compiled file.
//
//= require jquery
+//= require jquery-ui
//= require jquery_ujs
-//= require_tree .
+//= require twitter/bootstrap
+//= require_tree .
View
16 app/assets/javascripts/comments.js.coffee
@@ -0,0 +1,16 @@
+jQuery ->
+ $('.reply-link').live 'click', (e) ->
+ $('.comment .comment-form').remove()
+ comment = $(this).parents('.comment')
+ form = $('#reply_comment form').clone().hide()
+ comment.append(form)
+ form.fadeIn('fast')
+ comment.find('form #comment_parent_id').val(comment.attr('id').split('_')[1])
+ form.find('textarea').focus()
+ false
+
+ $('.cancel-link').live 'click', (e) ->
+ comment = $(this).parents('.comment')
+ $('.comment .comment-form').fadeOut('fast')
+ false
+
View
9 app/assets/javascripts/layout.js.coffee
@@ -0,0 +1,9 @@
+jQuery ->
+ setTimeout ->
+ $('.right-sidebar, .left-sidebar').each (i, e) ->
+ row_height = $(e).parent('.row').height()
+ $(e).height(row_height)
+ , 5
+
+ if $('.flash').length
+ $('.flash').delay(3000).fadeOut('slow')
View
3 app/assets/javascripts/password_resets.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
15 app/assets/javascripts/posts.js.coffee
@@ -0,0 +1,15 @@
+jQuery ->
+ $('form.post-form .url-link').click (e) ->
+ $('#post_text').hide()
+ $('#post_url').fadeIn('fast')
+ $('.url-link').addClass('active')
+ $('.text-link').removeClass('active')
+ false
+
+ $('form.post-form .text-link').click (e) ->
+ $('#post_url').hide()
+ $('#post_text').fadeIn('fast')
+ $('.text-link').addClass('active')
+ $('.url-link').removeClass('active')
+ false
+
View
31 app/assets/javascripts/tags.js.coffee
@@ -0,0 +1,31 @@
+jQuery ->
+ $('#tags tbody').sortable(
+ axis: 'y'
+ handle: '.handle'
+ update: ->
+ $.post($('#tags').data('update-url'), $(this).sortable('serialize'))
+ helper: (e, tr) ->
+ $originals = tr.children()
+ $helper = tr.clone()
+ $helper.children().each (index) ->
+ $(this).width($originals.eq(index).width())
+ $helper
+ )
+
+ $('#tags').hide() if $('#tags tbody tr').length == 0
+
+ $('#tags .edit-tag-link').live 'click', (e) ->
+ tr = $(this).parents('tr')
+ tr.find('.show').hide()
+ tr.find('.edit').fadeIn('fast')
+
+ $('#tags .cancel-edit-tag-link').live 'click', (e) ->
+ tr = $(this).parents('tr')
+ tr.find('.edit').hide()
+ tr.find('.show').fadeIn('fast')
+
+ $('.post-form .tag-link').click (e) ->
+ $(this).toggleClass('active')
+ checkbox = $(this).siblings('.tag-checkbox')
+ checkbox.attr('checked', !checkbox.attr('checked'))
+ false
View
3 app/assets/javascripts/verifications.js.coffee
@@ -0,0 +1,3 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
View
39 app/assets/javascripts/votes.js.coffee
@@ -0,0 +1,39 @@
+# Place all the behaviors and hooks related to the matching controller here.
+# All this logic will automatically be available in application.js.
+# You can use CoffeeScript in this file: http://jashkenas.github.com/coffee-script/
+
+jQuery ->
+ $('.upvote, .downvote').live 'click', (e) ->
+ e.preventDefault()
+ $(this).toggleClass('on')
+ if $(this).hasClass('upvote')
+ changePoints $(this), (if $(this).hasClass('on') then 1 else -1)
+ else
+ changePoints $(this), (if $(this).hasClass('on') then -1 else 1)
+ true
+
+changePoints = (e, points) ->
+ points += updateSibling(e)
+ span = e.parents('.post, .comment').find('.points')
+ span.html(points + parseInt(span.html()))
+ postToServer(e)
+
+updateSibling = (e) ->
+ if e.hasClass('upvote')
+ sib = e.siblings('.downvote')
+ p = 1
+ else
+ sib = e.siblings('.upvote')
+ p = -1
+ if sib.hasClass('on')
+ sib.removeClass('on')
+ p
+ else
+ 0
+
+postToServer = (e) ->
+ $.post e.attr('href'), {
+ dom_id: e.parents('.post, .comment').attr('id'),
+ direction: if e.hasClass('upvote') then 'up' else 'down',
+ toggle: if e.hasClass('on') then 'on' else 'off'
+ }
View
3 app/assets/stylesheets/account/comments.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the account/comments controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
3 app/assets/stylesheets/account/profiles.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the account/profiles controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
3 app/assets/stylesheets/account/settings.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the account/labels controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
3 app/assets/stylesheets/account/submissions.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the account/submissions controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
3 app/assets/stylesheets/account/themes.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the account/themes controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
3 app/assets/stylesheets/account/users.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the account/users controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
7 app/assets/stylesheets/application.css
@@ -1,7 +0,0 @@
-/*
- * This is a manifest file that'll automatically include all the stylesheets available in this directory
- * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
- * the top of the compiled file, but it's generally better to create a new file per style scope.
- *= require_self
- *= require_tree .
-*/
View
30 app/assets/stylesheets/application.css.scss
@@ -0,0 +1,30 @@
+/*
+ * This is a manifest file that'll automatically include all the stylesheets available in this directory
+ * and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
+ * the top of the compiled file, but it's generally better to create a new file per style scope.
+ *= require twitter/bootstrap
+ *= require_self
+ *= require_tree .
+ *= require jquery-ui/smoothness
+*/
+
+.topbar { position: static; margin-bottom: 19px; }
+.topbar a:visited { color: #BFBFBF; }
+.topbar a.brand { text-decoration: none; color: #fff; }
+footer { clear: both; }
+.flash { min-height: 18px; position: absolute; float: left; left: 50%; top: 0%; }
+.flash .alert-message { float: left; position: relative; left: -50%; }
+.divider { height: 1px; margin: 5px 0; overflow: hidden; background-color: #eee; border-bottom: 1px solid #ffffff; }
+
+.right-sidebar { border-left: 1px solid #DDD; padding-left: 19px; height: 100%; }
+.left-sidebar { border-right: 1px solid #DDD; padding-right: 19px; height: 100%; }
+
+.byline,
+.byline a.user-link { color: #777; }
+
+.left-sidebar h5.active a { color: black; }
+
+footer .pull-right,
+footer .pull-right a { font-size: 11px; color: #999; }
+
+table.border-less td { border: none; }
View
17 app/assets/stylesheets/comments.css.scss
@@ -0,0 +1,17 @@
+form.comment-form {
+ textarea { height: 80px; }
+}
+
+$comment-grid: 40px;
+
+.comment-offset0 { margin-left: $comment-grid * 0; }
+.comment-offset1 { margin-left: $comment-grid * 1; }
+.comment-offset2 { margin-left: $comment-grid * 2; }
+.comment-offset3 { margin-left: $comment-grid * 3; }
+.comment-offset4 { margin-left: $comment-grid * 4; }
+.comment-offset5 { margin-left: $comment-grid * 5; }
+.comment-offset6 { margin-left: $comment-grid * 6; }
+.comment-offset7 { margin-left: $comment-grid * 7; }
+.comment-offset8 { margin-left: $comment-grid * 8; }
+
+.comment .comment-form { margin-left: $comment-grid; }
View
3 app/assets/stylesheets/password_resets.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the password_resets controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
12 app/assets/stylesheets/posts.css.scss
@@ -0,0 +1,12 @@
+form.post-form {
+ textarea { height: 150px; }
+
+ .url-link.active,
+ .text-link.active { color: #333; text-decoration: none; cursor: default; }
+}
+
+.post { clear: both; }
+.post .description { width: 100%; }
+.post .description .byline { margin-bottom: 0; }
+
+.post-link { font-weight: bold; }
View
0 test/unit/.gitkeep → app/assets/stylesheets/scaffolds.css.scss
File renamed without changes.
View
40 app/assets/stylesheets/tags.css.scss
@@ -0,0 +1,40 @@
+.handle { cursor: move; }
+
+.tags {
+ tr {
+ a { display: inline-block; }
+ form { margin: 0; }
+ }
+}
+
+a.tag {
+ padding: 0 7px;
+ margin-right: 2px;
+ margin-bottom: 5px;
+ font-size: 12px;
+ line-height: 24px;
+ border: 1px solid transparent;
+ -webkit-border-radius: 4px;
+ -moz-border-radius: 4px;
+ border-radius: 4px;
+ background-color: #ffffff;
+ border: 1px solid #ddd;
+ display: inline-block;
+ color: #555;
+}
+
+a.tag:hover {
+ background-color: #eee;
+ text-decoration: none;
+}
+a.tag.active {
+ color: #ffffff;
+ text-shadow: 0 1px 1px rgba(0, 0, 0, 0.25);
+ background-color: #555;
+ background: #555 url(/assets/tag_remove.png) no-repeat 7px center;
+ padding-left: 21px;
+}
+
+input.tag-checkbox {
+ display: none;
+}
View
3 app/assets/stylesheets/verifications.css.scss
@@ -0,0 +1,3 @@
+// Place all the styles related to the verifications controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
View
16 app/assets/stylesheets/votes.css.scss
@@ -0,0 +1,16 @@
+// Place all the styles related to the votes controller here.
+// They will automatically be included in application.css.
+// You can use Sass (SCSS) here: http://sass-lang.com/
+
+.voting {
+ white-space: nowrap;
+
+ a {
+ color: #333; text-decoration: none;
+ &:hover { color: #333; text-decoration: none; }
+ }
+ a.upvote.on { color: green; }
+ a.downvote.on { color: red; }
+
+ .dead-links { color: #aaa; }
+}
View
12 app/controllers/account/comments_controller.rb
@@ -0,0 +1,12 @@
+class Account::CommentsController < ApplicationController
+ before_filter :authenticate_user!
+ before_filter :require_subdomain!
+
+ def index
+ @comments = Comment.where(:forum_id => current_forum.id, :user_id => current_user.id)
+ .includes(:post, :user)
+ .desc(:created_at)
+ .page(params[:page])
+ end
+
+end
View
12 app/controllers/account/posts_controller.rb
@@ -0,0 +1,12 @@
+class Account::PostsController < ApplicationController
+ before_filter :authenticate_user!
+ before_filter :require_subdomain!
+
+ def index
+ @posts = Post.where(:forum_id => current_forum.id, :user_id => current_user.id)
+ .includes(:post, :user)
+ .desc(:created_at)
+ .page(params[:page])
+ end
+
+end
View
17 app/controllers/account/profiles_controller.rb
@@ -0,0 +1,17 @@
+class Account::ProfilesController < ApplicationController
+ before_filter :authenticate_user!
+
+ def show
+ end
+
+ def update
+ @user = current_user
+ authorize! :edit, @user
+
+ if @user.update_attributes(params[:user])
+ redirect_to account_profile_path, :notice => "Profile updated!"
+ else
+ render :show
+ end
+ end
+end
View
18 app/controllers/account/settings_controller.rb
@@ -0,0 +1,18 @@
+class Account::SettingsController < ApplicationController
+ before_filter :authenticate_user!
+
+ def index
+ @forum = current_forum
+ authorize! :edit, @forum
+ end
+
+ def update
+ @forum = Forum.find(params[:id])
+ authorize! :update, @forum
+ if @forum.update_attributes params[:forum]
+ redirect_to account_settings_path, :notice => "Settings udpated!"
+ else
+ render :index
+ end
+ end
+end
View
38 app/controllers/account/tags_controller.rb
@@ -0,0 +1,38 @@
+class Account::TagsController < ApplicationController
+ before_filter :authenticate_user!
+ before_filter :require_subdomain!
+
+ def index
+ authorize! :edit, current_forum
+ @tag = Tag.new
+ @tags = current_forum.tags.asc(:position).page(params[:page])
+ end
+
+ def create
+ authorize! :udpate, current_forum
+ @tag = Tag.new(params[:tag])
+ @tag.forum = current_forum
+ @tag.save
+ @tag.move_to(1)
+ end
+
+ def update
+ authorize! :udpate, current_forum
+ @tag = current_forum.tags.find(params[:id])
+ @tag.update_attributes(params[:tag])
+ end
+
+ def destroy
+ authorize! :udpate, current_forum
+ @tag = current_forum.tags.find(params[:id])
+ @dom_id = "tag_#{@tag.id}"
+ @tag.destroy
+ end
+
+ def sort
+ params[:tag].each_with_index do |id, index|
+ Tag.where(:_id => id).update_all(:position => index+1)
+ end
+ render nothing: true
+ end
+end
View
5 app/controllers/account/themes_controller.rb
@@ -0,0 +1,5 @@
+class Account::ThemesController < ApplicationController
+ def index
+ end
+
+end
View
12 app/controllers/account/users_controller.rb
@@ -0,0 +1,12 @@
+class Account::UsersController < ApplicationController
+ before_filter :authenticate_user!
+
+ def index
+ authorize! :edit, current_forum
+ @participations = current_forum.participations
+ .includes(:user)
+ .desc(:created_at)
+ .page(params[:page])
+ end
+
+end
View
25 app/controllers/application_controller.rb
@@ -1,3 +1,28 @@
class ApplicationController < ActionController::Base
+ include UrlHelper
protect_from_forgery
+ include Authentication
+
+ before_filter :check_subdomain
+
+ def check_subdomain
+ if Rails.env.production? and request.host.downcase =~ /^www|ribbot\.heroku\.com/
+ redirect_to request.protocol + 'ribbot.com' + request.fullpath, :status => 301
+ end
+ end
+
+ def current_forum
+ @current_forum ||= request.subdomain.present? ? Forum.where(:subdomain => request.subdomain.downcase).first : nil
+ end
+ helper_method :current_forum
+
+ def require_subdomain!
+ if current_forum.nil?
+ redirect_to forums_url(:subdomain => false)
+ end
+ end
+
+ rescue_from CanCan::AccessDenied do |exception|
+ redirect_to root_url, :alert => exception.message
+ end
end
View
50 app/controllers/comments_controller.rb
@@ -0,0 +1,50 @@
+class CommentsController < ApplicationController
+ before_filter :require_subdomain!
+ before_filter :authenticate_user!
+ before_filter :load_params
+
+ def load_params
+ @post = current_forum.posts.find(params[:post_id])
+ @comment = @post.comments.find(params[:id]) if params[:id].present?
+ end
+
+ def create
+ @comment = @post.comments.new(params[:comment])
+ @comment.forum = current_forum
+ @comment.user = current_user
+ @comment.parent = @post.comments.find(params[:comment][:parent_id]) unless params[:comment][:parent_id].blank?
+
+ respond_to do |format|
+ format.html do
+ if @comment.save
+ redirect_to post_path(@comment.post), :notice => "Comment posted!"
+ else
+ redirect_to post_path(@comment.post)
+ end
+ end
+ format.js
+ end
+ end
+
+ def update
+ authorize! :update, @comment
+ if @comment.update_attributes(params[:comment])
+ redirect_to post_path(@post), :notice => "Updated!"
+ else
+ render :edit
+ end
+ end
+
+ def edit
+ authorize! :edit, @comment
+ end
+
+ def destroy
+ if @comment.children.empty? or current_user.admin_of?(@comment.forum)
+ @comment.destroy
+ else
+ @comment.update_attribute :deleted, true
+ end
+ redirect_to @post, :notice => "#{current_forum.comment_label} deleted"
+ end
+end
View
23 app/controllers/forums_controller.rb
@@ -0,0 +1,23 @@
+class ForumsController < ApplicationController
+ before_filter :require_subdomain!, :only => :show
+ before_filter :authenticate_user!, :except => :show
+
+ def new
+ @forum = Forum.new
+ end
+
+ def index
+ @forums = current_user.forums.order(:name)
+ end
+
+ def create
+ @forum = Forum.new(params[:forum])
+ if @forum.save
+ @forum.add_admin(current_user)
+ redirect_to root_url(:subdomain => @forum.subdomain), :notice => "Forum created!"
+ else
+ render :new
+ end
+ end
+
+end
View
16 app/controllers/participations_controller.rb
@@ -0,0 +1,16 @@
+class ParticipationsController < ApplicationController
+ before_filter :authenticate_user!
+ before_filter :require_subdomain!
+ load_and_authorize_resource
+
+ def ban
+ #@participation = Participation.find(params[:id])
+ @participation.update_attribute :banned, true
+ end
+
+ def unban
+ #@participation = Participation.find(params[:id])
+ @participation.update_attribute :banned, false
+ render :ban
+ end
+end
View
34 app/controllers/password_resets_controller.rb
@@ -0,0 +1,34 @@
+class PasswordResetsController < ApplicationController
+
+ def create
+ user = User.where(:email => params[:email]).first
+ user.send_password_reset if user
+ redirect_to root_url, :notice => "Email sent with password reset instructions."
+ end
+
+ def edit
+ @user = User.where(:password_reset_token =>params[:id]).first
+
+ if @user.nil?
+ redirect_to root_path, :notice => "That link is no longer valid"
+ return
+ end
+ end
+
+ def update
+ @user = User.where(:password_reset_token =>params[:id]).first
+
+ if @user.nil?
+ redirect_to root_path, :notice => "That link is no longer valid"
+ return
+ end
+
+ if @user.password_reset_sent_at < 2.hours.ago
+ redirect_to new_password_reset_path, :alert => "Your password reset link has expired. Please try again."
+ elsif @user.update_attributes(params[:user])
+ signin! @user, "Your password has been reset."
+ else
+ render :edit
+ end
+ end
+end
View
65 app/controllers/posts_controller.rb
@@ -0,0 +1,65 @@
+class PostsController < ApplicationController
+ before_filter :require_subdomain!
+ before_filter :authenticate_user!, :except => [:show, :index]
+
+ def new
+ @post = Post.new
+ end
+
+ def create
+ @post = current_forum.posts.new(params[:post])
+ @post.user = current_user
+ @post.forum = current_forum
+ if @post.save
+ redirect_to @post, :notice => "Post created!"
+ else
+ render :new
+ end
+ end
+
+ def index
+ if params[:search].present?
+ @posts = Post.solr_search do
+ keywords params[:search]
+ with :forum_id, current_forum.id
+ paginate :page => params[:page]
+ end
+ else
+ @posts = current_forum.posts.desc(:ranking).with_tags(params[:tags], current_forum).page(params[:page])
+ end
+ end
+
+ def show
+ @post = current_forum.posts.find(params[:id])
+ if @post.nil?
+ redirect_to root_path(:subdomain => current_forum.subdomain), :notice => "That post is no longer available."
+ return
+ end
+ @comment = @post.comments.new
+ @comments = @post.comments.asc(:lft).page(params[:page])
+ end
+
+ def edit
+ @post = current_forum.posts.find(params[:id])
+ authorize! :edit, @post
+ end
+
+ def update
+ params[:post][:tag_ids] ||= []
+ @post = current_forum.posts.find(params[:id])
+ authorize! :update, @post
+ if @post.update_attributes(params[:post])
+ redirect_to @post, :notice => "Post updated!"
+ else
+ render :edit
+ end
+ end
+
+ def destroy
+ @post = current_forum.posts.find(params[:id])
+ authorize! :destroy, @post
+ @post.destroy
+ redirect_to root_path, :notice => "Post deleted!"
+ end
+
+end
View
21 app/controllers/sessions_controller.rb
@@ -0,0 +1,21 @@
+class SessionsController < ApplicationController
+
+ def new
+ @user = User.new
+ end
+
+ def create
+ user = User.first(conditions: {email: params[:email]})
+ if user && user.authenticate(params[:password])
+ signin! user
+ else
+ flash.now.alert = "Invalid email or password"
+ render "new"
+ end
+ end
+
+ def destroy
+ signout!
+ end
+
+end
View
8 app/controllers/static_controller.rb
@@ -0,0 +1,8 @@
+class StaticController < ApplicationController
+ def features
+ end
+
+ def pricing
+ end
+
+end
View
69 app/controllers/users_controller.rb
@@ -0,0 +1,69 @@
+class UsersController < ApplicationController
+ before_filter :authenticate_user!, :only => :password_reset
+ before_filter :require_subdomain!, :only => :show
+
+ def new
+ @user = User.new
+ @forum = Forum.new
+ end
+
+ def create
+ @user = User.new(params[:user])
+ @user.password = params[:user][:password]
+ if @user.save
+ signin! @user, "Thanks for creating an account!"
+ else
+ try_login or render 'sessions/new'
+ end
+ end
+
+ def create_with_forum
+ @user = User.new(params[:user])
+ @user.password = params[:user][:password]
+ @forum = Forum.new(:subdomain => params[:subdomain])
+
+ if @user.valid? and @forum.valid?
+ @user.save!
+ @forum.save!
+ @forum.add_admin(@user)
+ signin! @user, "Thanks for creating an account!"
+ else
+ try_login or render :new
+ end
+ end
+
+ def show
+ @user = User.find(params[:id])
+ raise CanCan::AccessDenied.new("Not authorized!", :view, User) unless @user.member_of?(current_forum)
+ end
+
+ def password_reset
+ @user = current_user
+ if @user.authenticate(params[:old_password])
+ if params[:password] == params[:password_confirmation]
+ @user.password = params[:password]
+ if @user.save
+ redirect_to account_profile_path, :notice => "Password udpated!"
+ else
+ redirect_to account_profile_path, :notice => @user.errors.full_messages.join(" ")
+ end
+ else
+ redirect_to account_profile_path, :notice => "New password didn't match confirmation"
+ end
+ else
+ redirect_to account_profile_path, :notice => "Old password didn't match"
+ end
+ end
+
+ protected
+
+ def try_login
+ if user = User.first(conditions: {email: @user.email}) and user.authenticate(params[:user][:password])
+ signin! user
+ true
+ else
+ false
+ end
+ end
+
+end
View
28 app/controllers/verifications_controller.rb
@@ -0,0 +1,28 @@
+class VerificationsController < ApplicationController
+ #before_filter :authenticate_user!, :only => :index
+
+ def index
+ if current_user.nil?
+ redirect_to signin_path, :notice => "Please sign in first."
+ end
+ end
+
+ def create
+ current_user.send_verification_email
+ redirect_to verifications_path, :notice => "Verification email sent!"
+ end
+
+ def show
+ if params[:id].present? and user = User.where(:verification_token => params[:id]).first
+ if !user.verified?
+ user.verified_at = Time.zone.now
+ user.save!
+ end
+ path = forums_path
+ if p = current_user.participations.first
+ path = root_url(:subdomain => p.forum.subdomain)
+ end
+ redirect_to path, :notice => "Your account has been verified!"
+ end
+ end
+end
View
24 app/controllers/votes_controller.rb
@@ -0,0 +1,24 @@
+class VotesController < ApplicationController
+ before_filter :authenticate_user!
+ before_filter :require_subdomain!
+
+ def index
+ redirect_to root_path, :notice => "You'll need to enable javascript to vote"
+ end
+
+ def create
+ voteable = params[:dom_id].to_model
+
+ @error = nil
+ @error = "You are voting too fast. Please wait a bit." if current_user.over_rate_limit?
+
+ if @error.nil? and !current_user.banned_from?(voteable.forum)
+ if params[:toggle] == 'on'
+ current_user.vote(voteable, params[:direction].to_sym)
+ elsif params[:toggle] == 'off'
+ current_user.unvote(voteable)
+ end
+ voteable.update_ranking
+ end
+ end
+end
View
2 app/helpers/account/comments_helper.rb
@@ -0,0 +1,2 @@
+module Account::CommentsHelper
+end
View
2 app/helpers/account/profiles_helper.rb
@@ -0,0 +1,2 @@
+module Account::ProfilesHelper
+end
View
2 app/helpers/account/settings_helper.rb
@@ -0,0 +1,2 @@
+module Account::SettingsHelper
+end
View
2 app/helpers/account/submissions_helper.rb
@@ -0,0 +1,2 @@
+module Account::SubmissionsHelper
+end
View
2 app/helpers/account/themes_helper.rb
@@ -0,0 +1,2 @@
+module Account::ThemesHelper
+end
View
2 app/helpers/account/users_helper.rb
@@ -0,0 +1,2 @@
+module Account::UsersHelper
+end
View
40 app/helpers/application_helper.rb
@@ -1,2 +1,42 @@
module ApplicationHelper
+ def root_active?
+ controller_name == "users" and action_name == "new"
+ end
+
+ def signin_active?
+ controller_name == "sessions" and action_name == "new"
+ end
+
+ def flash_type_to_css_class type
+ case type
+ when :notice then 'warning'
+ when :alert then 'error'
+ end
+ end
+
+ def site_name
+ current_forum.present? ? current_forum.name : "Ribbot"
+ end
+
+ def title
+ return @title if @title.present?
+ return @post.title if @post.present?
+ site_name
+ end
+
+ def meta_description
+ return @meta_description if @meta_description.present?
+ return @post.text if @post.present?
+ ""
+ end
+
+ def comment_offset depth
+ depth = 8 if depth > 8
+ "comment-offset#{depth}"
+ end
+
+ def current_namespace
+ controller.class.name.split("::").first
+ end
+
end
View
2 app/helpers/password_resets_helper.rb
@@ -0,0 +1,2 @@
+module PasswordResetsHelper
+end
View
3 app/helpers/posts_helper.rb
@@ -0,0 +1,3 @@
+module PostsHelper
+
+end
View
5 app/helpers/static_helper.rb
@@ -0,0 +1,5 @@
+module StaticHelper
+ def checkmark
+ "<span style='color: green;'>&#x2713;</span>".html_safe
+ end
+end
View
14 app/helpers/url_helper.rb
@@ -0,0 +1,14 @@
+module UrlHelper
+ def with_subdomain(subdomain)
+ subdomain = (subdomain || "")
+ subdomain += "." unless subdomain.empty?
+ [subdomain, request.domain].join
+ end
+
+ def url_for(options = nil)
+ if options.kind_of?(Hash) && options.has_key?(:subdomain)
+ options[:host] = with_subdomain(options.delete(:subdomain))
+ end
+ super
+ end
+end
View
2 app/helpers/verifications_helper.rb
@@ -0,0 +1,2 @@
+module VerificationsHelper
+end
View
2 app/helpers/votes_helper.rb
@@ -0,0 +1,2 @@
+module VotesHelper
+end
View
13 app/mailers/mailer.rb
@@ -0,0 +1,13 @@
+class Mailer < ActionMailer::Base
+ default from: "no-reply@ribbot.com"
+
+ def password_reset user
+ @user = user
+ mail :to => user.email, :subject => "Resetting Your Password"
+ end
+
+ def email_verification user, forum=nil
+ @user = user
+ mail :to => user.email, :subject => "Please Verify Your Email Address"
+ end
+end
View
44 app/models/ability.rb
@@ -0,0 +1,44 @@
+class Ability
+ include CanCan::Ability
+
+ def initialize(user)
+
+ user ||= User.new # guest user (not logged in)
+
+ if user.superuser?
+ can :manage, :all
+ end
+
+ can :manage, Forum do |forum|
+ user.admin_of?(forum)
+ end
+
+ can :manage, User, :_id => user.id
+ can :manage, [Comment, Participation, Post], :user_id => user.id
+
+ # Admin actions
+ can :destroy, Comment do |c|
+ user.admin_of?(c.forum)
+ end
+ can :manage, Participation do |p|
+ user.admin_of?(p.forum)
+ end
+
+
+
+ #
+ # The first argument to `can` is the action you are giving the user permission to do.
+ # If you pass :manage it will apply to every action. Other common actions here are
+ # :read, :create, :update and :destroy.
+ #
+ # The second argument is the resource the user can perform the action on. If you pass
+ # :all it will apply to every resource. Otherwise pass a Ruby class of the resource.
+ #
+ # The third argument is an optional hash of conditions to further filter the objects.
+ # For example, here the user can only update published articles.
+ #
+ # can :update, Article, :published => true
+ #
+ # See the wiki for details: https://github.com/ryanb/cancan/wiki/Defining-Abilities
+ end
+end
View
70 app/models/comment.rb
@@ -0,0 +1,70 @@
+class Comment
+ include Mongoid::Document
+ include Mongoid::Timestamps
+ include Mongo::Voteable
+ acts_as_nested_set
+
+ field :text, type: String
+ field :deleted, type: Boolean, default: false
+ field :ranking, type: Float, default: 0.0
+
+ belongs_to :user, index: true
+ belongs_to :post, index: true
+ belongs_to :forum, index: true
+
+ validates_presence_of :text, :user, :post, :forum
+ validate :user_is_not_banned
+
+ voteable self, :up => +1, :down => -1
+
+ after_create :create_participation
+ after_create :inc_comment_count
+ after_destroy :dec_comment_count
+
+ attr_protected :parent_id
+
+ def create_participation
+ forum.add_member(user) unless user.member_of?(forum)
+ end
+
+ def inc_comment_count
+ post.inc(:comment_count, 1)
+ end
+
+ def dec_comment_count
+ post.inc(:comment_count, -1)
+ end
+
+ def user_is_not_banned
+ errors.add_to_base("You can no longer participate in this forum") if user.banned_from?(forum)
+ end
+
+ def update_ranking
+ if votes_point <= 0
+ self.update_attribute :ranking, votes_point
+ else
+ self.update_attribute :ranking, ci_lower_bound(up_votes_count, votes_count)
+ end
+ reorder
+ end
+
+ # http://www.evanmiller.org/how-not-to-sort-by-average-rating.html
+ def ci_lower_bound(pos, n, confidence=0.95)
+ return 0 if n == 0
+ z = 1.96 # Statistics2.pnormaldist(1-(1-confidence)/2)
+ phat = 1.0*pos/n
+ (phat + z*z/(2*n) - z * Math.sqrt((phat*(1-phat)+z*z/(4*n))/n))/(1+z*z/n)
+ end
+
+ # insertion sort to fixed the nested set when ranking changes
+ def reorder
+ sibs = siblings
+ return if sibs.empty?
+ sibs.each do |s|
+ if self.ranking >= s.ranking
+ self.move_to_left_of(s) and return
+ end
+ end
+ self.move_to_right_of(sibs.last)
+ end
+end
View
59 app/models/forum.rb
@@ -0,0 +1,59 @@
+class Forum
+ include Mongoid::Document
+ include Mongoid::Timestamps
+
+ POST_OPTIONS = {
+ :text_or_url => 0,
+ :url_or_text => 1,
+ :text_only => 2,
+ :url_only => 3
+ }
+
+ field :subdomain, type: String
+ field :name, type: String
+ field :description, type: String
+
+ field :post_options, type: Integer, default: POST_OPTIONS[:text_or_url]
+
+ field :post_label, type: String, default: "Post"
+ field :posts_label, type: String, default: "Posts"
+ field :new_post_label, type: String, default: "New Post"
+ field :comment_label, type: String, default: "Comment"
+ field :comments_label, type: String, default: "Comments"
+ field :new_comment_label, type: String, default: "Add Comment"
+
+ index :subdomain, unique: true
+
+ has_many :posts
+ has_many :participations
+ has_many :tags
+
+ validates_presence_of :subdomain, :name
+ validates_uniqueness_of :subdomain, :case_sensitive => false
+ validate :subdomain_uses_valid_characters
+
+ before_validation :set_default_name
+ before_save :downcase_subdomain
+
+ def subdomain_uses_valid_characters
+ errors.add(:subdomain, "can only use numbers and letters") if subdomain =~ /[^a-z0-9]/i
+ end
+
+ def set_default_name
+ if name.blank?
+ self.name = subdomain.titleize
+ end
+ end
+
+ def add_admin user
+ participations.create!(:user => user, :level => Participation::ADMIN)
+ end
+
+ def add_member user
+ participations.create!(:user => user, :level => Participation::MEMBER)
+ end
+
+ def downcase_subdomain
+ self.subdomain = subdomain.downcase
+ end
+end
View
25 app/models/participation.rb
@@ -0,0 +1,25 @@
+class Participation
+ include Mongoid::Document
+ include Mongoid::Timestamps
+
+ ADMIN = 0
+ MEMBER = 10
+
+ field :level, type: Integer
+ field :banned, type: Boolean, default: false
+
+ belongs_to :forum, index: true
+ belongs_to :user, index: true
+
+ validates_presence_of :level, :forum, :user
+
+ scope :admins, where(:level => ADMIN)
+
+ def level_in_words
+ case level
+ when ADMIN then "Admin"
+ when MEMBER then "Member"
+ else raise "invalid level"
+ end
+ end
+end
View
107 app/models/post.rb
@@ -0,0 +1,107 @@
+require 'uri'
+
+class Post
+ include Mongoid::Document
+ include Mongoid::Timestamps
+ include Sunspot::Mongoid
+ include Mongo::Voteable
+
+ field :title, type: String
+ field :url, type: String, index: true
+ field :text, type: String
+ field :ranking, type: Float, default: 0.0
+ field :comment_count, type: Integer, default: 0
+
+ belongs_to :user, index: true
+ belongs_to :forum, index: true
+ has_many :comments
+ has_and_belongs_to_many :tags, inverse_of: nil, index: true
+
+ validates_presence_of :title, :user, :forum
+ validate :user_is_not_banned
+ validate :url_is_new
+ validate :presence_of_url_or_text
+ validate :format_of_url
+
+ voteable self, :up => +1, :down => -1
+
+ after_create :create_participation
+ after_save :update_post_counts
+ after_destroy :update_post_counts
+
+ searchable do
+ text :title, :boost => 2.0, :stored => true
+ text :url, :stored => true
+ text :text, :stored => true
+ text :comments_texts do
+ comments.collect {|c| c.text }
+ end
+ string :forum_id, :references => Forum
+ string :tag_ids, :multiple => true
+ end