Skip to content

Instantly share code, notes, and snippets.

@kizzx2
Created February 6, 2013 14:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save kizzx2/4723038 to your computer and use it in GitHub Desktop.
Save kizzx2/4723038 to your computer and use it in GitHub Desktop.
A clean and elegant approach to partial object validation with Rails + Wicked wizards (store partial object in database)
class Post < ActiveRecord::Base
attr_accessible :body, :price, :title
validates_presence_of :title
validates_length_of :title, minimum: 10
validates_presence_of :body
validates_numericality_of :price, greater_than: 0
end
class PostWizardController < ApplicationController
include Wicked::Wizard
steps '1_title', '2_body', '3_price'
VALIDATIONS = {
'1_title' => [:title],
'2_body' => [:title, :body],
'3_price' => [:title, :body, :price],
}.freeze
# Here PartialPost is a private property of this controller not shared in any
# other part of the code so we make it a nested class.
class PartialPost < Post
attr_accessor :step
attr_accessor :session
def self.model_name
Post.model_name
end
def save
# Trigger ActiveRecord's validation
rv = super(validate: false)
if rv && self.step == VALIDATIONS.keys.last
self.partial = false
rv = super
session.delete(:post_wizard) if rv
rv
else
self.valid?
(self.errors.messages.keys - VALIDATIONS[self.step]).each do |k|
self.errors.messages.delete(k)
end
# Insert complicated custom validation manipulation here
self.errors.empty?
end
end
end
def index
post = Post.new
post.save(validate: false)
session[:post_wizard] ||= {}
session[:post_wizard][:post_id] = post.id
redirect_to wizard_path(steps.first)
end
def show
if session[:post_wizard].try(:[], :post_id).present?
@post = PartialPost.find(session[:post_wizard][:post_id])
end
render_wizard
end
def update
@post = PartialPost.find(session[:post_wizard][:post_id])
@post.attributes = params[:post]
@post.step = step
@post.session = session
render_wizard(@post)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment