forum_monster 1.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (39) hide show
  1. data/.gitignore +24 -0
  2. data/LICENSE +20 -0
  3. data/README.rdoc +51 -0
  4. data/Rakefile +53 -0
  5. data/VERSION +1 -0
  6. data/lib/forum_monster.rb +3 -0
  7. data/lib/generators/forum_monster/install_generator.rb +79 -0
  8. data/lib/generators/forum_monster/templates/controllers/categories_controller.rb +42 -0
  9. data/lib/generators/forum_monster/templates/controllers/forums_controller.rb +42 -0
  10. data/lib/generators/forum_monster/templates/controllers/posts_controller.rb +56 -0
  11. data/lib/generators/forum_monster/templates/controllers/topics_controller.rb +46 -0
  12. data/lib/generators/forum_monster/templates/migrations/categories.rb +15 -0
  13. data/lib/generators/forum_monster/templates/migrations/forums.rb +19 -0
  14. data/lib/generators/forum_monster/templates/migrations/posts.rb +16 -0
  15. data/lib/generators/forum_monster/templates/migrations/topics.rb +19 -0
  16. data/lib/generators/forum_monster/templates/migrations/user.rb +11 -0
  17. data/lib/generators/forum_monster/templates/models/category.rb +14 -0
  18. data/lib/generators/forum_monster/templates/models/forum.rb +19 -0
  19. data/lib/generators/forum_monster/templates/models/post.rb +34 -0
  20. data/lib/generators/forum_monster/templates/models/topic.rb +37 -0
  21. data/lib/generators/forum_monster/templates/public/images/ruby.png +0 -0
  22. data/lib/generators/forum_monster/templates/public/stylesheets/forum-monster.css +56 -0
  23. data/lib/generators/forum_monster/templates/views/categories/_form.html.erb +41 -0
  24. data/lib/generators/forum_monster/templates/views/categories/edit.html.erb +1 -0
  25. data/lib/generators/forum_monster/templates/views/categories/index.html.erb +46 -0
  26. data/lib/generators/forum_monster/templates/views/categories/new.html.erb +1 -0
  27. data/lib/generators/forum_monster/templates/views/forums/_form.html.erb +61 -0
  28. data/lib/generators/forum_monster/templates/views/forums/edit.html.erb +1 -0
  29. data/lib/generators/forum_monster/templates/views/forums/index.html.erb +46 -0
  30. data/lib/generators/forum_monster/templates/views/forums/new.html.erb +1 -0
  31. data/lib/generators/forum_monster/templates/views/forums/show.html.erb +36 -0
  32. data/lib/generators/forum_monster/templates/views/posts/_form.html.erb +26 -0
  33. data/lib/generators/forum_monster/templates/views/posts/edit.html.erb +1 -0
  34. data/lib/generators/forum_monster/templates/views/posts/new.html.erb +1 -0
  35. data/lib/generators/forum_monster/templates/views/topics/_form.html.erb +36 -0
  36. data/lib/generators/forum_monster/templates/views/topics/edit.html.erb +1 -0
  37. data/lib/generators/forum_monster/templates/views/topics/new.html.erb +1 -0
  38. data/lib/generators/forum_monster/templates/views/topics/show.html.erb +42 -0
  39. metadata +84 -0
