How to simulate typecasting of ActiveRecord in non-AR classes?

Hi,

I have non-ActiveRecord Ruby classes that I use for numerical (and
other) processing as part of an API service.

I seem to recall that AR will cast attributes, say, from a params hash,
into the data type expected for the attribute. That is useful, and I’m
missing that feature in my non-AR classes. Has anyone considered this
challenge in their own work, and, if so, what mechanism (existing
modules or code snippets) would they propose as a way to introduce
casting?

Thanks,

Grar

On 04 Nov 2011, at 15:01, Grary S. wrote:

I have non-ActiveRecord Ruby classes that I use for numerical (and
other) processing as part of an API service.

I seem to recall that AR will cast attributes, say, from a params
hash,
into the data type expected for the attribute. That is useful, and I’m
missing that feature in my non-AR classes. Has anyone considered this
challenge in their own work, and, if so, what mechanism (existing
modules or code snippets) would they propose as a way to introduce
casting?

Something along the lines of TypeCaster module · GitHub (put it
in the lib/ directory and include it in load path if needed) should
work.

Then you just create a custom class, e.g. an ActiveModel class:

class CustomModel
include ActiveModel::Validations
include ActiveModel::Conversion
include ActiveModel::Serializers::JSON
include ActiveModel::Serializers::Xml
extend ActiveModel::Naming

include TypeCaster

field :id, Integer
field :name, String
field :description, String
field :some_integer, Integer

validates_presence_of :id, :name
validate_numericality_of :some_integer

def persisted?
false
end
end

Just doing this off the top of my head, so might be some typos in
there, but you get the point.

I’d use this method so your custom classes at least have some notion
of what to expect, that’s what ActiveRecord also does (using the
database column types).

You can then just pass in a json hash to the constructor:

CustomModel.new(params)

where params is a json hash like {name: “John D.”, id: 123,
description: “Some anonymous man”, some_integer: 5}

Even if for some reason that some_integer would be passed in as a
string, your custom model would still typecast it to an integer, since
your model enforces it to.

Best regards

Peter De Berdt

On 04 Nov 2011, at 16:24, Peter De Berdt wrote:

You can then just pass in a json hash to the constructor:

CustomModel.new(params)

where params is a json hash like {name: “John D.”, id: 123,
description: “Some anonymous man”, some_integer: 5}

I stand corrected, where params is a normal Ruby hash (my weekend has
started, my mind is slowing down ;-))

Best regards

Peter De Berdt

Peter,

Wow, that’s a lot!

One of my reasons for posting was I saw
ActiveModel::Serializers#from_json and I thought, ‘What good is this, if
there is not some other facility to handle non-String attributes?’ It
seems, though, that the functionality you have so generously sketched is
just not available via some overriding of AM modules.

Thanks,

Grar