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:
- The Savage Beast 2.0 plugin. Go to your application root directory and:
svn exporthttp://savage-beast-2.googlecode.com/svn/trunk/vendor/plugins/savage_beast - 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‘)
- Redcloth:
- Copy the migration in /vendor/plugins/savage_beast/db/migrate into your own migration directory (and run it)
- 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“ - Add the line “
map.from_plugin :savage_beast” to your routes.rb. Location shouldn’t matter unless you intend to override it. - Add the line “
include SavageBeast::UserInit” to your User model. Location shouldn’t matter unless you intend to override it. - 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.

nevermind…i screwed up something…
great plugin btw..
@Sonia@: The original Savage Beast is the answer for Rails 1.x’ers: http://nnovation.ca/blog/
Hi Bill,
Just want to report a bug,
When I try to delete topic as admin, I get
NoMethodError (undefined method `update_posts_count’ for #):
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/attribute_methods.rb:205:in `method_missing’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/core_ext/symbol.rb:11:in `__send__’
/usr/local/lib/ruby/gems/1.8/gems/activesupport-2.0.2/lib/active_support/core_ext/symbol.rb:11:in `to_proc’
/vendor/plugins/savage_beast/app/models/topic.rb:85:in `each’
/vendor/plugins/savage_beast/app/models/topic.rb:85:in `update_forum_counter_cache’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:307:in `send’
/usr/local/lib/ruby/gems/1.8/gems/activerecord-2.0.2/lib/active_record/callbacks.rb:307:in `callback’
Hi,
Thanks for this plugin.
I am integrating beast into an existing site.
When I perform /forums, I get the following error
undefined method fond_ordered for …
My trace on the server shows me that engine is not able to loacate forums_controller, forums_helper
I am able to see the forum/new page but run into problems when I try to create a new pose.
Is my error due to some missing configuration to load beast plugin corrrectly.
Thanks,
-Ram
“undefined method fond_ordered for …”
should read
“undefined method find_ordered for …”
I see that this method is defined in the SB plugin.
We are using the will_paginate gem on a project that has Savage Beast installed. (This has recently been updated from a plugin to a gem.)
On 04/07/08, the developer changed the “page_count” method name to “total_pages” that is hanging off the model. Savage Beast uses “page_count” which was “giving me a undefined method page_count” error in quite a few places. I had to do a find/replace to change these all to total_pages and all appears to be working now.
Hi,
I looking for oryginal Savage Beast for rails 1.x, but http://nnovation.ca/blog/ seems to be not runing.
Can i download it from somewhere?
Krzysiek
@Ryan@: Thanks for the report. I’ll look into that next time I’m updating the plugin. Let me know if you fix it yourself and could give me specific code to add to the project.
@Ram@: I think that is a default Rails route? Never seen that particular error. Maybe someone else who has will chime in.
@Jim@: Thanks for the tip. I’m sure others using the gem version of will_paginate will appreciate this.
@Krzysztof@: I don’t have the original SB, but I know that nnovation.ca/blog has a history of being up and down (was down for a couple days when I first tried to grab it). Keep at it, email Jodi Showers if you can find his address. And maybe bug him to put the project on Google or RubyForge…
hi bill,
I think the problem is that it’s trying to update the post count of all the user in that topic, but the User model doesn’t have that function update_posts_count anymore. I don’t need savage beast to track user post count, so I simply commented out that line
#@voices.each &:update_posts_count if @voices
and it works perfectly now
@ryan@: Thanks buddy! I’ve updated the source with your change.
I also was experiencing the oddness of seeing Dutch languge activerecord errors… it was because of an incomplete removal of the GetText gem translations previously being done by savage_beast. Nothing to do with Gibberish plugin, as a previous response had claimed.
Commenting these two lines out from the init.rb makes everything good again:
# require ‘gettext/rails’
# GetText.locale = “nl” # Change this to your preference language
Thanks for working on getting savage_beast up to speed on Rails 2.0!
Hi,
where should i set value of variables users_path and forums_paht, any maybe other?
thank you in advance
Krzysiek
Is there a Google Groups available for this plugin? It would act better as a place for support.
My question is, how do I delete a forum once created?
I see the controller function is there, but it doesn’t seem to be linked from anywhere in views.
Zac, I believe there is a Google Groups-like thing in the Google Code project, but I hardly ever visit it. Others might.
In regards to your question, I know that an edit/delete link pop up when you mouse over a topic, but I believe that the Beast thinking is that Forums are generally static, whereas topics within Forums come and go (e.g., are created and deleted frequently). Thus, whatever link there might be to delete a forum is probably well hidden within the standard Beast views.
But I don’t know for sure, because in practice, and certainly with us, most apps overwrite the standard Beast views before they get to production, so once those views have been replaced by your own (which is as easy as just creating the overriding view partials in your app/views/* directory), then the links that are provided to add/edit/delete are totally up to you.
Hi do you have a solution to prevent simple users from creating forums or editing/deleting other user’s posts?
Thanks.
move from google groups to github? can spur more open developers to join in
@tito: Access to edit or delete posts is dictated by the admin? method in SB, as I recall (without the code in front of me right now). If not admin, there’s some other similar method that dictates that. It was one of those things that “Just worked” for me, so hopefully it will with you too.
@wilson: A good idea. I’ll take another look in the next few days to see if Git for Windows has reached the point of being decent yet, and if so, hopefully move over SB in the near future.
We just spent some time making savage beast compatible with Rails 2.1. Since we couldn’t find any information out there while we were sorting through the errors, I’ll post our fixes here in case anyone else encounters similar issues.
1. All the named routes in savage_beast started throwing exceptions. We found that an update to RESTful routing started to automatically prefix nested resources. SB doesn’t follow this convention. To fix, we had to pass an extra “:name_prefix => nil” to our nested routes in SB’s routes.rb, like so:
map.resources :forums do |forum|
forum.resources :topics, :name_prefix => nil
forum.resources :topics do |topic|
topic.resources :posts, :name_prefix => nil
topic.resource :monitorship, :controller => :monitorships, :name_prefix => nil
end
end
2. We’ve been using the will_paginate gem and of course, this also caused incompatibilities with SB, which was depending on an older version of will_paginate. To fix, we had to change all instances of @post_pages or @topic_pages to @posts and @topics, respectively. Also, the method page_count had to be replaced with the new total_pages. Lastly, the method “pagination_links” had to be changed to “will_paginate”, with the appropriate collection as the param.
3. Voices. I love the “voices” feature of SB, but that also stopped working. Two easy changes here: in the views, just change @voices to @topic.voices. When SB needs to update the forum counter cache, it tries to call a method “update_posts_count” on a “voice”. For us, that’s a user, so I added this to our user.rb:
def update_posts_count
self.posts_count = Post.find(:all, :conditions => {:user_id => self.id}).size
self.save
end
4. Finally, we ran into a strange 502 Bad Gateway issue when deployed into our nginx/mongrel environment. It only happened with IE when creating a new post. Turns out the Post#create redirect passes an :anchor param, which generates an HTML anchor (#) symbol in the URL. This was causing problems with nginx in IE only. The simple fix was to simply remove the :anchor param, since all it was doing was scrolling the user to the new post.
And now we’re rolling with SB on Rails 2.1…
Chris — you’re a saint!
We’ll probably be moving to 2.1 in the next couple months, I’ll definitely refer to your guide when we make the jump, and check in the changes at that time.
Do you think these changes will be backward compatible, such that we could update the main code base to work with Rails 2.0.x and 2.1?
Bill - I don’t see anything that would break with Rails 2.0.x The :name_prefix param should just be ignored in older versions of RESTful routing. Good luck!
i get the following error when i tried to do the migration.I am using rails 2.1.Can you please provide me the steps for getting out of this problem. I am struck here.I googled but it was of no use
undefined method initialize_schema_information’ for module `ActiveRecord::ConnectionAdapters::SchemaStatements’
i commented the following line in migrations.rb and was able to work to some extent.But i am facing problems in will paginate plugin’s init. can you provide me a permanent solution?
def self.included(base) # :nodoc:
# base.class_eval { alias_method_chain :initialize_schema_information, :engine_additions }
end
@prabha: I’m not on Rails 2.1 yet, but hopefully Chris or another user that is can speak to your problem. Bonanzle probably won’t be moving to 2.1 for another month or two. There’s a lot to be done.
If anyone who gets SB working with Rails 2.1 and would like commit access to the SB repository, I’m game for that, as long as it remains 2.0.x compatible.
prabha - haven’t seen that before. But if you’re having issues with the will_paginate plugin, maybe the easiest thing to do is to upgrade to the will_paginate gem (sudo gem install will_paginate), and then follow the instructions in my earlier post.
bill - I may be adventurous enough to give it a shot. But I’m working from Beijing at the moment and don’t have too much spare time. Have you also considered hosting it on github? That may open up contributions a little.
I just installed to a Rails 2.1 project. The migration was not an issue. No idea why @prabha would be having issues with that.
However, there was an issue with the “will_paginate” plugin. It was given a “stack level too deep” error when accessing the Topic view.
This issue was an issue with an old “will_paginate” and Rails 2.1.
http://err.lighthouseapp.com/projects/466/tickets/223
Updating to the latest gem and referencing the gem via the environment.rb file corrected the issue.
Unfortunately, I am now getting a “undefined method `page_count’” error.
So it turns out I commented on this “page_count” error on April 15th. I thought it looked familiar.
To correct the issue, do a global find and replace of “page_count” to “total_pages”.
@prabha: I have had the same problem today with rails 2.1, and you can solve it updating the engines plugin.
Instead of use the version in tested_plugin, download the last version.
Hey, I was wondering if anybody had a nice method or direction for overloading the posts class. I am using a blog and I want to use this for a forum plugin, but since savage beast and my blog use the posts class it causes issues. Does anybody have some suggestion?
thanks lot Diego
Hi,
I am getting the following error when am trying to svn export :
Error: REPORT request failed on ‘/svn/!svn/bc/9/trunk/vendor/plugins/savage_beast’
Error: ‘/svn/!svn/bc/9/trunk/vendor/plugins/savage_beast’ path not found
Could someone please suggest any solution or alternate way to get the plugin installed?
Thanks,
Disha.
I get a bunch of information added to my server after implementing forums using savage beast.Is there a way to cut that off? Can anybody help me?
@Disha: What address are you trying the export? The one you’re listing there appears to be different than the http://savage-beast-2.googlecode.com/svn/trunk/ address at which the plugin exists.
@Prabha: You’re probably observing the output of the Engines plugin. On my install, I commented out most of the debug info given by the Engines plugin by going into the Engines plugin and commenting the line that was doing most of the blabbering (don’t remember which one it was anymore, but do a find all for whatever the text you’re seeing is).
Hey Bill - thanks for working on this plugin, ever since I first discovered Beast I’ve wanted to add it to an existing site, rather than having to create a new one…
I’m trying to use SB without Engines. You mention above that the easiest way would be to just copy the controllers/helpers/models/views into my own app, which I’ve done. Of course I immediately get some errors about no `admin?` method in forums_controller.rb The only place I see a non-model `admin?` method is in /lib/savage_east/authentication_system.rb There’s a comment at the top that says “override in your app controller” Override what? Should I copy all of those methods into application_controller.rb and then uncomment the bodies of the methods?
/lib/savage_beast/user_init.rb mentions implementing a few of the methods in my own user model (there are specific comments above `admin?` and `display_name`) and then everything below the `ClassMethods` module…if those are really class methods, should I actually copy them into the model with `self.` in front? Should I just copy everything, ignoring the `base.extend` and module definitions, of course.
Is there anything in /init.rb that I need to worry about?
Should I just shut up and use Engines like you intended?
@Rob: Heh, Engines isn’t exactly the daintiest plugin… at all… so I can understand the initial aversion to it, I certainly felt the same way, though I have since come to love it and use it for many other subsystems in my app (like our feedback and blog systems). But that isn’t really your question.
The “override in your app controller” means that, for each method at which you see that, you should create a method in your application controller that implements that functionality in a way consistent with how you define an “admin” (or whatever) user in your application.
Same with the user model. Since everyone might have a different way that they define the display_name for the user, it’s intended that your user model will implement all of the methods that SB says “implement in your own X.”
You shouldn’t have to worry about anything in init.rb, you’ll just need to make sure that you get all the routes into your routes.rb from the SB routes.
Hope that clarifies things a bit.
Thanks Bill
Hi Bill,
just wanted to ask if there is an easier way to style the forums without having to explicitly state in the controller that the layout to be used should be forums.rhtml.erb? I tried overriding the file as you said(by creatign a forums.rhtml.erb file in my layouts folder) and it worked fine…for the index. when i clicked on a post, it proceeded to use the application default layout.
Also, what about shared partials? I am planning to clean up my application or forum layout by dividing the sections into partials, but when i tried making a /shared/ folder for my partials in my app/views/layout folder, savage beast still keeps looking for those shared partials in its own views/layout folder.
thanks!
my friend gave me a good suggestion for the shared partial problem: just make an empty “shared” folder in savage_beast\app\views and if you are using the engines plugin, it will “overwrite” the shared folder with what you have in your app’s shared folder.
the only remaining problem for me is that the topics controller and the post controller is loading the application.rhtml.erb instead of the forum controller. is this really the case by default?(and thus i have to override those controllers to force them to load the forums layout?) thanks again in advance!
…just found out about savage beast.
fyi, if you’re getting this error message reported by @prabha on rails 2.1:
undefined method initialize_schema_information’ for module `ActiveRecord::ConnectionAdapters::SchemaStatements’
you can fix this by not using the engines plugin in the tested_plugins and instead getting the latest:
cd vendor/plugins
git clone git://github.com/lazyatom/engines.git
git checkout 2.1.0
cheers,
tom
how use it in rails 2.1.0
How exactly do you do step 4. Can someone please explain how to do this as well as an example?
Thanks so much for the great work. Just got it up and running in Rails 2.1.1 and mostly just had trouble with plugins, like “page_count” method name to “total_pages” for will_paginate. Your savage_beast plugin will show up in the wild at the LegalTorrents.com website in a few days.
I’m curious if the plugin will track altered_beast. True to technoweenie’s form, beast-2.0 is not called beast-2.0, but altered_beast: http://github.com/courtenay/altered_beast/tree/master
It would be pretty cool if savage_beast was an actual fork at github of altered_beast…
Thanks again for making savage best 2.0…
*Austin Web Developer, this is one possible way to do step 4:
class AddAdminToUsers false
end
def self.down
remove_column :users, :admin
end
end
——— user.rb —————-
def display_name
if current_user.login.blank?
current_user.name
else
current_user.login
end
end
def self.currently_online
User.find(:all, :conditions => ["last_seen_at > ?", Time.now.utc-5.minutes])
end
def self.build_search_conditions(query)
query && ['LOWER(login) LIKE :q', {:q => "%#{query}%"}]
query
end
*Austin Web Developer, this is one possible way to do step 4:
**repost, the last code got munched some how…lets try again:
{{{
class AddAdminToUsers false
end
def self.down
remove_column :users, :admin
end
end
——— user.rb —————-
def display_name
if current_user.login.blank?
current_user.name
else
current_user.login
end
end
def self.currently_online
User.find(:all, :conditions => ["last_seen_at > ?", Time.now.utc-5.minutes])
end
def self.build_search_conditions(query)
query && ['LOWER(login) LIKE :q', {:q => "%#{query}%"}]
end
}}}
My bad:
1) The migration above is still being eaten cause I don’t know how to post code to wordpress. But it simply adds an example admin boolean to users.
2) I misspoke, altered_beast isn’t the official fork of beast…I just got confused as I saw technoweenie’s commits on altered_beast. I did notice though altered_beast has movement and technoweenie also has his own fork of altered_beast on github…
ok, back to adding Rick’s viking fork to savage_beast for Spam filtering: http://github.com/technoweenie/viking/tree/master/lib
so I just copied the following and placed it in my user.rb
def display_name
if current_user.login.blank?
current_user.name
else
current_user.login
end
end
def self.currently_online
User.find(:all, :conditions => [”last_seen_at > ?”, Time.now.utc-5.minutes])
end
def self.build_search_conditions(query)
query && [’LOWER(login) LIKE :q’, {:q => “%#{query}%”}]
end
is that all I need to do? I’ll keep moving forward to see if this works.
I am trying to add this to substruct and I pasted the map.from_plugin :savage_beast and I get this error:
/Users/nathan/Sites/projects/ror/1stmarine/vendor/plugins/savage_beast/init.rb:30:in `from_plugin’: undefined local variable or method `map’ for # (NameError)
Hi
I have problem with authenticated system.
I have User model and i have already added authenticated(acts_as_authenticated)plugin for my application.
included AuthenticatedSystem in my application controller.
now, I added savage beast, its working nice.
But if i clicked on Create new Forum,its goes to login page ,
another one is users_path undefined method, and current_user is nil
how to fix those problems with authenticated system.
i didn’t do any changes in savage beast application controller and my application controller
only i added 4 methods to user Model.
how to connect my application with forum.
please help me.
thanks.
Hi,
I am facing new issues with above issues
i cant give a reply for the topic.
if i click on Reply to Topic link,it is not going any where.
how to give reply for the topic?
thanks,
ravi.
I encountered problems with engines when my rails version is on freeze. Could someone enlighten me about this issue? The engines is fine though when rails is not freeze.
Hey Ravi,
I think the reply uses Javascript and RJS… tho I haven’t heard any specific issues with it before. Be sure to post it when you figure out what your problem is.
Is there a live sample of Savage Beast 2.0 anywhere?