Skip to content

Instantly share code, notes, and snippets.

@elithecho
Last active January 29, 2019 10:40
Show Gist options
  • Save elithecho/5583ab009b97b5862fb5311db1932138 to your computer and use it in GitHub Desktop.
Save elithecho/5583ab009b97b5862fb5311db1932138 to your computer and use it in GitHub Desktop.
Profile Form explained
class ProfileForm
# Make ProfileForm acts like a model
include ActiveModel::Model
include ActiveModel::Validations
attr_accessor :user, :profile
# This is shorthand for
# def user_attributes=(attribute)
# user.attributes = attributes
# end
#
# When calling super in initialize, this auto assigns
# params[:user_attributes] to self.user
# Thus, you are able to use the same nested form syntax in your views
# https://guides.rubyonrails.org/form_helpers.html#nested-forms
delegate :attributes=, to: :user, prefix: true
delegate :attributes=, to: :profile, prefix: true
validate :profile_is_complete
def initialize(user, params={})
@user = user
@profile = user.profile || new_user_profile
# Calling super params utilizes ActiveModel
# thus self assigning attributes to users
super(params)
end
def save
# early return form validation checks for errors
# in the form and return false to avoid the saving process
return false unless valid?
# Wrap save in a transaction
# Use `Model#save!` with a bang to ensure an error
# is raised to rollback thus avoiding partial save.
ActiveRecord::Base.transaction do
@user.save!
@profile.save!
end
# Once saving is successful, you may perform extra steps like
# sending emails, nofifying admins
AdminNofitication.new(message: "A user created a new profile!").call
UserMailer.profile_creation(@user, @profile).deliver_later
# Always return true when successful to
# notify controller to perform success action
true
rescue ActiveRecord::RecordInvalid
false
end
private
# Setup a new profile
def new_user_profile
@user.build_profile.tap do |profile|
profile.attributes = {
# setup default profile attributes
}
end
end
def profile_is_complete
# Perform custom validation
@profile.errors.add(:le_attribute, "You forgot to do this") if @profile.le_attributes.has_something_wrong
# Or use context/dry-validation
# https://guides.rubyonrails.org/active_record_validations.html#on
@profile.valid?(:complete)
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment