Created
February 26, 2012 15:54
-
-
Save fgrehm/1917450 to your computer and use it in GitHub Desktop.
Virtus custom attribute using coercion lib
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'json' | |
Virtus::Coercion::String.class_eval do | |
def self.to_hash(value) | |
JSON.parse(value) | |
end | |
end | |
module MyApp | |
module Attributes | |
class JSON < Virtus::Attribute::Object | |
primitive ::Hash | |
coercion_method :to_hash | |
end | |
end | |
class User | |
include Virtus | |
attribute :info, Attributes::JSON | |
end | |
end | |
@user = MyApp::User.new(:info => '{"email":"john@domain.com"}') | |
@user.info.class # => Hash | |
@user.info = {'new' => 'info'} # => Doesn't throw an exception :) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
How about something like this:
The implementation of this might work, but I'm having trouble with the proposed name of your Attribute class. I mean, if it really was a JSON field, then I would assume it was a JSON string, not an arbitrary ruby Object (or a Hash if you decide to restrict it that way). The naming is what threw me off above, and it still sticks out as something I might consider changing if I were modelling this.
With Virtus you're more focused around what the type of the attribute in the instance should be, not necessarily the serialization method used for the input. Sure, there are common coercions where it's unambiguous, like coercing
"1"
into1
for an Integer attribute, but there's no way to say "this is a Hash, but it could come in as a Hash or as a String in JSON encoding".I'm almost wondering if this is the kind of thing a form plugin would handle, like @emmanuel's conformitas. If I was writing a pure ruby object without Virtus or another framework I would almost certainly not handle deserialization inside the object, but I would have something that knows how to take the input and then create the object from it. It's often in bloated frameworks where the model handles this (and usually dozens of other responsibilities), but I'm not sure the core objects should know about that kind of thing.