store_model
store_model copied to clipboard
Adding before_validation and and after_validation hooks
First of all, StoreModel is awesome and we've been using it more and more in my teams project. We've been using it mostly for config type of data but I'm experimenting with using it for polymorphic records stored on a ActiveRecord model. One thing I think would be helpful (but maybe out of scope of this gem) is implementing before_validation
and and after_validation
hooks.
This could be useful in a number of ways. We could use before_validation to auto set values of fields. E.g. if we want to set randomly generated token as a unique identifier.
class FooStoreModel
include StoreModel::Model
attribute :token, :string
before_validation :set_token, on: :create
private
def set_token
token = SecureRandom.uuid
end
end
Another way this could be useful is for replicating STI type of inheritance. The polymorphic typing is awesome and I think it should conform to the Rails way of polymorphic STI (using a type variable).
class AbstractStoreModel
include StoreModel::Model
attribute :type, :string
before_validation :set_type, on: :create
private
def set_type
type= self.class.name
end
end
class FooStoreModel < AbstractStoreModel
end
class BarStoreModel < AbstractStoreModel
attribute :value, :string
end
class FooRecord < ActiveRecord::Base
StoreModelsType = StoreModel.one_of do |json|
case json['type']
when 'FooStoreModel'
FooStoreModel
when 'BarStoreModel'
BarStoreModel
else
raise InvalidTypeError
end
end
attribute :data, StoreModelsType.to_array_type
end
This would allow something like
record = FooRecord.create!
record.data << BarStoreModel.new(value: 'baz')
record.save
which would auto cast and infer types
Hi @arushs, thanks for the great idea! I guess it will be a bit tricky, since before_validation
is defined inside ActiveRecord::Callbacks module, and we do not need all these callbacks.
I think you can include ActiveModel::Validations::Callbacks
https://api.rubyonrails.org/classes/ActiveModel/Validations/Callbacks.html and it should work correctly