Иногда нужно использовать валидацию для введенных через форму данных, но при этом эти данные никакого отношения к базе данных не имеют. Например, данные формы обратной связи.
Можно сэмулировать стандартную модель использую такой базовый класс-заглушку:
module ActiveRecord
class Model
def id; nil; end
def new_record?; true; end
def save; nil; end
def save!; nil; end
class << self
def human_name(options = {})
defaults = self_and_descendants_from_active_record.map do |klass|
:"#{klass.name.underscore}"
end
defaults << self.name.humanize
I18n.translate(defaults.shift, {:scope => [:activerecord, :models], :count => 1, :default => defaults}.merge(options))
end
def human_attribute_name(attribute_key_name, options = {})
defaults = self_and_descendants_from_active_record.map do |klass|
:"#{klass.name.underscore}.#{attribute_key_name}"
end
defaults << options[:default] if options[:default]
defaults.flatten!
defaults << attribute_key_name.humanize
options[:count] ||= 1
I18n.translate(defaults.shift, options.merge(:default => defaults, :scope => [:activerecord, :attributes]))
end
def self_and_descendants_from_active_record
klass = self
classes = [klass]
while klass != klass.base_class
classes << klass = klass.superclass
end
classes
rescue
[self]
end
end
def initialize(params = nil)
unless params.nil?
params.each do |k,v|
self.send("#{k}=", v)
end
end
end
include ActiveRecord::Validations
end
end
Класс псевдомодели для формы обратной связи будет выглядить так:
class Message < ActiveRecord::Model
attr_accessor :name
attr_accessor :email
attr_accessor :subject
attr_accessor :body
validates_presence_of :name
validates_length_of :name, :within => 2..16, :allow_blank => true
validates_presence_of :email
validates_length_of :email, :within => 6..32, :allow_blank => true
validates_format_of :email, :with => Authlogic::Regex.email, :allow_blank => true
validates_presence_of :subject
validates_length_of :subject, :within => 2..32, :allow_blank => true
validates_presence_of :body
validates_length_of :body, :within => 5..4096, :allow_blank => true
def send_to(recipient)
# send message to recipient
end
end
Такую псевдомодель можно использовать в шаблонах с хелпером form_for
как обычную. Интернационализация сообщений об ошибках работает так же, как если бы это была обычная модель ActiveRecord::Base.
Пример использования:
class ContactsController < ApplicationController
def new
@message = Message.new
end
def create
@message = Message.new(params[:message])
if @message.valid?
@message.send_to(configatron.contacts.email)
flash[:notice] = "Сообщение успешно отправлено"
redirect_to new_contact_path
else
render :action => "new"
end
end
end