Ruby PORO quite confuse me sometimes, let talk a look at this example:
class TardisMotoForm
# Include the ActiveModel
include ActiveModel::Model
include ActiveModel::Validations::Callbacks
# Define a custom constant
PASSWORD_FORMAT = /(?=.*\d)(?=.*[a-z])(?=.*[A-Z])/
# Define attr_accessor, so we can expose these attributes to the outside world
# take a look more on attr_reader and attr_accessor
attr_accessor :user, :email, :password, :phone_number, :transfer_type, :params, :taken_email, :params
# Use the validation of model
validate :email_uniqueness
validates :password, presence: true, format: { with: PASSWORD_FORMAT }, length: { in: Devise.password_length }, if: :transfer_by_email?
validates :email, email: { validate_mx: false }
phony_normalize :phone_number
validates :phone_number, phony_plausible: true
# Define a custom method for the outside world can invoke
# For example, in the controller
# if @tardis_moto_form.valid_params?(filtered_fun_params)
# redirect_to somewhere_path
# else
# render :new
# end
def valid_params?(params)
assign_attributes(filter_params(params)) # where the assign_attribute come from?
valid?
end
# In the controller
# if @tardis_moto_form.save(filtered_fun_params, resource) && resource.persisted?
# end
def save(attributes = {}, user = nil)
@user = user # What is the user here? - it will assign to the attr user above
@params = attributes
user.errors.empty?
end
private
# Model validation callback
def transfer_by_email?
transfer_type.to_sym == :email
end
# Model validation call back
def email_uniqueness
return unless User.exists?(email: email)
@taken_email = true
errors.add(:email, I18n.t('activerecord.errors.models.transfer_form.taken_email'))
end
# Sanitize filter params before assign attribute
def filter_params(params)
{
email: params[:email],
password: params[:password],
phone_number: params[:phone_number],
}
end
end
Reference:
Ruby PORO quite confuse me sometimes, let talk a look at this example:
Reference: