Model:
[code=ruby]class BlogComment < ActiveRecord::Base
(…)
attr_accessor :user_captcha
attr_accessor :captcha
attr_accessor :sub_captcha_1
attr_accessor :sub_captcha_2
def validate
number = match_captcha(user_captcha)
if number.to_i != captcha.to_i
errors.add( captcha, “Wpisana liczba jest niepoprawna.”)
end
end
private
def match_captcha(text)
CAPTCHA_MAP.each do |pair|
return pair[1] if pair[0] == text
end
return -1
end
CAPTCHA_MAP = [
[“zero”, 0],
[“jeden”, 1],
[“dwa”, 2],
[“trzy”, 3],
[“cztery”,4],
[“pięć”, 5],
[“sześć”, 6],
[“siedem”, 7],
[“osiem”, 8],
[“dziewięć”,9],
[“dziesięć”,10],
[“jedenaście”, 11],
[“dwanaście”, 12],
[“trzynaście”, 13],
[“czternaście”, 14],
[“piętnaście”, 15],
[“szesnaście”, 16],
[“siedemnaście”, 17],
[“osiemnaście”, 18],
[“dziewiętnaście”, 19]
]
end[/code]
Controller:
[code=ruby] def new
if !params[:comment].nil?
@comment = @post.comments.build(params[:comment].merge(
{:captcha => nil, :user_captcha => nil}))
end
@sub_captcha_1 = rand( 6 ) + 1
@sub_captcha_2 = rand( 6 ) + 1
end
def create
@comment=@post.comments.build(params[:comment].merge({
:created_on=>Date.today, :captcha => params[:captcha]}))
if @comment.save
flash[:notice] = ‘Twój komentarz został zapisany. Dziękujemy.’
redirect_to blog_post_path(@post)
else
flash[:err] = ‘Twój komentarz nie został zapisany. Wypełnij wymagane pola.’
redirect_to blog_post_path(@post, :comment => params[:comment])
end
end[/code]
View
<% form_for( :comment, @comment, :url=>blog_comments_path(:blog_post_id=>post.id,
:captcha => @sub_captcha_1 + @sub_captcha_2 ), do |f| %>
(...) pola do wpisania komentarza
<%= @sub_captcha_1.to_i %> + <%= @sub_captcha_2.to_i %> =
<%= f.text_field :user_captcha, :size => 10%>
? (Odpowiedź wpisz słownie)
<%=error_message_on "comment", "captcha" -%>
<%= submit_tag "Zapisz komentarz" -%>
<% end -%>
W skrócie: w kontrolerze tworzymy dwa sub kody i w formularzu przekazujemy ich sumę i tekst użytkownika, walidacja następuje w modelu.