data/.gitignore ADDED
@@ -0,0 +1,24 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+ ._*
4
+ .AppleDouble
5
+
6
+ ## TEXTMATE
7
+ *.tmproj
8
+ tmtags
9
+
10
+ ## EMACS
11
+ *~
12
+ \#*
13
+ .\#*
14
+
15
+ ## VIM
16
+ *.swp
17
+
18
+ ## PROJECT::GENERAL
19
+ coverage
20
+ rdoc
21
+ pkg
22
+
23
+ ## PROJECT::SPECIFIC
24
+ *.gem
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 mkelley
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,51 @@
1
+ =Forum Monster
2
+
3
+ I've re-activated the issue tracker on the Github repository page.
4
+ I will be working on a refactoring of this code, please report any bugs you may find. I will greatly appreciate it.
5
+ *Pull requests welcome!*
6
+
7
+ Forum Monster is a simple forum generator written in rails 3. The goal of Forum Monster, is to provide a simple, and easy to setup forum application without having to dictate how your site it setup.
8
+
9
+ * Live Demo: http://forum_monster.dev.codezombie.org
10
+ * Github Repo for Demo: https://github.com/gitt/forum_monster_demo
11
+
12
+ ====A few things about what Forum Monster is, and is not:
13
+
14
+ * Forum Monster does not do any sort of authentication, or authorization. However, it does rely on the current_user method.
15
+ * Forum Monster while trying to assume as little as possible, currently assumes that the following columns are available from your user model: username, and created_at.
16
+ * Forum Monster does no authorization. By default all actions are available to all users. Even logged out users. ( Although, users who are not logged in cannot post, or create topics. )
17
+
18
+ ====Installation
19
+
20
+ Add the following to your Gemfile
21
+ gem 'forum_monster'
22
+
23
+ Generate the installation. <b><user model> should be the actual name of the model containing your user accounts.</b> This will copy all of the required controllers, models, views, and stylesheets to your application.
24
+ rails g forum_monster:install <user model>
25
+
26
+ Add the following to your user model to setup the needed associations with user/topics/posts
27
+ has_many :topics, :dependent => :destroy
28
+ has_many :posts, :dependent => :destroy
29
+
30
+ Finally, migrate your database
31
+ rake db:migrate
32
+
33
+ ====Authentication
34
+
35
+ Forum Monster, as stated before, does not come with any authentication built in. The reason for this is so you can add a forum to your existing application without having to change the way your application works. Forum Monster knows about your user model from the moment you run the installation command.
36
+
37
+ ====Authorization
38
+
39
+ Forum Monster, by default, allows all access to all users. Even those that are not currently logged in. This was by design, because of the vast number of authorization methods out there. If I tried to cover all of them it would just get out of hand. Not to mention that as soon as an API changes, Forum Monster would be broken. This also provides a large amount of flexibility. For example, if you wanted to use CanCan, you can! declarative_authorization? Yep. Aegis? Indeed! Since you have Forum Monster's controllers in your main application, you can customize them for your specific solution just like the rest of your application!
40
+
41
+ ====Avatars
42
+
43
+ I did not include support for avatars into Forum Monster for the same reason that authentication, and authorization were not included. Flexibility! You can use whatever you like, associate it with your user model, and put the corresponding image tag in the topic show view.
44
+
45
+ ====Markdown
46
+
47
+ Forum Monster has no forced support for markdown. Again, it's for flexibility.
48
+
49
+ ====Modifying the views, style, and adding your own images
50
+
51
+ Forum Monster will install the forum-monster.css stylesheet into your public/stylesheets directory. The views will be installed in your application app/views directory.
data/Rakefile ADDED
@@ -0,0 +1,53 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "Forum Monster"
8
+ gem.summary = %Q{A Rails 3 Forum Generator}
9
+ gem.description = %Q{A Rails 3 Forum Generator}
10
+ gem.email = "mike@codezombie.org"
11
+ gem.homepage = "http://github.com/gitt/forum_monster"
12
+ gem.authors = ["Mike Kelley"]
13
+ gem.files = Dir["{lib}/**/*", "{app}/**/*", "{config}/**/*", "{public}/**/*"]
14
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
15
+ end
16
+ Jeweler::GemcutterTasks.new
17
+ rescue LoadError
18
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
19
+ end
20
+
21
+ require 'rake/testtask'
22
+ Rake::TestTask.new(:test) do |test|
23
+ test.libs << 'lib' << 'test'
24
+ test.pattern = 'test/**/test_*.rb'
25
+ test.verbose = true
26
+ end
27
+
28
+ begin
29
+ require 'rcov/rcovtask'
30
+ Rcov::RcovTask.new do |test|
31
+ test.libs << 'test'
32
+ test.pattern = 'test/**/test_*.rb'
33
+ test.verbose = true
34
+ end
35
+ rescue LoadError
36
+ task :rcov do
37
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
38
+ end
39
+ end
40
+
41
+ task :test => :check_dependencies
42
+
43
+ task :default => :test
44
+
45
+ require 'rake/rdoctask'
46
+ Rake::RDocTask.new do |rdoc|
47
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
48
+
49
+ rdoc.rdoc_dir = 'rdoc'
50
+ rdoc.title = "Forum Monster #{version}"
51
+ rdoc.rdoc_files.include('README*')
52
+ rdoc.rdoc_files.include('lib/**/*.rb')
53
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 1.0.1
@@ -0,0 +1,3 @@
1
+ module ForumMonster
2
+ # Empty file... For simplicity!
3
+ end
@@ -0,0 +1,79 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ class ForumMonster::InstallGenerator < Rails::Generators::Base
5
+ include Rails::Generators::Migration
6
+
7
+ desc "Installs the ForumMonster Controllers, Models, Views, and Migrations."
8
+
9
+ argument :user_model, :type => :string, :required => false, :default => "User", :desc => "Your user model name."
10
+
11
+ attr_reader :singular_camel_case_name, :plural_camel_case_name, :singular_lower_case_name, :plural_lower_case_name
12
+
13
+ def self.source_root
14
+ @source_root ||= File.join(File.dirname(__FILE__), 'templates')
15
+ end
16
+
17
+ def self.next_migration_number(dirname)
18
+ if ActiveRecord::Base.timestamped_migrations
19
+ Time.now.utc.strftime("%Y%m%d%H%M%S")
20
+ else
21
+ "%.3d" % (current_migration_number(dirname) + 1)
22
+ end
23
+ end
24
+
25
+ def create_controllers
26
+ template "controllers/categories_controller.rb", "app/controllers/categories_controller.rb"
27
+ template "controllers/forums_controller.rb", "app/controllers/forums_controller.rb"
28
+ template "controllers/topics_controller.rb", "app/controllers/topics_controller.rb"
29
+ template "controllers/posts_controller.rb", "app/controllers/posts_controller.rb"
30
+ end
31
+
32
+ def create_models
33
+ @singular_camel_case_name = user_model.singularize.camelize
34
+ @plural_camel_case_name = user_model.pluralize.camelize
35
+ @singular_lower_case_name = user_model.singularize.underscore
36
+ @plural_lower_case_name = user_model.pluralize.underscore
37
+
38
+ template "models/category.rb", "app/models/category.rb"
39
+ template "models/forum.rb", "app/models/forum.rb"
40
+ template "models/topic.rb", "app/models/topic.rb"
41
+ template "models/post.rb", "app/models/post.rb"
42
+ end
43
+
44
+ def create_views
45
+ directory "views/categories", "app/views/categories"
46
+ directory "views/forums", "app/views/forums"
47
+ directory "views/topics", "app/views/topics"
48
+ directory "views/posts", "app/views/posts"
49
+ template "public/stylesheets/forum-monster.css", "public/stylesheets/forum-monster.css"
50
+ template "public/images/ruby.png", "public/images/ruby.png"
51
+ end
52
+
53
+ def create_migrations
54
+ migration_template 'migrations/categories.rb', 'db/migrate/create_categories_table.rb'
55
+ migration_template 'migrations/forums.rb', 'db/migrate/create_forums_table.rb'
56
+ migration_template 'migrations/topics.rb', 'db/migrate/create_topics_table.rb'
57
+ migration_template 'migrations/posts.rb', 'db/migrate/create_posts_table.rb'
58
+ migration_template 'migrations/user.rb', 'db/migrate/update_users_table.rb'
59
+ end
60
+
61
+ def create_routes
62
+ route "resources :categories, :except => [:index, :show]
63
+ resources :forums, :except => :index do
64
+ resources :topics, :shallow => true, :except => :index do
65
+ resources :posts, :shallow => true, :except => [:index, :show]
66
+ end
67
+ root :to => 'categories#index', :via => :get
68
+ end"
69
+ end
70
+
71
+ def self.next_migration_number(path)
72
+ unless @prev_migration_nr
73
+ @prev_migration_nr = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
74
+ else
75
+ @prev_migration_nr += 1
76
+ end
77
+ @prev_migration_nr.to_s
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ class CategoriesController < ApplicationController
2
+ def index
3
+ @categories = Category.all
4
+ end
5
+
6
+ def new
7
+ @category = Category.new
8
+ end
9
+
10
+ def create
11
+ @category = Category.new(params[:category])
12
+
13
+ if @category.save
14
+ flash[:notice] = "Category was successfully created."
15
+ redirect_to forums_url
16
+ else
17
+ render :action => 'new'
18
+ end
19
+ end
20
+
21
+ def edit
22
+ @category = Category.find(params[:id])
23
+ end
24
+
25
+ def update
26
+ @category = Category.find(params[:id])
27
+
28
+ if @category.update_attributes(params[:category])
29
+ flash[:notice] = "Category was updated successfully."
30
+ redirect_to forums_url
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ @category = Category.find(params[:id])
36
+
37
+ if @category.destroy
38
+ flash[:notice] = "Category was deleted."
39
+ redirect_to forums_url
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,42 @@
1
+ class ForumsController < ApplicationController
2
+ def show
3
+ @forum = Forum.find(params[:id])
4
+ end
5
+
6
+ def new
7
+ @forum = Forum.new
8
+ end
9
+
10
+ def create
11
+ @forum = Forum.new(params[:forum])
12
+
13
+ if @forum.save
14
+ flash[:notice] = "Forum was successfully created."
15
+ redirect_to forums_url
16
+ else
17
+ render :action => 'new'
18
+ end
19
+ end
20
+
21
+ def edit
22
+ @forum = Forum.find(params[:id])
23
+ end
24
+
25
+ def update
26
+ @forum = Forum.find(params[:id])
27
+
28
+ if @forum.update_attributes(params[:forum])
29
+ flash[:notice] = "Forum was updated successfully."
30
+ redirect_to forum_url(@forum)
31
+ end
32
+ end
33
+
34
+ def destroy
35
+ @forum = Forum.find(params[:id])
36
+
37
+ if @forum.destroy
38
+ flash[:notice] = "Category was deleted."
39
+ redirect_to forums_url
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,56 @@
1
+ class PostsController < ApplicationController
2
+ def new
3
+ @topic = Topic.find(params[:topic_id])
4
+ @post = Post.new
5
+
6
+ if params[:quote]
7
+ quote_post = Post.find(params[:quote])
8
+ if quote_post
9
+ @post.body = quote_post.body
10
+ end
11
+ end
12
+ end
13
+
14
+ def create
15
+ @topic = Topic.find(params[:topic_id])
16
+ @post = @topic.posts.build(params[:post])
17
+ @post.forum = @topic.forum
18
+ @post.user = current_user
19
+
20
+ if @post.save
21
+ flash[:notice] = "Post was successfully created."
22
+ redirect_to topic_path(@post.topic)
23
+ else
24
+ render :action => 'new'
25
+ end
26
+ end
27
+
28
+ def edit
29
+ @post = Post.find(params[:id])
30
+ end
31
+
32
+ def update
33
+ @post = Post.find(params[:id])
34
+
35
+ if @post.update_attributes(params[:post])
36
+ flash[:notice] = "Post was successfully updated."
37
+ redirect_to topic_path(@post.topic)
38
+ end
39
+ end
40
+
41
+ def destroy
42
+ @post = Post.find(params[:id])
43
+
44
+ if @post.topic.posts_count > 1
45
+ if @post.destroy
46
+ flash[:notice] = "Post was successfully destroyed."
47
+ redirect_to topic_path(@post.topic)
48
+ end
49
+ else
50
+ if @post.topic.destroy
51
+ flash[:notice] = "Topic was successfully deleted."
52
+ redirect_to forum_path(@post.forum)
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,46 @@
1
+ class TopicsController < ApplicationController
2
+ def show
3
+ @topic = Topic.find(params[:id])
4
+ @topic.hit! if @topic
5
+ end
6
+
7
+ def new
8
+ @forum = Forum.find(params[:forum_id])
9
+ @topic = Topic.new
10
+ end
11
+
12
+ def create
13
+ @forum = Forum.find(params[:forum_id])
14
+ @topic = @forum.topics.build(params[:topic])
15
+ @topic.user = current_user
16
+
17
+ if @topic.save
18
+ flash[:notice] = "Topic was successfully created."
19
+ redirect_to topic_url(@topic)
20
+ else
21
+ render :action => 'new'
22
+ end
23
+ end
24
+
25
+ def edit
26
+ @topic = Topic.find(params[:id])
27
+ end
28
+
29
+ def update
30
+ @topic = Topic.find(params[:id])
31
+
32
+ if @topic.update_attributes(params[:topic])
33
+ flash[:notice] = "Topic was updated successfully."
34
+ redirect_to topic_url(@topic)
35
+ end
36
+ end
37
+
38
+ def destroy
39
+ @topic = Topic.find(params[:id])
40
+
41
+ if @topic.destroy
42
+ flash[:notice] = "Topic was deleted successfully."
43
+ redirect_to forum_url(@topic.forum)
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,15 @@
1
+ class CreateCategoriesTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :categories, :force => true do |t|
4
+ t.string :title
5
+ t.boolean :state, :default => true
6
+ t.integer :position, :default => 0
7
+
8
+ t.timestamps
9
+ end
10
+ end
11
+
12
+ def self.down
13
+ drop_table :categories
14
+ end
15
+ end
@@ -0,0 +1,19 @@
1
+ class CreateForumsTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :forums, :force => true do |t|
4
+ t.string :title
5
+ t.text :description
6
+ t.boolean :state, :default => true
7
+ t.integer :topics_count, :default => 0
8
+ t.integer :posts_count, :default => 0
9
+ t.integer :position, :default => 0
10
+ t.integer :category_id
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+
16
+ def self.down
17
+ drop_table :forums
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ class CreatePostsTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :posts, :force => true do |t|
4
+ t.string :body
5
+ t.integer :forum_id
6
+ t.integer :topic_id
7
+ t.integer :user_id
8
+
9
+ t.timestamps
10
+ end
11
+ end
12
+
13
+ def self.down
14
+ drop_table :posts
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ class CreateTopicsTable < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :topics, :force => true do |t|
4
+ t.string :title
5
+ t.integer :hits, :default => 0
6
+ t.boolean :sticky, :default => false
7
+ t.boolean :locked, :default => false
8
+ t.integer :posts_count
9
+ t.integer :forum_id
10
+ t.integer :user_id
11
+
12
+ t.timestamps
13
+ end
14
+ end
15
+
16
+ def self.down
17
+ drop_table :topics
18
+ end
19
+ end
@@ -0,0 +1,11 @@
1
+ class <%= "Update#{plural_camel_case_name}Table" %> < ActiveRecord::Migration
2
+ def self.up
3
+ add_column :<%= plural_lower_case_name %>, :topics_count, :integer, :default => 0
4
+ add_column :<%= plural_lower_case_name %>, :posts_count, :integer, :default => 0
5
+ end
6
+
7
+ def self.down
8
+ remove_column :<%= plural_lower_case_name %>, :topics_count
9
+ remove_column :<%= plural_lower_case_name %>, :posts_count
10
+ end
11
+ end
@@ -0,0 +1,14 @@
1
+ class Category < ActiveRecord::Base
2
+
3
+ # Associations
4
+ has_many :forums, :dependent => :destroy
5
+
6
+ # Accessors
7
+ attr_accessible :title, :state, :position, :category_id
8
+
9
+ # Scopes
10
+ default_scope :order => 'position ASC'
11
+
12
+ # Validations
13
+ validates :title, :presence => true
14
+ end
@@ -0,0 +1,19 @@
1
+ class Forum < ActiveRecord::Base
2
+
3
+ # Associations
4
+ has_many :topics, :dependent => :destroy
5
+ has_many :posts, :through => :topics
6
+
7
+ belongs_to :category
8
+
9
+ # Accessors
10
+ attr_accessible :title, :description, :state, :position, :category_id
11
+
12
+ # Scopes
13
+ default_scope :order => 'position ASC'
14
+
15
+ # Validations
16
+ validates :title, :presence => true
17
+ validates :description, :presence => true
18
+ validates :category_id, :presence => true
19
+ end
@@ -0,0 +1,34 @@
1
+ class Post < ActiveRecord::Base
2
+
3
+ # Associations
4
+ belongs_to :forum, :counter_cache => true
5
+ belongs_to :topic, :counter_cache => true, :touch => true
6
+ belongs_to :user, :class_name => "<%= "#{singular_camel_case_name}" %>", :counter_cache => true
7
+
8
+ # Accessors
9
+ attr_accessible :body
10
+
11
+ # Validations
12
+ validates :body, :presence => true
13
+ validates :user, :presence => true
14
+
15
+ # Default Scope
16
+ default_scope :order => 'created_at ASC'
17
+
18
+ # Scope to display only the last n posts. Used for "Recent Posts" display
19
+ scope :recent, lambda {
20
+ |c| reorder('created_at desc').limit(c)
21
+ }
22
+
23
+ # Callbacks
24
+ before_save :topic_locked?
25
+
26
+ # Methods
27
+ private
28
+ def topic_locked?
29
+ if topic.locked?
30
+ errors.add(:base, "That topic is locked")
31
+ false
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,37 @@
1
+ class Topic < ActiveRecord::Base
2
+
3
+ # Associations
4
+ has_many :posts, :dependent => :destroy
5
+ belongs_to :forum, :counter_cache => true
6
+ belongs_to :user, :class_name => "<%= "#{singular_camel_case_name}" %>", :counter_cache => true
7
+
8
+ # Accessors
9
+ attr_accessor :body
10
+ attr_accessible :title, :body, :sticky, :locked
11
+
12
+ # Validations
13
+ validates :title, :presence => true
14
+ validates :body, :presence => true, :on => :create
15
+ validates :posts, :presence => true, :allow_nil => false, :on => :update
16
+ validates :user, :presence => true
17
+
18
+ # Scopes
19
+ default_scope :order => 'sticky DESC, updated_at DESC'
20
+
21
+ # Callbacks
22
+ after_create :create_initial_post
23
+
24
+ # Methods
25
+ def hit!
26
+ self.class.increment_counter :hits, id
27
+ end
28
+
29
+ private
30
+ def create_initial_post
31
+ self.posts.build(:body => self.body).tap do |post|
32
+ post.forum = self.forum
33
+ post.user = self.user
34
+ post.save
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,56 @@
1
+ /* Modules
2
+ --------------------------------------------------------------------------------------------------*/
3
+ .module { border:1px solid #e2e2e2; margin:.8em 0; background-color:#fff; overflow:auto; }
4
+ .module_controls { padding:.8em; }
5
+ .module_header { color:#fff; padding:.7em .7em .7em 1.4em; background-color:#000; }
6
+ .module_header a { color:#fff; }
7
+ .module_subheader, .module_footer { margin:.6em .8em; padding:.6em; }
8
+ .module_subheader { border-bottom:1px solid #e2e2e2; }
9
+ .module_footer { border-top:1px solid #e2e2e2; }
10
+ .module_body { padding:1em; }
11
+
12
+ /* Form Fields & Labels
13
+ --------------------------------------------------------------------------------------------------*/
14
+ .module .fieldset { width:100%; }
15
+ .module .fieldset .indent { width:16em; }
16
+ .module .fieldset .label { font-weight:bold; text-align:right; display:block; float:left; padding:6px 0px 2px 1em; }
17
+ .module .fieldset .label small { font-weight:normal; }
18
+ .module .fieldset .input { padding:.2em 1em; display:block; float:left; }
19
+
20
+ /* Common
21
+ --------------------------------------------------------------------------------------------------*/
22
+ .module .clear { clear: both; height: 0; overflow: hidden; }
23
+ .module .smaller { font-size:.9em; }
24
+ .module .left { float:left; }
25
+ .module .right { float:right; text-align:right; }
26
+ .controls a { margin:0 5px; font-size:.8em; }
27
+
28
+ /* Tables
29
+ --------------------------------------------------------------------------------------------------*/
30
+ table { width:100%; border-collapse:collapse; }
31
+ table th { font-weight:normal; padding:.7em; font-size:.8em; }
32
+ table td { padding:.5em; border:1px solid #e2e2e2; border-bottom:0px; vertical-align:top; background:#fff; }
33
+ table td:first-child { border-left:0px; }
34
+ table td:last-child { border-right:0px; }
35
+
36
+ table .icon { width:26px; text-align:center; }
37
+ table .counts { width:8%; text-align:center; }
38
+ table .last_post { padding-left:10px; }
39
+ table .description { width:55%; text-align:left; padding-left:20px; }
40
+
41
+ /* Post View Table
42
+ --------------------------------------------------------------------------------------------------*/
43
+ table .post_author { padding-left:15px; vertical-align:top !important; }
44
+ table .post_author .name { font-size:1.5em; display:block; margin-bottom:5px; }
45
+ table .post_author .name a { margin-left:-20px; }
46
+ table .post_author .info { display:block; margin:5px 0; }
47
+ table .post_body { width:80%; padding:10px 10px 30px 10px; border-bottom:0px; }
48
+
49
+ /* BBCode
50
+ --------------------------------------------------------------------------------------------------*/
51
+ blockquote {
52
+ border: 1px solid #e2e2e2;
53
+ font-style: italic;
54
+ margin: 10px 0px 0px 25px;
55
+ padding: 10px;
56
+ }
@@ -0,0 +1,41 @@
1
+ <div class="module">
2
+ <div class="module_header"><%= action_name.humanize %> Category</div>
3
+ <div class="module_subheader smaller"></div>
4
+ <div class="module_body">
5
+ <%= form_for @category do |f| %>
6
+ <% if @category.errors.any? %>
7
+ <% flash.now[:error] = @category.errors.full_messages.join(', and ') %>
8
+ <% end %>
9
+ <div class="fieldset">
10
+ <span class="label indent smaller">
11
+ <%= f.label :title %><br />
12
+ <small>(Required)</small>
13
+ </span>
14
+ <span class="input indent smaller"><%= f.text_field :title, :size => 75 %></span>
15
+ <div class="clear"></div>
16
+ </div>
17
+ <div class="fieldset">
18
+ <span class="label indent smaller">
19
+ <%= f.label :position %>
20
+ </span>
21
+ <span class="input indent smaller"><%= f.text_field :position %></span>
22
+ <div class="clear"></div>
23
+ </div>
24
+ <div class="fieldset">
25
+ <span class="label indent smaller"></span>
26
+ <span class="input indent smaller">
27
+ <%= f.check_box :state %>
28
+ <%= f.label :state %>
29
+ </span>
30
+ <div class="clear"></div>
31
+ </div>
32
+ </div>
33
+ <div class="module_footer">
34
+ <div class="fieldset">
35
+ <span class="input"><%= f.submit "submit" %> or <%= link_to "cancel", forums_path %></span>
36
+ <div class="clear"></div>
37
+ </div>
38
+ </div>
39
+ <% end %>
40
+ </div>
41
+ </div>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,46 @@
1
+ <div class="right controls"><%= link_to "New Forum Category", new_category_path %></div>
2
+ <% @categories.each do |category| %>
3
+ <div class="module">
4
+ <div class="module_header">
5
+ <%= category.title %>
6
+ <span class="controls right smaller">
7
+ <%= link_to "New Forum", new_forum_path %>
8
+ <%= link_to "Edit Category", edit_category_path(category) %>
9
+ <%= link_to "Delete Category", category_path(category), :confirm => "Are you sure you want to delete this category?", :method => :delete %>
10
+ </span>
11
+ </div>
12
+ <% if category.forums.size > 0 %>
13
+ <div>
14
+ <table>
15
+ <tr class="smaller">
16
+ <th colspan="2" align="left">Forum</th>
17
+ <th>Topics</th>
18
+ <th>Posts</th>
19
+ <th class="last_post" align="left">Last Post</th>
20
+ </tr>
21
+ <% category.forums.each do |forum| %>
22
+ <tr>
23
+ <td class="icon"><%= image_tag 'ruby.png' %></td>
24
+ <td class="description">
25
+ <%= link_to forum.title, forum_path(forum) %><br />
26
+ <span class="smaller"><%= forum.description %></span><br />
27
+ </td>
28
+ <td class="counts smaller"><%= forum.topics.size %></td>
29
+ <td class="counts smaller"><%= forum.posts.size - forum.topics.size %></td>
30
+ <td class="last_post smaller">
31
+ <% if forum.posts.size > 0 %>
32
+ <%= forum.posts.last.created_at %><br />
33
+ <%= forum.posts.last.user.username %>
34
+ <% else %>
35
+ No Topics / Posts
36
+ <% end %>
37
+ </td>
38
+ </tr>
39
+ <% end %>
40
+ </table>
41
+ </div>
42
+ <% else %>
43
+ <div class="module_body">There are currently no forums.</div>
44
+ <% end %>
45
+ </div>
46
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,61 @@
1
+ <div class="module">
2
+ <div class="module_header"><%= action_name.humanize %> Forum</div>
3
+ <div class="module_subheader smaller">
4
+ <em>To create a category, leave the category field unselected.</em>
5
+ </div>
6
+ <div class="module_body">
7
+ <%= form_for @forum do |f| %>
8
+ <% if @forum.errors.any? %>
9
+ <% flash.now[:error] = @forum.errors.full_messages.join(', and ') %>
10
+ <% end %>
11
+ <div class="fieldset">
12
+ <span class="label indent smaller">
13
+ <%= f.label :category_id %><br />
14
+ <small>(Required)</small>
15
+ </span>
16
+ <span class="input indent smaller">
17
+ <%= f.collection_select :category_id, Category.all, :id, :title %>
18
+ </span>
19
+ <div class="clear"></div>
20
+ </div>
21
+ <div class="fieldset">
22
+ <span class="label indent smaller">
23
+ <%= f.label :title %><br />
24
+ <small>(Required)</small>
25
+ </span>
26
+ <span class="input indent smaller"><%= f.text_field :title, :size => 75 %></span>
27
+ <div class="clear"></div>
28
+ </div>
29
+ <div class="fieldset">
30
+ <span class="label indent smaller">
31
+ <%= f.label :description %><br />
32
+ <small>(Required)</small>
33
+ </span>
34
+ <span class="input indent smaller"><%= f.text_area :description, :cols => 60, :rows => 5 %></span>
35
+ <div class="clear"></div>
36
+ </div>
37
+ <div class="fieldset">
38
+ <span class="label indent smaller">
39
+ <%= f.label :position %>
40
+ </span>
41
+ <span class="input indent smaller"><%= f.text_field :position %></span>
42
+ <div class="clear"></div>
43
+ </div>
44
+ <div class="fieldset">
45
+ <span class="label indent smaller"></span>
46
+ <span class="input indent smaller">
47
+ <%= f.check_box :state %>
48
+ <%= f.label :state %>
49
+ </span>
50
+ <div class="clear"></div>
51
+ </div>
52
+ </div>
53
+ <div class="module_footer">
54
+ <div class="fieldset">
55
+ <span class="input"><%= f.submit "submit" %> or <%= link_to "cancel", @forum.nil? ? forum_path(@forum) : forums_path %></span>
56
+ <div class="clear"></div>
57
+ </div>
58
+ </div>
59
+ <% end %>
60
+ </div>
61
+ </div>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,46 @@
1
+ <div class="right controls"><%= link_to "New Forum/Category", new_forum_path %></div>
2
+ <% @categories.each do |category| %>
3
+ <div class="module">
4
+ <div class="module_header">
5
+ <%= category.title %>
6
+ <span class="controls right smaller">
7
+ <%= link_to "New Forum", new_forum_path %>
8
+ <%= link_to "Edit Category", edit_forum_path(category) %>
9
+ <%= link_to "Delete Category", forum_path(category), :confirm => "Are you sure you want to delete this category?", :method => :delete %>
10
+ </span>
11
+ </div>
12
+ <% if category.forums.size > 0 %>
13
+ <div>
14
+ <table>
15
+ <tr class="smaller">
16
+ <th colspan="2" align="left">Forum</th>
17
+ <th>Topics</th>
18
+ <th>Posts</th>
19
+ <th class="last_post" align="left">Last Post</th>
20
+ </tr>
21
+ <% category.forums.each do |forum| %>
22
+ <tr>
23
+ <td class="icon"><%= image_tag 'ruby.png' %></td>
24
+ <td class="description">
25
+ <%= link_to forum.title, forum_path(forum) %><br />
26
+ <span class="smaller"><%= forum.description %></span><br />
27
+ </td>
28
+ <td class="counts smaller"><%= forum.topics.size %></td>
29
+ <td class="counts smaller"><%= forum.posts.size - forum.topics.size %></td>
30
+ <td class="last_post smaller">
31
+ <% if forum.posts.size > 0 %>
32
+ <%= forum.posts.last.created_at %><br />
33
+ <%= forum.posts.last.user.username %>
34
+ <% else %>
35
+ No Topics / Posts
36
+ <% end %>
37
+ </td>
38
+ </tr>
39
+ <% end %>
40
+ </table>
41
+ </div>
42
+ <% else %>
43
+ <div class="module_body">There are currently no forums.</div>
44
+ <% end %>
45
+ </div>
46
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,36 @@
1
+ <div class="right controls"><%= link_to "Back to Forum List", forums_path %></div>
2
+ <div class="module">
3
+ <div class="module_header">
4
+ <%= @forum.title %>
5
+ <span class="controls right">
6
+ <%= link_to "New Topic", new_forum_topic_path(@forum) %>
7
+ <%= link_to "Edit Forum", edit_forum_path(@forum) %>
8
+ <%= link_to "Delete Forum", forum_path(@forum), :confirm => "Are you sure you want to delete this forum?", :method => :delete %>
9
+ </span>
10
+ </div>
11
+ <div>
12
+ <table>
13
+ <tr class="smaller">
14
+ <th colspan="2" align="left">Topic</th>
15
+ <th>Replies</th>
16
+ <th>Views</th>
17
+ <th class="last_post" align="left">Last Post</th>
18
+ </tr>
19
+ <% @forum.topics.each do |topic| %>
20
+ <tr>
21
+ <td class="icon"><%= image_tag 'ruby.png' %></td>
22
+ <td class="description">
23
+ <%= link_to topic.title, topic_path(topic) %><br />
24
+ <span class="smaller">by <%= topic.user.username %></span>
25
+ </td>
26
+ <td class="counts smaller"><%= topic.posts.size - 1 %></td>
27
+ <td class="counts smaller"><%= topic.hits %></td>
28
+ <td class="last_post smaller">
29
+ <%= topic.posts.last.created_at %><br />
30
+ by <%= topic.posts.last.user.username %>
31
+ </td>
32
+ </tr>
33
+ <% end %>
34
+ </table>
35
+ </div>
36
+ </div>
@@ -0,0 +1,26 @@
1
+ <div class="module">
2
+ <div class="module_header"><%= action_name.humanize %> Post</div>
3
+ <div class="module_subheader smaller"></div>
4
+ <div class="module_body">
5
+ <%= form_for [@topic, @post] do |f| %>
6
+ <% if @post.errors.any? %>
7
+ <% flash.now[:error] = @post.errors.full_messages.join(', and ') %>
8
+ <% end %>
9
+ <div class="fieldset">
10
+ <span class="label indent smaller">
11
+ <%= f.label :body %><br />
12
+ <small>(Required)</small>
13
+ </span>
14
+ <span class="input indent smaller"><%= f.text_area :body, :cols => 60, :rows => 15 %></span>
15
+ <div class="clear"></div>
16
+ </div>
17
+ </div>
18
+ <div class="module_footer">
19
+ <div class="fieldset">
20
+ <span class="input"><%= f.submit "submit" %> or <%= link_to "cancel", @topic %></span>
21
+ <div class="clear"></div>
22
+ </div>
23
+ </div>
24
+ <% end %>
25
+ </div>
26
+ </div>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,36 @@
1
+ <%= form_for [@forum, @topic] do |f| %>
2
+ <% if @topic.errors.any? %>
3
+ <% flash.now[:error] = @topic.errors.full_messages.join(', and ') %>
4
+ <% end %>
5
+ <div class="module">
6
+ <div class="module_header"><%= action_name.humanize %> Topic</div>
7
+ <div class="module_subheader smaller"></div>
8
+ <div class="module_body">
9
+ <div class="fieldset">
10
+ <span class="label indent smaller">
11
+ <%= f.label :title %><br />
12
+ <small>(Required)</small>
13
+ </span>
14
+ <span class="input indent smaller"><%= f.text_field :title, :size => 75 %></span>
15
+ <div class="clear"></div>
16
+ </div>
17
+ <% unless @topic.id %>
18
+ <div class="fieldset">
19
+ <span class="label indent smaller">
20
+ <%= f.label :body %><br />
21
+ <small>(Required)</small>
22
+ </span>
23
+ <span class="input indent smaller"><%= f.text_area :body, :cols => 60, :rows => 15 %></span>
24
+ <div class="clear"></div>
25
+ </div>
26
+ </div>
27
+ <% end %>
28
+ <div class="module_footer">
29
+ <div class="fieldset">
30
+ <span class="input"><%= f.submit "submit" %> or <%= link_to "cancel", @topic.nil? ? @topic : @forum %></span>
31
+ <div class="clear"></div>
32
+ </div>
33
+ </div>
34
+ </div>
35
+ </div>
36
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1 @@
1
+ <%= render :partial => 'form' %>
@@ -0,0 +1,42 @@
1
+ <div class="right controls"><%= link_to "Back to Forum", forum_path(@topic.forum) %></div>
2
+ <div class="module">
3
+ <div class="module_header">
4
+ <%= @topic.title %>
5
+ <span class="right controls">
6
+ <%= link_to "Edit", edit_topic_path(@topic) %>
7
+ <%= link_to "Delete", @topic, :confirm => "Are you sure?", :method => :delete %>
8
+ <%= link_to @topic.sticky ? "Unstick" : "Sticky", {:controller => 'topics', :action => 'update', :topic => {:sticky => @topic.sticky ? "false" : "true" }}, :method => :put %>
9
+ <%= link_to @topic.locked ? "Unlock" : "Lock", {:controller => 'topics', :action => 'update', :topic => {:locked => @topic.locked ? "false" : "true" }}, :method => :put %>
10
+ </span>
11
+ </div>
12
+ <div>
13
+ <table>
14
+ <% @topic.posts.each do |post| %>
15
+ <tr>
16
+ <td class="post_author" rowspan="2">
17
+ <span class="name"><%= post.user.username %></span>
18
+ <span class="avatar"><!-- This space reserved for Avatar --></span>
19
+ <span class="info smaller">
20
+ Posts <%= post.user.posts.size %><br />
21
+ Registered <%= post.user.created_at.to_s(:joined) %><br />
22
+ </span>
23
+ </td>
24
+ <td class="post_header">
25
+ <span class="left post_date smaller">Posted <%= post.created_at %></span>
26
+ <span class="right controls">
27
+ <%= link_to "Reply", new_topic_post_path(@topic) %>
28
+ <%= link_to "Quote", new_topic_post_path(@topic, :quote => post) %>
29
+ <%= link_to "Edit", edit_post_path(post) %>
30
+ <%= link_to "Delete", post, :confirm => "Are you sure?", :method => :delete %>
31
+ </span>
32
+ </td>
33
+ </tr>
34
+ <tr>
35
+ <td class="post_body">
36
+ <%= post.body %>
37
+ </td>
38
+ </tr>
39
+ <% end %>
40
+ </table>
41
+ </div>
42
+ </div>
metadata ADDED
@@ -0,0 +1,84 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: forum_monster
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mike Kelley
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-03-28 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: A Rails 3 Forum Generator
15
+ email: mike@codezombie.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files:
19
+ - LICENSE
20
+ - README.rdoc
21
+ files:
22
+ - .gitignore
23
+ - LICENSE
24
+ - README.rdoc
25
+ - Rakefile
26
+ - VERSION
27
+ - lib/forum_monster.rb
28
+ - lib/generators/forum_monster/install_generator.rb
29
+ - lib/generators/forum_monster/templates/controllers/categories_controller.rb
30
+ - lib/generators/forum_monster/templates/controllers/forums_controller.rb
31
+ - lib/generators/forum_monster/templates/controllers/posts_controller.rb
32
+ - lib/generators/forum_monster/templates/controllers/topics_controller.rb
33
+ - lib/generators/forum_monster/templates/migrations/categories.rb
34
+ - lib/generators/forum_monster/templates/migrations/forums.rb
35
+ - lib/generators/forum_monster/templates/migrations/posts.rb
36
+ - lib/generators/forum_monster/templates/migrations/topics.rb
37
+ - lib/generators/forum_monster/templates/migrations/user.rb
38
+ - lib/generators/forum_monster/templates/models/category.rb
39
+ - lib/generators/forum_monster/templates/models/forum.rb
40
+ - lib/generators/forum_monster/templates/models/post.rb
41
+ - lib/generators/forum_monster/templates/models/topic.rb
42
+ - lib/generators/forum_monster/templates/public/images/ruby.png
43
+ - lib/generators/forum_monster/templates/public/stylesheets/forum-monster.css
44
+ - lib/generators/forum_monster/templates/views/categories/_form.html.erb
45
+ - lib/generators/forum_monster/templates/views/categories/edit.html.erb
46
+ - lib/generators/forum_monster/templates/views/categories/index.html.erb
47
+ - lib/generators/forum_monster/templates/views/categories/new.html.erb
48
+ - lib/generators/forum_monster/templates/views/forums/_form.html.erb
49
+ - lib/generators/forum_monster/templates/views/forums/edit.html.erb
50
+ - lib/generators/forum_monster/templates/views/forums/index.html.erb
51
+ - lib/generators/forum_monster/templates/views/forums/new.html.erb
52
+ - lib/generators/forum_monster/templates/views/forums/show.html.erb
53
+ - lib/generators/forum_monster/templates/views/posts/_form.html.erb
54
+ - lib/generators/forum_monster/templates/views/posts/edit.html.erb
55
+ - lib/generators/forum_monster/templates/views/posts/new.html.erb
56
+ - lib/generators/forum_monster/templates/views/topics/_form.html.erb
57
+ - lib/generators/forum_monster/templates/views/topics/edit.html.erb
58
+ - lib/generators/forum_monster/templates/views/topics/new.html.erb
59
+ - lib/generators/forum_monster/templates/views/topics/show.html.erb
60
+ homepage: http://github.com/gitt/forum_monster
61
+ licenses: []
62
+ post_install_message:
63
+ rdoc_options: []
64
+ require_paths:
65
+ - lib
66
+ required_ruby_version: !ruby/object:Gem::Requirement
67
+ none: false
68
+ requirements:
69
+ - - ! '>='
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.5
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: A Simple Rails 3 Forum Generator
84
+ test_files: []