Savage Beast 2.0 – A Rails 2.0 Message Forum Plugin

Update: If you’re running Rails 2.2 or 2.3, see the newer version of Savage Beast.

I’ve been working the last couple days on creating a new version of the original Savage Beast plugin that is Rails 2.0 compliant and integrates the changes to the Beast source code that have been added over the last year. The result has been an interesting trek through the ins and outs of Rails plugin writing, that has given birth to a new version of the Savage Beast plugin, re-ported from scratch from the Beast trunk.

Installation

Currently, the following is necessary to use the Savage Beast plugin:

  1. The Savage Beast 2.0 plugin. Go to your application root directory and:
    svn export http://savage-beast-2.googlecode.com/svn/trunk/ vendor/plugins/savage_beast
  2. Most of the stuff you need to run Beast
    • Redcloth: gem install Redcloth
    • A bunch of plugins (white_list, white_list_formatted_content, acts_as_list, gibberish, will_paginate, engines). The easiest way to install these en masse is just to copy the contents of savage_beast/tested_plugins to your standard Rails plugin directory (/vendor/plugins). If you already have versions of these plugins, you can just choose not to overwrite those versions
    • For the engines plugin to work, add this line to the top of your environment.rb, right after the require of boot: require File.join(File.dirname(__FILE__), '../vendor/plugins/engines/boot')
  3. Copy the migration in /vendor/plugins/savage_beast/db/migrate into your own migration directory (and run it)
  4. Implement in your User model the four methods in plugins/savage_beast/lib/savage_beast/user_init that are marked as "#implement in your user model
  5. Add the line “map.from_plugin :savage_beast” to your routes.rb. Location shouldn’t matter unless you intend to override it.
  6. Add the line “include SavageBeast::UserInit” to your User model. Location shouldn’t matter unless you intend to override it.
  7. Implement versions of the methods in SavageBeast::AuthenticationSystem (located in /plugins/savage_beast/lib) in your application controller if they aren’t already there (note: technically, I believe only “login_required” and “current_user” are necessary, the others give you more functionality). Helpful commenter Adam says that if you have the “helper :all” line in your application controller, be sure to add the “SavageBeast::AuthenticationSystem” line after that.

And off you go! When you visit your_site/forums something should happen. I’ve been creating new forums by visiting /forums/new. There’s probably a hidden admin view somewhere.

I’d like to remove some of these steps during the plugin install process with subsequent releases (is it possible to install a dependent plugin during your plugin install process?), but given that this is my first plugin project (and not a small one at that), I’m just trying to “get it done” before I “get it done beautifully.” I think DHH said somewhere that I should do that.

Implementing Your Own Views and Controllers

The engines plugin makes it eminently easy to mix in your own stuff as you see fit. Just create a new file in your /controllers or /views directories with the same name as the file you want to override in Savage Beast. If you just want to override a particular method in a controller, you can do that piecemeal if you just leave your XController empty except for the method you wanted to override.

If you’re integrating this into an existing site, I’d recommend you start by creating a forums layout page (/app/views/layouts/forums.html.erb). This will give you a taste of how easy it is to selectively override files from the plugin.

Demo

You can check out a (slightly-but-not-too-modified) version of Savage Beast online at Bonanzle. The differences between our version and the version checked into Subversion are 1) addition of topic tagging (users can tag topics to get them removed, etc) 2) recent post list shows posts in unique topics, rather than showing posts from the same topic repeatedly (there’s another blog on here about the SQL I used to do that) and 3) skinning. None of those changes feel intrinsic to what SB is “supposed to do,” which is why they aren’t checked in.

Differences from Savage Beast 1.0

The main difference is that this incorporates about a year’s worth of progress to the Beast source, and it actually takes that code a step further by being Rails 2.0.x compliant.

One thing Jodi seemed pretty excited about in the first Savage Beast was the ability to create forums off of models. Bonanzle doesn’t need that functionality, so I haven’t tested it, but I imagine it will probably work if you follow the steps that did it in the first Savage Beast.

TODO

Would be nice to have some help writing tests. Would also be great to figure out how to install this through the standard “ruby script/plugin install”.

Without Engines?

There are a couple means by which you can use this plugin without using the Engines plugin. I originally had intended to do this, suspecting that Engines would be a performance detriment. Turns out it’s not. But maybe you want to roll without Engines for some other reason.

The most dumb-easy way to get by without Engines would just be to copy the views, helpers, controllers, and models into your own project. Yes, it means having a lot more of all the above in your project, but it’s no worse than if you were coding the plugin from scratch yourself (actually, I’d argue it’s a lot better, since you didn’t have to do the work yourself :) ).

