Maybe it's because I've been reading about DCI lately, but I think this example could go even further in moving business logic out of the AR model.
class GuestbookLibrarian
def initialize(rate_limiter, tweeter, spam_checker)
@rate_limiter = rate_limiter
@tweeter = tweeter
@spam_checker = spam_checker
end
def add_entry(name, msg, ip_addr)
raise PostingTooSpammy if @spam_checker.is_spammy? msg
raise PostingTooFast if @rate_limiter.exceeded? ip_addr
entry = GuestbookEntry.create(:name => name,
:msg => msg,
:ip_addr => ip_addr)
@rate_limiter.record(ip_addr)
@tweeter.tweet_new_guestbook_post(name, msg)
entry
end
end
class GuestbookController < ApplicationController
... SNIP ...
rescue_from PostingTooSpammy, :with => :some_spam_handler
rescue_from PostingTooFast, :with => :some_other_spam_handler
def create
#maybe these should be globals in an initializer somewhere if we
#use them elsewhere? or in a :before_filter at least :)
rate_limiter = UserContentRateLimiter.new
tweeter = Tweeter.new
spam_checker = UserContentSpamChecker.new
librarian = GuestbookLibrarian.new(rate_limiter, tweeter, spam_checker)
entry = librarian.add_entry(params[:name], params[:msg], params[:ip_addr])
redirect_to entry, :notice => "Thanks for posting"
end
end
Something like that? Too Java-y? Feedback appreciated :)
I think in general models can handle their own validation (especially if you use AR), but I guess the difference is that these validations hit external "services", instead of like a :max_length validation.
I agree on the first pass comment - I imagine that the user
stories went something like:
* v1 - An anon user can post to the guestbook
* v2 - Guestbook comments are checked for spam
* v3 - Post guestbook comments to twitter for Web 2.0-ness
Not too Java-y, but too "DataMapper-y" for most Rails devs, I think (the pattern, not the ORM - the Ruby DataMapper ORM implements the ActiveRecord pattern, though DataMapper 2 actually finally will implement DataMapper)