On Sunday, November 26, 2017 at 5:38:56 PM UTC-8, Andrew Burleson wrote:
>
> I have a pattern I've used a few times with Sequel where I want to
> represent a model attribute with a Ruby object, even though it makes sense
> to store it as some primitive in the database (string or hash typically).
>
> Here's a contrived example: assume we have a User model with a Role
> attribute, and Role is acting like an enum of sorts. My code might look
> like this:
>
> class Role
> VALUES = %w|guest member admin|
>
>
> def initialize(value)
> raise "Invalid Role" unless VALUES.include?(role)
> @value = value
> end
>
>
> VALUES.each do |val|
> define_method "#{val}?" do
> @value == val
> end
> end
>
>
> def to_s
> @value
> end
> end
>
>
> class User < Sequel::Model
> def role=(input)
> @role = Role.new(input)
> super(@role.to_s)
> end
>
>
> def role
> @role ||= Role.new(super)
> end
> end
>
> Now, this kind of thing seems to work fine, but it's a bit verbose on the
> model side. I've been thinking about writing some class macros to reduce
> the verbosity, but it occurred to me that I might get some input on whether
> or not the above is a good idea or there's a better way to do this before I
> go to that trouble.
>
> My question is just this: is there a better and/or built-in mechanism for
> saying "this column should be cast to and serialized from ____", where in
> my case ____ is some Ruby class.
>
The serialization or composition plugins handle something similar to what
you want, though you would have to create a custom serializer/deserializer
for Role (a pair of procs).
The main difference is that your code has #role returning a deserialized
value but #role= taking serialized input. From a modelling perspective,
this is questionable, you would generally want deserialized input for both
or serialized input for both. If #role returns a Role instance, then
#role= should take a Role instance. The serialization plugin would expect
#role= to take a Role instance, and the composition plugin would expect
that instead of overriding #role and #role=, you would have separate
methods for getting/setting Role instances.
Thanks,
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
Visit this group at https://groups.google.com/group/sequel-talk.
For more options, visit https://groups.google.com/d/optout.