9
Form objects done right / / Szymon Fiedler @fidelski @arkency

Form objects done right

Embed Size (px)

Citation preview

Page 1: Form objects done right

Form objectsdone right

/ / Szymon Fiedler @fidelski @arkency

Page 2: Form objects done right

Form #1 Class Signup include ActiveModel::Model attr_reader :company, :user

attr_accessor( :name, :company_name, :email ) validates :company_name, presence: true validates :email, presence: true, email: true validates :name, presence: true validate :email_uniquenes def save if valid? persist! true else false end end

def persisted? false end private

def email_uniqueness errors.add(:email, "Email already used dude") if User.where(email: email).exists? end def persist!

Page 3: Form objects done right

Form #2 class Signup include Virtus.model extend ActiveModel::Naming include ActiveModel::Conversion include ActiveModel::Validations attr_reader :user attr_reader :company attribute :name, String attribute :company_name, String attribute :email, String validates :company_name, presence: true validates :email, presence: true, email: true validates :name, presence: true validate :email_uniquenes def persisted? false end def save if valid? persist! true else false end end private def email_uniqueness errors.add(:email, "Email already used dude") if User.where(email: email).exists?

Page 4: Form objects done right

What's wrong with theseexamples?

Is the persistence aresponsibility of the form object?Nope, it is not

Page 5: Form objects done right

Form #3 class Signup ValidationError = Class.new(StandardError) include Virtus.model include ActiveModel::Validations attribute :name, String attribute :company_name, String attribute :email, String validates :company_name, presence: true validates :email, presence: true, email: true validates :name, presence: true def persisted? false end

def validate! raise ValidationError, errors unless valid? end end

Page 6: Form objects done right

Let's use service class SignupService

def call(form_object) form_object.validate!

if User.where(email: form_object.email).exists? form_object.errors.add(:email, "email already taken") end company = Company.create!(name: company_name) User.create!(name: form_object.name, email: form_object.email, company: company)

form_object rescue from_object.class::ValidationError form_object # we have errors here rescue ActiveRecord::RecordInvalid => e # add additional errors to form object end end

Page 7: Form objects done right

Controller class FancyController < ApplicationController def new @signup = Signup.new end def create form = Signup.new(params[:signup]) @signup = SignupService.new.call(form) end end

Page 8: Form objects done right

hawkins.io

Page 9: Form objects done right

Thanks