Another way is to uncomment the code at the bottom of Savage Beast’s init.rb. Before I knew about the Engines plugin I created the code in there that simulates Engines without having Engines installed. The caveat is that you won’t get Engines’ ability to selectively override particular methods/views, and you need to copy all your helpers into the SB/lib directory, where they become global (yuck). If anyone out there has cycles to hone this Engines’-less approach, please email me and we can talk about getting those changes into the project.

Conclusion

Comments are most welcome. I’ll be checking in changes to the project as I find bugs and improvements in using it, but this is admittedly something I don’t have a lot of spare time to closely follow (see my other entries on the wonders of entrepreneurship). Hopefully others can contribute patches as they find time. If you like the plugin, feel free to stop by Agile Development and give it a rating so that others can find it in the future.

143 thoughts on “Savage Beast 2.0 – A Rails 2.0 Message Forum Plugin

  1. P.S. Judging by the fact that several thousand people have downloaded SB in its months of existence (at least 50 people visit this blog per day), I’m betting that it is probably online at many Rails sites that use forums.

  2. Hi all. No update for Rails 2.1 ? I’ve a lot of difficulties with routes :(
    undefined local variable or method `users_path’
    or
    undefined local variable or method `new_session_path’
    even my restful seems kaput:
    No route matches “/login” with {:method=>:get}
    :( (((
    if someone has an idea…
    I’m running Rails 2.1.2 & engines 2.1.2

  3. mode autoresponse: It seems that ‘map.from_plugin :savage_beast’ is not working in my route.rb…
    If I take all routes defined in ‘vendor/plugins/savage_beast/routes.rb’ and put it directly in route.rb of my app, it’s working. cool.

  4. @Ravi: The problem you mentioned about Reply to Topic link not working, is because in the layout application.html, “application.js” is wrongly included before “prototype”, “effects” (hence the show/hide/toggle functions weren’t working)

    Bill, please correct the actual plugin code. Loving the Savage Beast! I am about to launch it on my site: http://www.chictini.com

  5. Pingback: mathemagicio.us » Easy-peasy symbolic computation with Ruby

  6. You might get this error after upgrading to Rails 2.2:

    uninitialized constant Rails::Plugin::Dependencies

    You need change savage_beast/init.rb:
    Rails::Plugin::Dependencies

    to

    ActiveSupport::Dependencies

    Zac

  7. I was ALSO having issues with a users_path variable not being found.

    Adding map.resources :users to routes.rb didn’t fix it, but when I moved the map.from_plugin :savage_beast so that it happened before the map.resources :users line, then everything started working.

    –Tyler

  8. Does anyone know a good way to port the data/postings from an existing Beast forum to Savage beast?
    (is it even possible?)

    thanks.

  9. Note: In part 2.1, “Redcloth” should be “RedCloth” – with a capital ‘C’. The gem install could not find gem “Redcloth” otherwise.

    gem install RedCloth

  10. I’m also running into the uninitialized constant ForumsController problem…I do have that line added to environment.rb…feels like repeatedly slamming myself against a brick wall as a rails newbie sometimes!

  11. Hi, nice plugin

    I think

    By the way, I had to do

    gem install RedCloth

    (not gem install Redcloth)

  12. Jirapong’s instructions have moved to http://bananacoding.com/Blog/Savage-Beast-Forum-Installation but the images are missing. I managed to install it on Rails 2.2.0. Some remarks:

    * Don’t overwrite restful_authentication with the copied files from vendor/plugins/aep_beast/tested_plugins

    * In routes.rb, it should be
    map.from_plugin :aep_beast # not :savage_beast

    * For some reason restful_authentication didn’t create a config/initializers/mailer.rb for me – set up your smtp_settings or nobody will be able to register!

    * change YOURSITE and ADMINEMAIL in app/models/user_mailer.rb (hiding stuff like that in some string literal in a view is a real antipattern, those parameters should be defined in an initializer so whoever installs the plugin sees them)

    * And you need to define a users/index action for the “Users” link. Something like
    def index
    @active_users = User.find(:all).select(&:active?)
    end
    and decide who should be allowed to see the list.

  13. I installed everything as instructed above, and when i start server, or infact even when i run rake (for migrations) or generator (for scaffolding) it is breaking and throwing up this error : c:/ruby/lib/ruby/gems/1.8/gems/activesupport-2.1.0/lib/active_support/core_ext/module/aliasing.rb:31:in `alias_method’: undefined method `initialize_schema_information’ for module `ActiveRecord::ConnectionAdapters::SchemaStatements’ (NameError) Any clue why this mite be happening?

  14. Hi Bill,

    I downloaded your Savage Beast to work with my Rails 2.3 project. Here are the changes I needed to make:
    * need a version of engines that’s compatible with the version of Rails, since a lot of code has been moving
    from Engines to Rails (git://github.com/lazyatom/engines.git)
    * the migration should be renamed before copying to the migration directory so it doesn’t conflict (I’m using timestamped migrations)
    * in init.rb, need to change “Dependencies.load_once_paths.delete(path)” to “ActiveSupport::Dependencies.load_once_paths.delete(path)”
    (dependencies are part of ActiveSupport now, according to http://sagarkulkarni.com/2009/03/02/getting-weborb-to-work-with-rails-22-const_missing-uninitia-lized-constant-railsplugindependencies/)
    * (note for Mac users, no RedCloth precompiled version for Mac, so you need XTools installed)
    * according to Rails 2.3 release notes, no need to “Add the line map.from_plugin :savage_beast to your routes.rb” as rails now automatically includes your mappings, but I still needed to add it.
    * I got the error message “Rails::Plugins::RedCloth not found”, even though I had installed RedCloth as a gem. To get around this, I had to add the line “config.gem “RedCloth”" in my environment.rb.
    * got this warning message “/Users/jobsearch/Documents/Rails/19gale/vendor/plugins/white_list_formatted_content/init.rb:5: warning: default `to_a’ will be obsolete”
    * this is because “Object.to_a” will dissapear in Ruby 1.9. Changed to Array(options)
    * got warning “DEPRECATION WARNING: formatted_forum_posts_path() has been deprecated. Please pass format to the standard forum_posts_path method instead.. (called from _run_erb_vendor47plugins47savage_beast47app47views47forums47show46html46erb at vendor/plugins/savage_beast/app/views/forums/show.html.erb:33)”
    * changed “formatted_forum_posts_path(@forum, :rss)” to “forum_posts_path(@forum, :format => :rss)” wherever found
    * got error “undefined method `to_i’ for {:page=>nil}:Hash” on line #25 of forums_controller.rb
    * paginate method is being called improperly, as it uses default arguments, not options.
    * changed “@forum.topics.paginate :page => params[:page]” to “@forum.topics.paginate( params[:page] ? params[:page] : 1 )” and fixed the problem.
    * (note if you pass 0 or nil as the page #, you get an array, not a collection back).
    * same issue (paginate method) for topics_controller, same fix
    * got error “undefined method `email’ for “#”:User”. Your documentation doesn’t mention you need an “email” method for user.
    * got warning “DEPRECATION WARNING: truncate takes an option hash instead of separate length and omission arguments.”
    * changed all instances of truncate(a,b) to truncate(a,:length=>b). Includes 2 instances in white_list_formatted_content/init.rb
    * when I click on “Reply to topic”, nothing happens. There doesn’t appear to be a function ReplyForm.init()
    * plugin javascript was not included. I added an extra “content_for :head” in topics/show.html.erb as I’m not sure if I want this script available for the rest of my application.
    * “\n \n”
    * Fixed typo “Administator” => “Administrator” in topics/show.html.erb (not related to port, but just to let you know…)

    Hope this information is useful,

    Thomas O’Dell

  15. Believe it or not, I actually created a Github project, moved Savage Beast into a project directory with Git, and started making the changes to get it Rails 2.3 compatible. I’m being contracted to make a 2.3-compatible (and fleshed out) version of Bloggity, so I’m going to try to kill two birds with one stone here.

    So this checklist will be extremely helpful in bringing SB in the 2009s. Thanks Thomas!

  16. Actually, William, it would be cool if you contacted me (via email or any-method from my website) — we did some work with our fork of Savage Beast (named it Aep_Beast) to make it Rails 2.1-compliant (and clean up some code ;) ) and I think you could use/merge our fork and start from that point onwards.

  17. Hi Bill, looking forward to a 2.3 compatible Savage Beast. Let me know if/when code is pushed to GitHub. I would love to help out; I think it would be great for a current project I’m working on.

  18. Hey Tomash,

    Thanks for your generous offer! Hopefully you received my email today that I’d like to try to work with you over the long term to merge the two as best we can. For starters, though, I’d just like to get SB working with 2.3 via the changes suggested above. I don’t think this will tkae me more than a couple hours time, after I actually have those couple hours available (have been spending my open source time this week on Bloggity).

    You can watch the developments unfold at
    Savage Beast:
    http://github.com/wbharding/savage-beast/tree/master

    and Bloggity:
    http://github.com/wbharding/bloggity/commits/master

    I’ll make announcements to the blog when they get to the point of being consumable. Since I’ve been contracted to make progress on Bloggity, that’s getting first dibs; I have to be done with that by May 15. SB is going to be pretty easy to at least get to the point its running though, so I’m pretty sure I’ll be able to sneak in its updates within the next couple weeks as well.

  19. I’ve implemented this using the steps above and implemented current_user and login_required.

    I’m seeing the forums index and I can create a new forum. But I don’t see a “new topic” button on the topics index page.

    Ideas?

  20. Also, does anyone have an example of application.rb?

    What’s the actual code I put in application.rb to include the AuthenticationSystem? When it says override, do I write my specific code for those functions in the AuthenticationSystem file or in Application.rb?

  21. I’ve gotten the New Topic button to display, but now when I go to start a new topic, I get this error:

    You have a nil object when you didn’t expect it!
    The error occurred while evaluating nil.display_name

    Line 8: 8:

    This is in my Application.rb:

    def current_user
    @current_user ||= ((session[:user_id] && User.find_by_id(session[:user_id])) || 0)
    end

    I also tried:

    def current_user
    User.find_by_id(session[:user_id])
    end

    Why is “current_user” nil in the New Topic page?

    Thanks

  22. I have gone through all the steps an I am receiving this error when I attempt to start my server:
    /Library/Ruby/Gems/1.8/gems/activesupport-2.2.2/lib/active_support/dependencies.rb:442:in `load_missing_constant’: uninitialized constant SavageBeast::UserInit::Forum (NameError)

    I am using Rails 2.2.2. Any ideas on the SavageBeast::UserInit::Forum error?

  23. Hi Bill – first of all, thanks for SB! By any chance is there a version of savage beast compatible with rails 2.2.2? (eg that has a version of engines compatible with 2.2.2?) I’m running into some of the same problems that Thomas reported, but i think my problems may be the opposite of his, in the sense that at the time he was using 2.3 and SB wasn’t compatible. Now i think SB is compatible with 2.3 but i’m still using 2.2.2, and running into problems (with engine in particular). Ive asked on engine mailing list about a 2.2.2 version but thought i’d ask you if you’ve got a 2.2.2 SB in the archive.

    thanks!
    max

  24. Note the upgrade note at the top of the blog, SB has been updated for Rails 2.2 and 2.3! If you’re using those and have questions, please add them to the other blog post.

  25. Hi Bill,

    I’m trying to integrate the Savage Beast plugin into my site (like everyone else!) The thing is – this plugin assumes that the user-model is named ‘User’. My user-model in my site is named ‘Person’. Is there a quick and clean way to make the plugin recognize that as the user-model?
    I ask this because after all the described configuration activities I get this error:

    Showing vendor/plugins/savage_beast/app/views/forums/index.html.erb where line #14 raised:

    uninitialized constant ActionView::Base::CompiledTemplates::User
    Extracted source (around line #14):

    11:
    12: ‘rss’) %>
    13: ,
    14: , “posts_count > 0″))==1 ? :voice_count : :voices_count, number_with_delimiter(count)] %>
    15:
    16:
    17:

  26. I implemented the admin? method in my application.rb (application controller) but it is not called when forums/index.html.erb is executed.
    I have included “SavageBeast::AuthenticationSystem” after the “helper: all” tag in the file.

    running Rails v 2.0.2
    Ruby 1.8.7

  27. @Arvind
    fixed the “Overriding methods of SavageBeast::AuthenticationSystem” by ACTUALLY overriding them in application_helper.rb !!!
    That’s the ONLY way I could get them to be loaded for the Savage Beast views to see them. Otherwise they kept going back to the SavageBeast::AuthenticationSystem methods.

  28. Hi All,

    I want to update the Savage Beast plugin for my rails 3.0.1
    application’s forum from rails 2.3.8, Is it available for Rails 3.0.1
    version or is there any plugin patch is available to update from rails
    2.3.8 to Rails 3.0.1 ?

    Thanks in Advance,
    Jak.

  29. Good post. I learn one thing tougher on totally different blogs everyday. It’s going to always be stimulating to learn content material from different writers and apply somewhat one thing from their store. I’d desire to make use of some with the content material on my weblog whether or not you don’t mind. Natually I’ll offer you a link in your internet blog. Thanks for sharing.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong> <pre lang="" line="" escaped="">